skills

package
v2.19.0 Latest Latest
Warning

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

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

Documentation

Overview

Package skills installs LiveKit's agent skills (https://agentskills.io) and the LiveKit Docs MCP server into coding agents such as Claude Code, Codex and Cursor.

Installs are plain copies, never symlinks, and are recorded in the same lock files the `skills` CLI (github.com/vercel-labs/skills) and `gh skill` use, so any of the three tools can manage what another installed.

Index

Constants

View Source
const (
	// MCPServerName is the name the Docs MCP server is registered under,
	// matching the setup instructions on docs.livekit.io.
	MCPServerName = "livekit-docs"
	MCPServerURL  = "https://docs.livekit.io/mcp"
	// MCPDocsURL covers manual setup for agents lk can't configure.
	MCPDocsURL = "https://docs.livekit.io/intro/mcp-server/"
)
View Source
const (
	// SourceRepo is the GitHub repo LiveKit's skills are published from.
	SourceRepo = "livekit/agent-skills"
	// DefaultRef is the branch installs track. Skills are written to stay
	// valid as the SDKs evolve, so the tip of main is what everyone gets.
	DefaultRef = "main"
)

Variables

View Source
var Agents = []*Agent{
	{
		ID: "claude-code", Name: "Claude Code",
		// contains filtered or unexported fields
	},
	{
		ID: "codex", Name: "Codex",
		// contains filtered or unexported fields
	},
	{
		ID: "cursor", Name: "Cursor",
		// contains filtered or unexported fields
	},
	{
		ID: "github-copilot", Name: "GitHub Copilot",
		// contains filtered or unexported fields
	},
	{
		ID: "gemini-cli", Name: "Gemini CLI",
		// contains filtered or unexported fields
	},
	{
		ID: "opencode", Name: "OpenCode",
		// contains filtered or unexported fields
	},
	{
		ID: "windsurf", Name: "Windsurf",
		// contains filtered or unexported fields
	},
	{
		ID: "amp", Name: "Amp",
		// contains filtered or unexported fields
	},
	{
		ID: "cline", Name: "Cline",
		// contains filtered or unexported fields
	},
	{
		ID: "goose", Name: "Goose",
		// contains filtered or unexported fields
	},
}

Agents is every agent lk knows how to install into, in display order. Skill paths follow the `skills` CLI's table so installs from either tool land in the same place.

View Source
var ArchiveURL = func(ref string) string {
	return "https://codeload.github.com/" + SourceRepo + "/tar.gz/" + ref
}

ArchiveURL is the tarball for a ref. It is a variable so tests can serve their own archive.

Functions

func AgentIDs

func AgentIDs() []string

AgentIDs lists every known agent ID.

func AgentNames

func AgentNames(agents []*Agent) string

AgentNames joins agents' display names for messages.

func ContentHash

func ContentHash(files []File) string

ContentHash is the `skills` CLI's project lock hash (computedHash): SHA-256 over each file's relative path followed by its contents, in the order JavaScript's String.prototype.localeCompare sorts the paths. Matching it exactly lets lk recognize skills that `npx skills` installed, and vice versa.

func TreeHash

func TreeHash(files []File) string

TreeHash is the git tree SHA-1 of a skill directory, which the `skills` CLI's global lock records as skillFolderHash.

Types

type Agent

type Agent struct {
	ID   string // stable identifier, matching the `skills` CLI's agent names
	Name string // display name
	// contains filtered or unexported fields
}

Agent describes one coding agent: where it reads skills from, how to tell it is installed, and how to register an MCP server with it.

func DetectAgents

func DetectAgents(env *Env) []*Agent

DetectAgents returns the agents that appear to be installed.

func FindAgent

func FindAgent(id string) *Agent

FindAgent looks an agent up by ID.

func (*Agent) Detected

func (a *Agent) Detected(env *Env) bool

Detected reports whether the agent appears to be installed.

func (*Agent) SkillsDir

func (a *Agent) SkillsDir(env *Env, scope Scope) string

SkillsDir returns the directory this agent reads skills from in scope.

type Bundle

type Bundle struct {
	Ref    string
	Commit string // full SHA, when the archive carries it
	Skills []*Skill
	// Skipped explains skill directories that failed validation, so one bad
	// skill upstream doesn't block installing the rest.
	Skipped []string
}

