skills

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package skills discovers reusable instruction "skills" stored on disk as */SKILL.md files. Each skill is a directory containing a SKILL.md whose optional YAML-ish frontmatter carries a name/description and whose markdown body is the skill content the model can pull in on demand (PRD F15).

The loader is deliberately dependency-free: frontmatter is hand-parsed (no YAML library) and malformed files are skipped rather than failing the whole load, so a single bad skill never hides the good ones.

Index

Constants

View Source
const LockFileName = "skills.lock"

LockFileName is the name of the per-directory lockfile that maps an installed skill name to the source it was installed from and the content hash recorded at install time.

Variables

View Source
var ErrNameClash = errors.New("a different skill with that name is already installed")

ErrNameClash is returned when an install would overwrite a skill that was installed from a DIFFERENT source, unless InstallOptions.Force is set. It is a safety guard so a remote source can never silently shadow a skill the user already trusts.

Functions

func DefaultDir

func DefaultDir(env map[string]string) string

DefaultDir resolves the skills directory, mirroring sessions.DefaultRoot. An explicit ZERO_SKILLS_DIR override wins; otherwise it is $XDG_DATA_HOME/zero/skills or ~/.local/share/zero/skills. The directory is NOT created — a missing directory simply yields no skills.

func ReadLock

func ReadLock(dir string) (map[string]LockEntry, error)

ReadLock loads the lockfile from dir. A missing lockfile yields an empty map with no error so callers can treat "no lockfile" as "nothing installed".

func Remove

func Remove(dir string, name string) error

Remove deletes an installed skill directory and its lockfile entry. It errors if the named skill is not present in either the dir or the lockfile.

Types

type DuplicateName

type DuplicateName struct {
	Name   string
	Winner string
	Loser  string
}

DuplicateName records two skills that resolved to the same frontmatter name. Winner is the SKILL.md path of the skill that was kept (the one in the lexicographically-first directory); Loser is the path that was dropped.

func Duplicates

func Duplicates(dir string) ([]DuplicateName, error)

Duplicates returns the duplicate-name collisions Load resolved by the first-directory-wins rule, so a caller can warn the user that a shadowed skill was dropped. A missing directory yields no duplicates and no error.

type GitRunner

type GitRunner func(ctx context.Context, destination string, source string) error

GitRunner fetches the skill at source into destination. The default runner shallow-clones with the system git, which inherits the process environment (and therefore any proxy/egress settings). It is injectable so tests never hit the network. A runner must only fetch — it must never execute fetched content.

type InstallOptions

type InstallOptions struct {
	// Source is a git URL or a local filesystem path to a skill directory (one
	// that contains a SKILL.md, or whose tree contains exactly one).
	Source string
	// Dir is the skills directory to install into (typically DefaultDir(env)).
	Dir string
	// Force allows overwriting a skill that was installed from a different source.
	Force bool
	// GitRunner overrides the fetch implementation (tests/proxy control). When
	// nil, a git source is shallow-cloned with the system git.
	GitRunner GitRunner
}

InstallOptions configures a single skill install.

type InstallResult

type InstallResult struct {
	Name string `json:"name"`
	// Path is the absolute path to the installed SKILL.md.
	Path string `json:"path"`
	// Hash is the content hash recorded for the installed skill.
	Hash string `json:"hash"`
	// Source echoes the source the skill was installed from.
	Source string `json:"source"`
	// Updated is true when an existing install was replaced; PreviousHash then
	// carries the prior recorded hash so a caller can show the change.
	Updated      bool   `json:"updated"`
	PreviousHash string `json:"previousHash,omitempty"`
}

InstallResult reports what an install did.

func Install

func Install(ctx context.Context, options InstallOptions) (InstallResult, error)

Install fetches the skill at options.Source and copies its SKILL.md into options.Dir/<name>/, validating the frontmatter and recording a content hash in the lockfile. A git URL is fetched via the (injectable) GitRunner into a temp dir; a local path is read in place. Fetched content is never executed.

type LockEntry

type LockEntry struct {
	Source string `json:"source"`
	Hash   string `json:"hash"`
}

LockEntry records the source and content hash for one installed skill.

type Skill

type Skill struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Content     string `json:"content,omitempty"`
	Path        string `json:"path"`
}

Skill is a single discovered skill. Name and Description come from the SKILL.md frontmatter (Name falls back to the directory name); Content is the markdown body; Path is the absolute path to the SKILL.md file.

func Get

func Get(dir string, name string) (Skill, bool)

Get loads the named skill from dir, returning false if it is not found.

func List

func List(dir string) ([]Skill, error)

List loads the skills directory and returns each skill without its (possibly large) Content body — handy for `zero skills` listings.

func Load

func Load(dir string) ([]Skill, error)

Load scans dir for */SKILL.md files and returns the parsed skills sorted by name. A missing directory yields an empty slice with no error; individual malformed skill files are skipped rather than failing the whole load.

When two skills declare the SAME frontmatter name, resolution is made DETERMINISTIC by a documented rule: the skill in the lexicographically-first directory name wins (os.ReadDir returns entries sorted by filename, so the first one encountered is kept and later same-name duplicates are dropped). This guarantees Load/List/Get always resolve a duplicated name to the same winner regardless of sort stability. Use Duplicates to surface a warning about any such collisions.

NOTE: Load scans one root. Agent startup merges plugin-declared skill roots separately during plugin activation, so the runtime skill surface can include both the default directory and skills bundled by active plugins.

type SkillInfo

type SkillInfo struct {
	Skill  Skill  `json:"skill"`
	Source string `json:"source,omitempty"`
	Hash   string `json:"hash,omitempty"`
}

SkillInfo bundles a discovered skill with its recorded source and hash, for `skill info`.

func Info

func Info(dir string, name string) (SkillInfo, bool)

Info returns the named skill plus its recorded source and hash, or ok=false if it is not discoverable in dir.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL