skills

package
v0.156.2 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package skills implements discovery of Agent Skills. A skill is a folder containing a SKILL.md whose YAML frontmatter (name, description) is parsed at startup; the body is read lazily by the model via the Read tool.

The on-disk format intentionally matches the contract shared by the standard, so a folder authored for any of them drops in unchanged.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CleanupDynamic added in v0.155.0

func CleanupDynamic() error

CleanupDynamic removes all dynamically downloaded skills from the temporary skills directory. Called after the session ends.

func ExpandShorthand added in v0.109.1

func ExpandShorthand(input, repository string) string

ExpandShorthand turns shorthand install targets into full GitHub tree URLs, resolving them against the configured "<owner>/<repo>" skills repository (config.DefaultSkillsRepository when empty). For the default repository:

The two-segment form keeps the repository *name* from the configured value and swaps only the owner, so a renamed fork stays reachable as "<org>/<skill>".

Anything else (3+ slash-separated segments, empty segments, etc.) is returned unchanged so ParseGitHubTreeURL produces its existing error.

func LoadSkillMetadata added in v0.134.0

func LoadSkillMetadata(skillDir, dirName string, scope domain.SkillScope, pluginName string) (*domain.Skill, *domain.SkillLoadError)

LoadSkillMetadata reads <skillDir>/SKILL.md, parses frontmatter, validates the fields, and returns the populated domain.Skill. Returns (nil, nil) when the directory has no SKILL.md, (nil, err) when SKILL.md is invalid. pluginName is set only for plugin-scoped skills.

func SeedBuiltins added in v0.144.0

func SeedBuiltins(destDir string, overwrite bool) error

SeedBuiltins writes each embedded built-in skill under destDir, mirroring the embedded tree (destDir/<name>/SKILL.md, plus any helper files). A file is written only when it is absent, unless overwrite is set - so a user's edits to a seeded skill survive a re-run of `infer init` (seed-if-absent). destDir is the user-scope skills directory (~/.infer/skills), the same directory the loader reads user skills from.

func SkillTreeURL added in v0.155.0

func SkillTreeURL(repository, skill string) string

SkillTreeURL returns the GitHub tree URL of skill inside the given "<owner>/<repo>" skills repository. It is the single place the skills-repo layout (<ref>/<subdir>/<skill>) is encoded.

func Uninstall

func Uninstall(name, destBase string) (string, error)

Uninstall removes the skill folder named `name` from `destBase`. The name must match the on-disk skill-name regex (lowercase letters, digits and hyphens) so callers can't smuggle in path-traversal payloads like `../`. Returns an error if the folder doesn't exist or isn't a directory.

Types

type CatalogClient added in v0.155.0

type CatalogClient struct {
	// contains filtered or unexported fields
}

CatalogClient fetches skill metadata from the centralized skills registry. It implements progressive discovery: only the index (name + description) is fetched up front; the full skill body is downloaded only on activation.

func NewCatalogClient added in v0.155.0

func NewCatalogClient(cfg *config.Config) *CatalogClient

NewCatalogClient returns a CatalogClient for the configured skills repository. Both the index and the skill bodies come from that one repo, so agent.skills.repository is the only knob needed to point the CLI at a fork.

func (*CatalogClient) DownloadSkill added in v0.155.0

func (c *CatalogClient) DownloadSkill(ctx context.Context, name string) (string, error)

DownloadSkill fetches the full skill folder from the catalog and writes it to the dynamic skills directory. Returns the path to the downloaded SKILL.md.

func (*CatalogClient) Index added in v0.155.0

func (c *CatalogClient) Index(ctx context.Context) []catalogEntry

Index fetches the catalog index (name + description for every published skill) and caches it for the process lifetime. Returns nil on any failure - the catalog is best-effort, never fatal. No body download.

func (*CatalogClient) Lookup added in v0.155.0

func (c *CatalogClient) Lookup(ctx context.Context, name string) (*catalogEntry, bool)

Lookup queries the catalog index for a skill with the given name. Returns the entry metadata and true on success, or false when the skill is not found.

func (*CatalogClient) Release added in v0.155.0

func (c *CatalogClient) Release() (release, updated string)

Release returns the catalog's published release version and update timestamp as of the last Index fetch. Both are empty when the catalog has not been fetched or does not publish them. Individual skills carry no version of their own - the catalog is versioned as a whole.

func (*CatalogClient) Search added in v0.155.0

func (c *CatalogClient) Search(ctx context.Context, query string, limit int) []domain.Skill