Bundle is every skill at one commit of the source repo.

func Fetch

func Fetch(ctx context.Context, client *http.Client, ref string) (*Bundle, error)

Fetch downloads the source repo at ref and parses every skill in it.

func ParseArchive

func ParseArchive(r io.Reader) (*Bundle, error)

ParseArchive reads a GitHub source tarball (one top-level directory holding the repo) and returns the skills under skills/<name>/.

func (*Bundle) Find

func (b *Bundle) Find(name string) *Skill

Find returns the named skill, or nil.

func (*Bundle) Names

func (b *Bundle) Names() []string

Names lists the bundle's skill names.

type Copy

type Copy struct {
	Skill    string
	Dir      SkillsDir
	State    State
	Upstream *Skill // nil when the skill is no longer published
}

Copy is one skill in one skills directory.

func (*Copy) Path

func (c *Copy) Path() string

Path is the skill's directory.

type Env

type Env struct {
	Home string // user home directory
	Root string // project root (the working directory)
	// Getenv and LookPath default to os.Getenv and exec.LookPath.
	Getenv   func(string) string
	LookPath func(string) (string, error)
}

Env is the filesystem context an install runs against. Tests point it at temporary directories.

func DefaultEnv

func DefaultEnv() (*Env, error)

DefaultEnv returns an Env for the real user and working directory.

type File

type File struct {
	Path string // slash-separated
	Mode int64  // 0o644 or 0o755
	Data []byte
}

File is one file of a skill, relative to the skill's directory.

type Frontmatter

type Frontmatter struct {
	Name        string         `yaml:"name"`
	Description string         `yaml:"description"`
	Metadata    map[string]any `yaml:"metadata"`
}

Frontmatter is the subset of SKILL.md frontmatter lk reads.

func ParseFrontmatter

func ParseFrontmatter(data []byte) (*Frontmatter, error)

ParseFrontmatter reads the YAML block at the top of a SKILL.md.

type Installer

type Installer struct {
	Env    *Env
	Scope  Scope
	Bundle *Bundle
	Lock   *Lock
	Now    func() time.Time
}

Installer compares and applies skills for one scope.

func NewInstaller

func NewInstaller(env *Env, scope Scope, bundle *Bundle) (*Installer, error)

NewInstaller loads the scope's lock file. bundle may be nil for operations that don't need upstream (remove).

func (*Installer) Delete

func (in *Installer) Delete(c Copy) error

Delete removes c's directory.

func (*Installer) Forget

func (in *Installer) Forget(name string) error

Forget drops name from the lock unless a copy remains in one of the scope's known directories.

func (*Installer) Inspect

func (in *Installer) Inspect(names []string, dirs []SkillsDir) ([]Copy, error)

Inspect reports the state of each named skill in each directory.

func (*Installer) InstalledLiveKitSkills

func (in *Installer) InstalledLiveKitSkills(dirs []SkillsDir) ([]string, error)

InstalledLiveKitSkills finds LiveKit skills present in dirs: those the lock attributes to LiveKit, those upstream publishes, and any SKILL.md whose frontmatter names LiveKit as its author.

func (*Installer) Orphans

func (in *Installer) Orphans(dirs []SkillsDir) ([]string, error)

Orphans lists LiveKit skills installed in dirs that upstream no longer publishes (removed or renamed).

func (*Installer) Record

func (in *Installer) Record(s *Skill)

Record notes an installed skill in the lock.

func (*Installer) Save

func (in *Installer) Save() error

Save writes the lock file.

func (*Installer) Write

func (in *Installer) Write(c Copy) error

Write installs (or overwrites) the upstream skill into c's directory.

type Lock

type Lock struct {
	Path string
	// contains filtered or unexported fields
}

Lock is a lock file loaded for editing.

func LoadLock

func LoadLock(env *Env, scope Scope) (*Lock, error)

LoadLock reads the lock file for scope. A missing file is an empty lock; a file that isn't valid JSON is an error rather than something to overwrite.

func (*Lock) Get

func (l *Lock) Get(name string) (*LockEntry, bool)

Get returns the entry for name, if any.

