Documentation
¶
Overview ¶
Package skillinject installs the Pilot Protocol skill into the well-known directories of agent tools (Claude Code, OpenClaw, PicoClaw, OpenHands, Hermes, …). The configuration — what to inject, where, and what marker content to upsert into each tool's heartbeat file — is fetched at runtime from the pilot-skills repository on GitHub. There is no embedded fallback: a tick that cannot reach the network is logged and skipped; the next tick retries.
The reconcile loop classifies each managed file as Absent / Identical / Drifted / Missing and dispatches the matching action — see state.go.
Index ¶
- Constants
- func IsEnabled(home string) bool
- func ParseFileMode(s string) os.FileMode
- func Run(ctx context.Context, cfg Config)
- func SetEnabled(home string, enabled bool) error
- type Action
- type Config
- type EnabledFlag
- type FileKind
- type Manifest
- type ManifestHelper
- type ManifestTool
- type Outcome
- type Report
- type State
Constants ¶
const DefaultInterval = 15 * time.Minute
DefaultInterval is how often the daemon re-runs the scan/reconcile pass after the initial startup tick.
const DefaultManifestURL = "https://raw.githubusercontent.com/TeoSlayer/pilot-skills/main/inject-manifest.json"
DefaultManifestURL is the canonical raw GitHub URL for the inject manifest. Overridable via Config.ManifestURL (test hook).
const DefaultRepoBaseURL = "https://raw.githubusercontent.com/TeoSlayer/pilot-skills/main/"
DefaultRepoBaseURL is the prefix used to fetch any path the manifest references (skills/<name>/SKILL.md, heartbeats/<tool>.md). Overridable via Config.RepoBaseURL.
Variables ¶
This section is empty.
Functions ¶
func IsEnabled ¶
IsEnabled returns whether skill injection is on. Defaults to TRUE (opt-out, not opt-in) when the flag isn't present, so fresh installs get the feature without any extra step.
func ParseFileMode ¶
ParseFileMode parses an octal mode string like "0755". Empty input returns the default 0o755 (executable). Invalid input returns 0o755 with no error so a malformed manifest doesn't break the tick.
func Run ¶
Run blocks running scan/reconcile ticks until ctx is cancelled. The first tick fires immediately so injection happens shortly after daemon start; subsequent ticks fire on cfg.Interval.
func SetEnabled ¶
SetEnabled persists the opt-out flag. Reads the existing config (if any), updates only the skill_inject key, writes back atomically.
Types ¶
type Action ¶
type Action string
Action is what the reconcile loop chose to do in response to a State.
type Config ¶
type Config struct {
// Home overrides the user home dir (test hook).
Home string
// Interval between scan ticks after the initial startup tick.
Interval time.Duration
// ManifestURL overrides the canonical raw GitHub URL for inject-manifest.json.
ManifestURL string
// RepoBaseURL overrides the prefix used to resolve relative paths in
// the manifest (skills/<name>/SKILL.md, heartbeats/<tool>.md).
RepoBaseURL string
// HTTPClient overrides the HTTP client used for fetching.
HTTPClient *http.Client
}
Config tunes the injector. Zero values use sensible defaults.
type EnabledFlag ¶
type EnabledFlag struct {
Enabled bool `json:"enabled"`
}
EnabledFlag describes the persisted opt-out state. Stored at ~/.pilot/config.json under "skill_inject" → {"enabled": bool}.
type FileKind ¶
type FileKind string
FileKind names which of a target's two files an Outcome is about.
type Manifest ¶
type Manifest struct {
Version int `json:"version"`
Entrypoint string `json:"entrypoint"`
Description string `json:"description,omitempty"`
Tools []ManifestTool `json:"tools"`
Helpers []ManifestHelper `json:"helpers,omitempty"`
}
Manifest mirrors inject-manifest.json. Field tags match the upstream schema. Unknown fields are ignored (forward-compat with new tool fields).
type ManifestHelper ¶
type ManifestHelper struct {
Name string `json:"name"`
// Src is a repo-relative path fetched via fetchRepoFile, e.g.
// "workflow-injection/pilot-ask".
Src string `json:"src"`
// Dst is the absolute install target. Supports ~/ expansion, e.g.
// "~/.pilot/bin/pilot-ask".
Dst string `json:"dst"`
// Mode is the file mode in octal string form, e.g. "0755". Empty
// defaults to 0755 (helpers are executables).
Mode string `json:"mode,omitempty"`
}
ManifestHelper is one helper script the daemon installs at a well-known path so any AI tool on the host can invoke it. Used to ship pilot-ask (the directory + specialist round-trip wrapper).
Helpers are tool-agnostic — they live under ~/.pilot/bin/ and are referenced by every tool's heartbeat directive.
type ManifestTool ¶
type ManifestTool struct {
Name string `json:"name"`
RootDir string `json:"rootDir"`
SkillsDir string `json:"skillsDir"`
HeartbeatPath string `json:"heartbeatPath,omitempty"`
HeartbeatTemplate string `json:"heartbeatTemplate,omitempty"`
SkillNaming string `json:"skillNaming,omitempty"` // "" = "directory" (default), "flat" = single-file
SelfHeartbeat bool `json:"selfHeartbeat,omitempty"`
}
ManifestTool is one tool target row.
type Outcome ¶
type Outcome struct {
Tool string `json:"tool"`
Kind FileKind `json:"kind"`
Path string `json:"path"`
State State `json:"state"`
Action Action `json:"action"`
Hash string `json:"hash,omitempty"`
Err string `json:"err,omitempty"`
}
Outcome records one reconcile decision.
type Report ¶
type Report struct {
At time.Time `json:"at"`
Outcomes []Outcome `json:"outcomes"`
Skipped []string `json:"skipped,omitempty"`
// Disabled is true if the tick was a no-op because the user has
// `pilotctl skills disable`'d injection.
Disabled bool `json:"disabled,omitempty"`
}
Report is the result of one Tick.
func Tick ¶
Tick performs one scan + reconcile pass and returns a Report. Network failures abort the tick and return an error — there is no embedded fallback. Exposed for tests, one-shot use, and `pilotctl skills check`.
If the user has disabled skill injection via `pilotctl skills disable` (persisted in ~/.pilot/config.json), Tick returns an empty report without touching disk or the network.