Install, update, and curate agent skills from GitHub repositories.
skill is a small CLI for managing installable SKILL.md bundles across projects. It supports direct installation from GitHub repos, local and global install roots, and a favorites workflow that helps agents and users reuse the same curated skill set across projects.
Agent skills are useful only if they are easy to reuse.
Without a dedicated manager, teams usually end up copying SKILL.md files by hand, duplicating the same setup work across repositories, and losing track of which curated skills they actually want to keep using.
skill gives that workflow a stable contract:
- install skills directly from GitHub repositories
- keep project-local and global skill roots separate
- save favorite skill refs for repeated use
- refresh installed skills and favorite metadata over time
Install the latest release:
curl -fsSL https://raw.githubusercontent.com/ethan-huo/skill/main/install.sh | bashBy default, the installer downloads the executable JS bundle from GitHub Releases
and installs it to ~/.local/bin/skill.
Set SKILL_INSTALL_DIR to choose another install directory.
Requirements:
- Bun 1.3+
gitonPATHghonPATHfor favorite metadata refresh and repo validation
For most real usage, start from favorites and install only what the current project needs.
skill install owner/repo/skill
skill install gh:owner/repo/path/to/skill
skill install owner/repo --skills 'skill-a,skill-b'
skill install owner/repo --skills 'core/{skill-a,skill-b},codex/skill-c'
skill install owner/repo --map
skill listAgents should prefer this path over broad search when the user's favorites already contain good candidates.
Project and global installs keep source-scoped items in the scope's manifest.json and expose
one-level links from the shared ~/.agents/.skills cache.
$HOME has no project scope, because its .agents/skills is the global root: project commands
run there fail and ask for --global. Global links that predate the global manifest are
recorded the first time any command writes it.
Install specific favorites by id, or open an interactive selector when no ids are given:
skill favorite install
skill favorite install ethan-huo/agents/cx
skill favorite install ethan-huo/agents --globalfavorite install merges same-repo selections into one install flow. Repo-level favorites may trigger a second skill-selection prompt when the repo contains multiple skills.
When favorites do not cover the task, use the public search index:
skill find seo
skill find animation --limit 5Search is a discovery path, not the default install path. Results are emitted as a YAML list so agents and pipelines receive the complete records without terminal-width truncation.
skill update
skill install
skill install --global
skill remove --global
skill remove owner/repo
skill remove owner/repo/skill
skill favorite refresh
skill favorite remove
skill favorite remove owner/repo owner/repo/skillskill @schema is the agent contract. Agent calls use dotted command paths and one
quoted object literal:
skill favorite.list
skill install "{ repo: ['owner/repo'], skills: 'skill-a,skill-b' }"The positional and flag forms below remain the shorter human-facing surface.
| Command | Purpose |
|---|---|
skill add owner/repo/skill |
Install one known skill directly |
skill add gh:owner/repo/path/to/skill |
Install one exact GitHub skill ID |
skill add owner/repo --skills 'a,b' |
Install multiple skills from one repo without prompts |
skill add owner/repo --skills 'core/{a,b},other/c' |
Select exact variants without expanding repeated selectors |
skill add owner/repo |
Interactive selection when the repo contains multiple skills |
skill remove |
Interactively remove local skills or repo maps |
skill remove --global |
Interactively remove one or more global skills |
skill remove owner/repo |
Remove all installed skills from one repo |
skill remove owner/repo/skill |
Remove one installed skill without touching siblings |
skill remove gh:owner/repo/path/to/skill |
Remove one GitHub skill by its canonical ID |
skill remove owner/repo --global |
Purge global links, shared source cache, and repo favorites |
| Command | Purpose |
|---|---|
skill install |
Rebuild project links and maps from .agents/skills/manifest.json |
skill install --global |
Rebuild global links from ~/.agents/skills/manifest.json |
skill install owner/repo/skill |
Install a shared source and link one skill into this project |
skill install gh:owner/repo/path/skill |
Install one exact GitHub skill ID |
skill install owner/repo/skill --global |
Install a shared source and link one skill globally |
skill install owner/repo --skills 'a,b' |
Link multiple selected skills into this project |
skill install owner/repo --map |
Generate one repo-level map skill with ctx-read routing rows |
| Command | Purpose |
|---|---|
skill favorite add <refs...> |
Save one or more favorite refs |
skill favorite remove |
Remove favorites with an interactive selector in TTY |
skill favorite remove <refs...> |
Remove one or more favorite refs non-interactively |
skill favorite list |
Show favorite refs with cached descriptions |
skill favorite list --json |
Machine-readable favorite list |
skill favorite refresh |
Refresh descriptions and remove upstream refs that no longer exist |
skill favorite install |
Install favorites (interactive selector in TTY, or pass ids) |
skill favorite install <ids...> |
Install specific favorites by id non-interactively |
| Command | Purpose |
|---|---|
skill find <query> |
Search published skills on skills.sh |
skill list |
List installed skills and estimate frontmatter name/description tokens |
| skill update | Refresh shared source caches and reconcile global plus project links |
| skill update --concurrency <n> | Run repo updates in parallel (default 8, 1 matches old behavior) |
| skill update --no-progress | Disable the live progress grid (auto-disabled on non-TTY/CI) |
skill list returns only file and description for each skill. file is
the absolute path to its installed SKILL.md through the visible skill link.
Use skill list --scope global or skill list --scope local to filter; omit
--scope to include both. Structured input also accepts skill list "{ scope: 'global' }".
Managed repo maps count as one entry each, using their SKILL.md frontmatter. Unmanaged
inline directories are excluded. Missing or non-file SKILL.md paths are skipped; malformed
frontmatter keeps the entry with empty metadata.
The summary count and estimated tokens describe only the returned skills.
Human-facing output is ANSI-highlighted when stdout is an interactive terminal. YAML keys, list markers, and scalar types receive lightweight colors; Markdown and schema output keep argc's existing formatting. Piped output, NO_COLOR=1, TERM=dumb, and --no-color remain byte-plain for agents and scripts.
skillscans a cloned GitHub repository forSKILL.md, including nested catalogs, while ignoring agent config roots such as.agents; a root-level skill has the stable folder IDroot- public skill IDs preserve their origin as
gh:{owner}/{repo}/{source-path} - same-name bundles with identical files are safely collapsed; bundles with different content remain distinct variants
- interactive installs select logical skills first, then use one repo-level variant radio when the selected conflicts share the same variants; mismatched variant sets are resolved per skill
- non-interactive installs use
--skills 'skill,variant/skill,variant/{skill,...}'; unqualified ambiguous skills fail with the available qualified selectors - copied
SKILL.mdfiles with repairable malformed YAML frontmatter are repaired before entering the shared source cache owner/repo/skillis shorthand forskill add owner/repo --skills 'skill'- visible skill folders and cached
SKILL.mdnames use the Agent Skills-compatible{skill-path}-{owner}form; the manifest retains the repo and exact source path, and conflicting sources cannot claim the same visible folder skill install owner/repo --mapwrites.agents/skills/map-{repo}-{owner}/SKILL.mdwith actx read github://owner/repo/<path>rule andWhen ..., read path/SKILL.mdrows- a map's description is derived as
{owner}/{repo} skills router: <skill-a>, <skill-b>, ...(justrouterwhen the repo name already ends inskill/skills) (truncated with+N moreat the 1024-character spec limit); it needs no GitHub metadata or caller input, and the manifestmapitem stores only the repo (a legacy pinneddescriptionis dropped on the next manifest write) - interactive project installs show "Install as repo map" above individual skills; selecting either mode disables the other
- interactive repo skill selection preselects already installed skills from the target scope;
--globalpreselects global installs, while project installs preselect project links - repo maps and selected skill installs are mutually exclusive per repo; installing one mode removes the other mode from the manifest and visible aliases
- project-scope
skill updateregenerates map items recorded in.agents/skills/manifest.json - versionless and version 2 manifests migrate to version 3; new installs persist each logical skill ID with its exact upstream source path
- repeated installs reuse shallow clone caches keyed by the remote
HEADhash - local and global installs skip selected skills whose normalized visible folder is already claimed in the other scope, install the remaining selection, and report each skip with a canonical skill ID plus a stable reason
- each skill has one stable shared directory; updating it from any project immediately updates every project that links to it
- unchanged normalized bundles leave source directories and visible links untouched
- updates stage and normalize complete bundles beside the destination, atomically exchange directories on macOS/Linux, and delete the old contents; filesystems without atomic exchange fail without replacing the installed bundle
- old snapshot directories migrate to redirects to the shared directory, preserving existing project pointers without retaining historical contents; new installs never create snapshots or
.currentpointers - installs record repo-scoped manifest items in the target scope's manifest
- project-scope
skill addandskill install <ref>share the same install effects;--globaltargets the global manifest and visible root skill updateupdates the union of repos recorded in the global manifest and current project's manifest, then reconciles both visible rootsskill updateruns all source repos in parallel (default 8 in flight), renders a live progress grid on stderr, and returns stable-order YAML records for repo diffs, regenerated maps, and failures on stdoutskill updatemigrates source-scoped and legacy visible aliases to manifest-backed skill IDs- project-scope
skill updateremoves visible links for upstream skills that disappeared, including stale symlinks whose source target is already gone - interactive
skill removeincludes repo maps recorded in the target scope manifest alongside visible skill links skill removeremoves matching visible aliases and manifest entries from the target scope; empty repo skill items are prunedskill remove owner/repo --globalremoves global links, manifest entries, and matching favorite refs; shared source directories remain available to other projects
Install roots:
- local visible links:
{cwd}/.agents/skills/{skill-path}-{owner}/ - global visible links:
~/.agents/skills/{skill-path}-{owner}/ - local map skills:
{cwd}/.agents/skills/map-{repo}-{owner}/ - shared current skill directories:
~/.agents/.skills/{owner}/{repo}/{skill-path}/ - local manifest:
{cwd}/.agents/skills/manifest.jsonstores versionedskillswith exact source paths andmapitems, not visible link names - local manifest writes maintain an exact-name block in
{cwd}/.agents/skills/.gitignore; entries outside that block, including user-created skills, are preserved - generated ignore rules prevent new links from entering Git but do not untrack links already present in the index; existing projects must remove those generated entries from the index once
- global manifest:
~/.agents/skills/manifest.jsonstores versionedskillswith exact source paths, not visible link names
To normalize an existing global install to the current {skill-path}-{owner} layout:
bun run migrate:global-skillsTo migrate a project-local skill root:
bun run migrate:skills /path/to/project
bun run migrate:skills /path/to/project/.agents/skillsFavorites:
- stored at
~/.agents/skill-favorites.json - support both
owner/repoandowner/repo/skill - include cached descriptions and last refresh timestamps
This repository ships with an agent-facing skill. src/index.md
is the source of truth, served by skill @skill.
skills/skill/SKILL.md routes matching intent directly
to that command; its body is only a harness fallback.
That skill is intentionally narrower than this README. It teaches agents the main workflow:
- inspect
skill @schemafirst to learn the command surface - read project context
- inspect favorites
- pick a small set of relevant skills
- install locally by default
- fall back to
findonly when favorites are insufficient
If you want an agent to use this tool in new projects, install this skill into the agent's skill root first.
- non-interactive installs that match multiple skills must pass a
--skills '<selector,...>'expression favorite installwithout ids requires a TTY; in non-TTY environments pass ids explicitlyfavorite removewithout ids requires a TTY; in non-TTY environments pass ids explicitlyfavorite install --globalinstalls into the global skill rootfavorite addvalidates upstream repo existence before writing the favoritefavorite refreshdepends on authenticatedghaccess- only
github.comrepositories are supported right now