Documentation
¶
Overview ¶
Package skills is the catalogue of agent skills that ship inside the seamark binary. It reads the embedded skills/ tree, parses the SKILL.md frontmatter, and owns the marker that tells the installer which directories seamark may refresh. init, doctor, and status all go through this package, so the marker rule exists once.
Index ¶
- Constants
- Variables
- func Apply(w io.Writer, root string, entries []Entry, printOnly bool) error
- func Details(states []ClientState) string
- func Files(name string) (map[string][]byte, error)
- func Install(w io.Writer, root string, targets []Target, printOnly bool) error
- func IsManaged(fm Frontmatter) bool
- func Names() ([]string, error)
- func Summary(states []ClientState) string
- func SymlinkIn(root, rel string) (string, error)
- type ClientState
- type Entry
- type Frontmatter
- type State
- type Target
Constants ¶
const ( ModeAuto = "auto" ModeClaude = "claude" ModeCodex = "codex" ModeAll = "all" )
Install modes for Targets. Auto is what a bare --skills means: Claude Code always, Codex only when the repository already has an .agents/ directory, which is the place Codex and other Agent Skills clients read. .codex/ is not consulted.
const ( ClaudeDir = ".claude/skills" AgentsDir = ".agents/skills" )
Client skill directories, repository-relative with forward slashes.
const ( MarkerKey = "seamark" MarkerValue = "managed" )
Ownership marker. A SKILL.md whose metadata carries MarkerKey set to MarkerValue belongs to seamark: init refreshes such a directory and never touches any other. This mirrors how hooks are recognized by their argument tail, with the marker read from frontmatter instead.
const Root = "skills"
Root is the embedded directory that holds one subdirectory per skill.
const SkillFile = "SKILL.md"
SkillFile is the file every skill directory carries. Its YAML frontmatter is the skill's metadata; the Markdown body is the skill.
Variables ¶
var Modes = []string{ModeAuto, ModeClaude, ModeCodex, ModeAll}
Modes lists the accepted install modes for help and error text.
Functions ¶
func Apply ¶
Apply executes a plan with one narrated line per skill directory, in init's vocabulary: wrote, updated, kept, and the would- forms under preview. An absent directory gets every shipped file; a stale managed copy gets the shipped files rewritten and keeps any extra file the user added; current and foreign directories are left alone. A write failure returns with the path in the error, and a re-run completes the set because the plan is recomputed from disk.
func Details ¶
func Details(states []ClientState) string
Details renders every client's Describe on one line, for example "claude 3/3 current · codex not installed". doctor prints it as the detail of its own verdict; Summary adds the corrective command.
func Files ¶
Files returns every file of one skill keyed by its path relative to the skill directory, for example "SKILL.md" and "references/interpreting-seamark.md". The map is unordered; a caller that writes the files sorts the keys for stable output.
func Install ¶
Install plans and applies in one call for callers that need no gap between the two, such as tests and doctor fixtures.
func IsManaged ¶
func IsManaged(fm Frontmatter) bool
IsManaged reports whether the frontmatter carries the ownership marker.
func Names ¶
Names lists the embedded skills in sorted order. A skill is a directory under Root that contains SkillFile; other entries, such as the tree's README, are not skills.
func Summary ¶
func Summary(states []ClientState) string
Summary renders the one-line view init and status print. A stale or missing managed copy names the corrective command once at the end.
func SymlinkIn ¶
SymlinkIn walks rel down from root one component at a time and returns the first component that is a symbolic link, or "" when none is. The walk stops at the first missing component, because nothing below it exists yet. Every path seamark reads or writes under a client directory passes this check, so a link committed in a cloned repository can never redirect a refresh outside the tree.
Types ¶
type ClientState ¶
type ClientState struct {
Client string `json:"client"`
Dir string `json:"dir"`
Current int `json:"current"`
Stale int `json:"stale"`
Missing int `json:"missing"`
Foreign int `json:"foreign"`
Err string `json:"error,omitempty"`
}
ClientState summarizes one client's skill directory for init, doctor, and status. Counts are over the shipped skills; Foreign counts directories that carry a shipped skill's name but not seamark's marker.
func Inspect ¶
func Inspect(root string) []ClientState
Inspect reports both clients regardless of detection, so a stale copy in a directory auto would skip stays visible. A read error is recorded on the client instead of failing the call: status must never fail because one directory is unreadable.
func (ClientState) Describe ¶
func (c ClientState) Describe() string
Describe renders one client in a few words, for example "claude 3/3 current, 1 stale" or "codex not installed". init, status, and doctor all print it, so the three never phrase a state differently.
func (ClientState) Installed ¶
func (c ClientState) Installed() bool
Installed reports whether the client holds any managed skill.
func (ClientState) NeedsRefresh ¶
func (c ClientState) NeedsRefresh() bool
NeedsRefresh reports whether a managed copy is stale or missing, the two states `seamark init --skills` repairs.
func (ClientState) Notable ¶
func (c ClientState) Notable() bool
Notable reports whether the client is worth a line when nobody asked for skills: it holds managed skills, a directory seamark does not own, or an unreadable one. init and status print the summary only then, so a plain run never claims "not installed" over any of the three.
type Entry ¶
type Entry struct {
Name string
// Rel is the repository-relative directory, slash-separated.
Rel string
State State
// Reason explains a Foreign classification; empty otherwise.
Reason string
}
Entry is one skill directory in an install plan.
type Frontmatter ¶
type Frontmatter struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
License string `yaml:"license"`
Compatibility string `yaml:"compatibility"`
Metadata map[string]string `yaml:"metadata"`
AllowedTools string `yaml:"allowed-tools"`
}
Frontmatter is the YAML header of a SKILL.md. The fields are the Agent Skills core set plus allowed-tools. Unknown fields are ignored, so a user's own skill still parses when init inspects it for the marker.
func ParseFrontmatter ¶
func ParseFrontmatter(skillMD []byte) (Frontmatter, string, error)
ParseFrontmatter splits a SKILL.md into its frontmatter and body. The file must open with a "---" line and close the header with another; the body is everything after the closing fence. YAML syntax errors are reported rather than loaded as an empty header, so a malformed shipped skill fails the tests instead of failing silently in a client.
type State ¶
type State int
State classifies one skill directory on disk.
const ( Absent State = iota // nothing at the path Current // managed and byte-equal to the shipped files Stale // managed, but a shipped file differs or is missing Foreign // present without seamark's marker )
The four states Plan reports. Only Absent and Stale lead to a write. Foreign is never touched: the directory is the user's, not seamark's.