skills

package
v0.7.1-rc.1 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package skills discovers agent skills where foreign harnesses keep them.

A skill — as agentskills.io spells it, and as Claude Code, Codex, Cursor and Gemini all read it — is a directory holding a SKILL.md whose frontmatter names it and describes it. The harnesses that install such folders do so in a handful of conventional places, and a person who has already collected skills there should not have to copy or reinstall them for codeaf to offer them: discovery reads them IN PLACE and reports the original directory, so the caller can register the folder itself as the artifact.

The package is pure on purpose. It reads directories the foreign harnesses own and writes nothing; it takes the project and home directories as arguments rather than resolving them; and it knows nothing about the store — what a discovery becomes is the resident's decision. That is what keeps the scan testable against fixture trees, and keeps the fact shape another surface consumes out of the scan's business.

Index

Constants

View Source
const (
	ScopeProject = "project"
	ScopeUser    = "user"
)

Scope values. A skill found under the project directory belongs to that project; a skill found under the home directory belongs to the machine.

View Source
const MaxSkillFileBytes = 64 * 1024

MaxSkillFileBytes bounds the text read from one SKILL.md on every door.

View Source
const RootClaudePlugins = ".claude/plugins"

RootClaudePlugins is the Root every skill read out of a Claude Code plugin carries. It is where Claude Code keeps its plugin registry, not a folder this scan walks: the skills themselves live wherever each installation's own record says it was unpacked.

View Source
const RootCodexSystem = ".codex/skills/.system"

RootCodexSystem is the folder Codex installs its own bundled skills into. It sits INSIDE .codex/skills, where the folder scan sees it as one child with no SKILL.md and passes over it, so it is read as a root of its own.

IT RANKS LAST IN ITS SCOPE, below the plugin skills too. A system skill is the harness's default and nobody chose it: a person who installed a skill of the same name into .codex/skills or anywhere else meant theirs.

Variables

View Source
var (
	// ErrNotRegular makes an unsafe file absent from discovery instead of
	// offering a skill whose content could block the conversation.
	ErrNotRegular = errors.New("not a regular file")
	// ErrTooLarge keeps plugin JSON from consuming an unbounded allocation.
	ErrTooLarge = errors.New("file exceeds read limit")
)

Functions

func OpenRegular

func OpenRegular(path string) (*os.File, error)

OpenRegular opens only ordinary files, including links to ordinary files. Stat rejects a pipe before open can block; Fstat checks the actual descriptor after open because another process can replace the path between those calls.

func ReadRegularHead

func ReadRegularHead(path string, limit int64) ([]byte, error)

ReadRegularHead reads only the bounded head of an ordinary file. A SKILL.md can have a long body, but its frontmatter is what discovery needs.

func ReadWholeRegular

func ReadWholeRegular(path string, limit int64) ([]byte, error)

ReadWholeRegular rejects a file beyond limit instead of returning a truncated JSON document. Stat avoids reading a known large file, and the extra byte catches one that grew while it was being read.

Types

type Options

type Options struct {
	ProjectDir string
	HomeDir    string
}

Options names where to look: the project's own directory and the login home directory, not any skills folder under them.

type Skill

type Skill struct {
	// Name is the frontmatter name, as written.
	Name string
	// Description is the frontmatter description, one line.
	Description string
	// Dir is the absolute path of the original skill folder. The skill is
	// never copied; this is where it lives.
	Dir string
	// Scope is ScopeProject or ScopeUser.
	Scope string
	// Root is the skills folder the skill was read from, e.g. ".claude/skills".
	Root string
	// SizeBytes is the total size of the regular files under Dir.
	SizeBytes int64
	// Warning says what is wrong with a skill that still loaded — a name that
	// does not match its folder, or one that breaks the field rules. A skill
	// that was skipped rather than loaded carries the reason here too.
	Warning string
	// Shadowed is true when another folder owns this skill's name: a project
	// skill over a user one, or an earlier root over a later one within a
	// scope. A shadowed skill stays in the result rather than being silently
	// dropped, because "why is my skill not working" deserves an answer.
	Shadowed bool
	// Plugin names the Claude Code plugin a skill arrived inside, spelled the
	// way Claude Code keys it (`name@marketplace`), and is empty for a skill
	// read from a skills folder. Root is [RootClaudePlugins] whenever this is
	// set.
	Plugin string
}

Skill is one discovered skill. The shape is FROZEN — the resident registers facts from it and other surfaces read those facts, so a field may be added but not renamed, reshaped or dropped.

func Discover

func Discover(opts Options) ([]Skill, error)

Discover scans the conventional skill folders under one project directory and one home directory, in issue #1277's order, and returns what it found: within each scope the hand-kept folders, then the skills of every installed and enabled Claude Code plugin, then Codex's bundled skills — every folder that holds a SKILL.md, winners first, losers marked Shadowed, and unreadable ones carried with a Warning rather than dropped. It never fails because one folder is broken — the worst a malformed skill can do is appear with a Warning — and it errors only when the caller named nowhere to look at all.

Jump to

Keyboard shortcuts

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