func (*Lock) Hash

func (l *Lock) Hash(name string) string

Hash is the recorded hash for name in this lock's format.

func (*Lock) LiveKitSkills

func (l *Lock) LiveKitSkills() []string

LiveKitSkills lists the names of entries installed from LiveKit's repo. Names are joined into paths that get deleted, so only valid skill names are returned: a lock file comes from whatever repo was cloned.

func (*Lock) Record

func (l *Lock) Record(s *Skill, ref string, now time.Time)

Record writes the entry for a skill installed from bundle.

func (*Lock) Remove

func (l *Lock) Remove(name string)

Remove drops the entry for name.

func (*Lock) Save

func (l *Lock) Save() error

Save writes the lock file, or deletes a project lock that has become empty and was only ever lk's.

type LockEntry

type LockEntry struct {
	Source          string `json:"source"`
	SourceType      string `json:"sourceType"`
	SourceURL       string `json:"sourceUrl,omitempty"`
	Ref             string `json:"ref,omitempty"`
	SkillPath       string `json:"skillPath,omitempty"`
	ComputedHash    string `json:"computedHash,omitempty"`
	SkillFolderHash string `json:"skillFolderHash,omitempty"`
	InstalledAt     string `json:"installedAt,omitempty"`
	UpdatedAt       string `json:"updatedAt,omitempty"`
}

LockEntry is one skill's record. Fields are the union of both lock formats.

func (*LockEntry) FromLiveKit

func (e *LockEntry) FromLiveKit() bool

FromLiveKit reports whether the entry was installed from LiveKit's repo, by any tool.

type MCPState

type MCPState string

MCPState is whether an agent has the Docs MCP server configured.

const (
	MCPConfigured  MCPState = "configured"
	MCPMissing     MCPState = "missing"
	MCPCustom      MCPState = "custom"      // an entry with our name points somewhere else; left alone
	MCPUnsupported MCPState = "unsupported" // lk can't configure this agent in this scope
)

type MCPStatus

type MCPStatus struct {
	Agent *Agent
	State MCPState
	Path  string
	Err   error // the config exists but couldn't be read
	// Added is set by ConfigureMCP when it added the server (rather than
	// finding it already there).
	Added bool
}

MCPStatus reports an agent's Docs MCP setup and the file it lives in.

func CheckMCP

func CheckMCP(env *Env, scope Scope, a *Agent) MCPStatus

CheckMCP inspects an agent's MCP config without changing it.

func ConfigureMCP

func ConfigureMCP(ctx context.Context, env *Env, scope Scope, a *Agent) (MCPStatus, error)

ConfigureMCP adds the Docs MCP server to an agent's config. It never replaces an existing entry of the same name.

type Scope

type Scope int

Scope selects where skills and MCP config are written: the current project, or the user's home directory.

const (
	ScopeProject Scope = iota
	ScopeGlobal
)

func (Scope) String

func (s Scope) String() string

type Skill

type Skill struct {
	Name        string
	Description string
	Files       []File // sorted by Path
}

Skill is one skill as published upstream.

func (*Skill) SkillPath

func (s *Skill) SkillPath() string

SkillPath is the SKILL.md path inside the source repo, as recorded in lock files.

type SkillsDir

type SkillsDir struct {
	Path   string
	Agents []*Agent
}

SkillsDirs groups agents by the directory they read skills from, so a shared directory like .agents/skills gets a single copy. Order follows agents.

func GroupSkillsDirs

func GroupSkillsDirs(env *Env, scope Scope, agents []*Agent) []SkillsDir

type State

type State string

State is how an installed copy of a skill compares to upstream.

const (
	StateMissing  State = "missing"  // not installed in this directory
	StateCurrent  State = "current"  // matches upstream
	StateOutdated State = "outdated" // unchanged since install; upstream has moved on
	StateModified State = "modified" // differs from both upstream and what was installed
	StateRemoved  State = "removed"  // installed from LiveKit, but no longer published
	// StateUntracked is a LiveKit skill (by its frontmatter) that no lock file
	// records, e.g. one committed to a starter template. It can't be told
	// apart from an edited copy, so replacing it asks first.
	StateUntracked State = "untracked"
)

Jump to

Keyboard shortcuts

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