Search matches query against the catalog, best match first, capped at limit. An empty query returns the head of the index so the command doubles as a browse.

Ranking, in order: names fuzzy-matched by score, then entries whose description literally contains the query. Fuzzy runs over names ONLY - a subsequence match against a paragraph of prose is meaningless ("rust" matches r..u..s..t in most English sentences), which makes description matching substring-only.

Matching is local over the cached index because catalog.json is a single static file with no server-side query support - see NewCatalogClient.

type GitHubLocation

type GitHubLocation struct {
	Owner string
	Repo  string
	Ref   string
	Path  string
}

GitHubLocation identifies a directory inside a public GitHub repository, parsed out of a /tree/<ref>/<path> URL.

func ParseGitHubTreeURL

func ParseGitHubTreeURL(rawURL string) (*GitHubLocation, error)

ParseGitHubTreeURL accepts URLs of the form

https://github.com/<owner>/<repo>/tree/<ref>/<path-to-skill>

Refs containing a literal "/" (e.g. "feature/foo" branches) are not supported; pass the URL of a tag or single-segment branch instead.

type Installer

type Installer struct {
	Client  *http.Client
	APIBase string
	RawBase string
	Token   string
	// Repository is the "<owner>/<repo>" skills repository shorthand install
	// targets resolve against. Empty means config.DefaultSkillsRepository.
	Repository string
}

Installer downloads a skill folder from a GitHub repo into a local destination directory. When Token is non-empty its requests are authenticated, which raises the GitHub API rate limit from 60 to 5,000 requests/hour and allows access to private repositories the token can see.

func NewInstaller

func NewInstaller(repository string) *Installer

NewInstaller returns an Installer pointed at github.com with a 30s HTTP timeout, resolving shorthand targets against the given "<owner>/<repo>" skills repository (empty = config.DefaultSkillsRepository). The GitHub token is read from the environment (GITHUB_TOKEN, then GH_TOKEN); when neither is set requests are made unauthenticated. Tests substitute APIBase / RawBase to point at httptest.Server.

func (*Installer) InstallFromGitHub

func (i *Installer) InstallFromGitHub(ctx context.Context, rawURL, destBase string, overwrite bool) (string, error)

InstallFromGitHub downloads the skill folder at rawURL into <destBase>/<dirname>/, where dirname is the last path segment of the repo URL. Existing folders are rejected unless overwrite is true.

The downloaded folder is post-validated with LoadSkillMetadata - if frontmatter fails the spec checks, the folder is removed and the validation error is returned. There is never a half-installed state.

Returns the absolute path of the installed skill on success.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service discovers SKILL.md files and exposes the parsed metadata. Loading is gated by config.AgentSkillsConfig - when disabled the scan is skipped entirely so there is zero token / IO cost.

func New

func New(cfg *config.Config) *Service

New returns a Service bound to cfg. Call Load to populate the skill list.

func (*Service) CleanupDynamic added in v0.155.0

func (s *Service) CleanupDynamic(_ context.Context) error

CleanupDynamic removes dynamically downloaded skills from disk. When cleanup is enabled in config, this removes all skills that were fetched from the catalog during this session. No-op when discovery is disabled or cleanup is explicitly turned off.

func (*Service) Discover added in v0.155.0

func (s *Service) Discover(ctx context.Context, name string) (domain.Skill, bool)

Discover resolves a skill by name, downloading its body from the centralized catalog when the loaded entry is a metadata-only catalog placeholder (empty Path, seeded by Load). Any skill already backed by a file on disk - local or previously downloaded - is returned as-is, so this is the safe replacement for Get on the activation path. Returns false when the name is unknown, or when it is only resolvable via the catalog and discovery is disabled.

func (*Service) Errors

func (s *Service) Errors() []domain.SkillLoadError

Errors returns a defensive copy of validation failures from the last Load.

func (*Service) Get added in v0.117.0

func (s *Service) Get(name string) (domain.Skill, bool)

Get returns the loaded skill with the given name. Lookup is exact (names are validated to the lowercase `[a-z0-9-]+` charset at load time).

func (*Service) List

func (s *Service) List() []domain.Skill

List returns a defensive copy of the loaded skills.

func (*Service) Load

func (s *Service) Load(ctx context.Context) error

Load scans both project and user-global skill directories, parses frontmatter, validates each skill, and populates the in-memory list. When skills are disabled in config the call is a no-op and returns nil.

Jump to

Keyboard shortcuts

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