CLI Reference
The skillrepo CLI is the recommended way to connect SkillRepo to your dev environment. One command (npx skillrepo init) validates your access key, detects your dev environment, and pulls your library to disk. Use the same binary day-to-day to sync, search, add, and remove skills from the terminal.
On this page
Overview
skillrepo is a pull-based CLI. It reads your library from the registry and writes skills to disk, where your agent reads them directly — no long-running daemon, no background process. Every command is idempotent and safe to re-run.
Use the CLI when you want SkillRepo connected to your dev environment the way most users do: skills on disk (e.g. under .claude/skills/ for Claude Code), and a single command (skillrepo update) to keep everything current. The remote MCP endpoint exists for external agents and standalone MCP clients that don't run the CLI — see the MCP Reference for that path.
npx skillrepo initValidates your access key, auto-detects your dev environment, and pulls your library. Safe to re-run at any time.
Install
skillrepo is published to npm. Use npx for one-off invocations, or install globally so the binary lives at a stable absolute path on your machine — required for the session-sync hook to call back into the CLI on every Claude Code session start.
# One-off via npx (recommended for first run)
npx skillrepo <command>
# Or install globally
npm install -g skillrepo
skillrepo <command>Requires Node.js 18 or later. The CLI ships as ESM and uses node:-prefixed builtins; older Node releases will refuse to load it.
Authentication
The CLI authenticates with the same sk_live_* access keys SkillRepo issues for any registry surface. The CLI is the developer-machine surface; the MCP server and REST API serve remote agents and integrations. Mint a key from the dashboard’s Connect page; see Getting Started for the click path.
On first init, the CLI writes credentials to ~/.claude/skillrepo/config.json (chmod 0600 on POSIX) so subsequent commands run without a prompt. The file looks like:
{
"schemaVersion": 1,
"apiKey": "sk_live_...",
"serverUrl": "https://skillrepo.dev",
"accountSlug": "alice",
"accountId": "acc_...",
"userId": "user_...",
"writtenAt": "2026-04-15T00:00:00Z"
}Resolution order
Every command except init looks for credentials in this order. The first source that yields a key wins; later sources are ignored.
--key/--urlCLI flags~/.claude/skillrepo/config.jsonSKILLREPO_ACCESS_KEY/SKILLREPO_URLenvironment variables- Hard-fail with a hint to run
skillrepo init
init uses a slightly different order so it can reuse an existing config when one is already valid, fall back to .env.local / .env for the project, and finally prompt interactively. Pass --force to skip the cached config and re-prompt.
Keep your key secret
Access keys grant full read/write access to your account. Never commit keys to source control. Rotate compromised keys from the dashboard immediately.
Commands
Every command accepts --json to emit structured output suitable for scripting, and --verbose to print stack traces and per-attempt retry timings on failure.
skillrepo initValidates your access key, detects your dev environment, pulls your library to disk, and (in Claude Code) offers to install the SessionStart hook. Idempotent — re-run it any time to refresh detection or pick up a new vendor.
skillrepo init [--key <key>] [--url <url>] [--yes] [--force]
[--agent <list>] [--global] [--json] [--no-session-sync]Flags
| Flag | Description |
|---|---|
--key, -k | Access key. Falls back to SKILLREPO_ACCESS_KEY, then an interactive prompt. |
--url, -u | Server URL. Defaults to https://skillrepo.dev. Use this to point at a self-hosted instance. |
--yes, -y | Non-interactive setup. Skips every confirmation prompt. Installs the session-sync hook by default — pair with --no-session-sync to opt out. Under npx, also auto-runs npm install -g skillrepo if no global install is present so the hook can use a stable absolute path. |
--force | Re-prompt for a new key even if ~/.claude/skillrepo/config.json is valid. Use this to rotate credentials. |
--agent <list> | Comma-separated target override. Canonical tokens: claude (Claude Code at .claude/skills/), agents (the cohort — Cursor, Windsurf, Gemini CLI, Codex CLI, Cline, GitHub Copilot — sharing .agents/skills/), none (skip placement; config and gitignore still happen). Vendor names like cursor or claude-code are accepted as silent aliases. Combine targets with a comma, e.g. --agent claude,agents. |
--global | Write skills to the personal-scope path (~/.claude/skills/ for Claude Code, ~/.agents/skills/ for the cohort, or ~/.codeium/windsurf/skills/ for Windsurf) instead of the project-scoped path. |
--no-session-sync | Skip the SessionStart hook install. Works in both interactive and --yes modes. Use this in scripts that bootstrap a project but never start a Claude Code session. |
--json | Emit a structured JSON summary on success. Includes a sessionSync block describing whether the hook was installed and where it lives. |
Auto-refresh hooks per agent
For every agent the CLI knows how to install a SessionStart hook for, init writes a user-scope hook config so skillrepo update runs automatically when you open a new agent session. Five vendors are covered today; two are deferred until their docs publish a SessionStart-equivalent event. The cohort hook command is always npx --yes skillrepo update --silent — no global install required, cross-platform. Pass --no-session-sync to skip all hook installs in a single run. See the CLI README's session-sync section for the canonical JSON shapes the merger writes into each file.
| Agent | Hook config path | Event name | Notes |
|---|---|---|---|
| Claude Code | .claude/settings.local.json (project) or ~/.claude/settings.local.json (--global) | SessionStart | Legacy mechanism — runs your installed skillrepo binary by absolute path with a POSIX || true backstop. Toggled by the dedicated session-sync command, not the cohort installer. |
| Cursor | ~/.cursor/hooks.json | sessionStart (lowercase) | timeout: 60 (seconds). Multi-tool merge surface — 1Password, Snyk, and Apiiro extend the same file, and round-trip preservation of unknown keys is enforced. |
| Gemini CLI | ~/.gemini/settings.json | SessionStart (uppercase) | timeout: 60000 — milliseconds, distinct from every other vendor on this page. Requires a matcher: “*” group filter (without it Gemini silently skips the entry) and uses name: “skillrepo-update” as the entry id. |
| Codex CLI | ~/.codex/hooks.json | SessionStart (uppercase) | timeout: 60 (seconds). Codex also reads a [hooks] table from ~/.codex/config.toml; the two sources coexist because Codex merges them at runtime, so a hand-written TOML entry will not conflict with the JSON we write. |
| VS Code + CopilotPreview | ~/.copilot/hooks/skillrepo-update.json | sessionStart (lowercase) | timeout: 60 (seconds). Per-tool single-file config, not a shared multi-tool surface. Preview status: GitHub currently labels Copilot's hook system as Preview — the schema may shift before GA. |
| Windsurf | — | — | Not supported. Windsurf has no documented SessionStart-equivalent event in its docs as of 2026-05. Run skillrepo update manually. |
| Cline | — | — | Not supported. Cline uses per-task hooks (TaskStart / TaskEnd) and stores configs at a non-standard global path. Run skillrepo update manually. |
Unit tip when copying snippets between vendors: Gemini CLI's timeout is in milliseconds; Cursor, Codex CLI, and VS Code + Copilot all use seconds. The values look interchangeable but a 60 that means a minute on one vendor means 60 milliseconds on Gemini — check the unit before hand-editing a hook entry.
Cloud agent runners do not see these hooks
All hook config files listed above live under the developer's $HOME and are per-developer state. GitHub Codespaces and other cloud-agent runners cannot read them — the files never enter the runner's working tree. Auto-refresh is local-developer only; cloud runners always rely on whatever pre-warmed library shipped in the image.
Re-running init with a valid existing config re-runs detection and the per-vendor MCP merge prompts without re-prompting for a key. If the stored key has been revoked (the server returns 401), the CLI falls back to the interactive prompt automatically — no --force needed.
Non-interactive setup: under --yes the picker is skipped and the pre-checked rows become the selection. With no detection signals, both default rows (.claude/skills/ and .agents/skills/) are pre-checked — so running init --yes on a fresh clone always produces a working library. Pass --agent (e.g. --agent claude, --agent agents, or --agent claude,agents) to bypass the picker entirely. Pass --agent none to skip placement and just write config + gitignore.
Hitting the access-key quota
SkillRepo enforces one active access key per user. If you mint a key in Connect while another is already active, the dashboard surfaces a Rotate key CTA — rotating revokes the oldest active key and mints a new one in the same database transaction. CLI users running with --key directly will see quota_exceeded on the second mint and need to revoke or rotate through the dashboard. See Access Keys in a Team.
Accepting a team invitation
init doubles as the invitation-acceptance flow for invitees who have not clicked the email link yet. When the CLI does not already have a working access key, it opens the browser to the SkillRepo authentication page; after sign in, that page lists pending invitations for the email address alongside the accounts the user already belongs to.
- Run
npx skillrepo initin any project. - Sign in with the email address the invitation was sent to (GitHub or Google OAuth).
- Pick the invitation from the list. Acceptance and key issuance run in a single database transaction, so there is never a state where the membership exists without a key, or vice versa.
- The CLI receives the key and finishes its first-run sync against the team library.
The email-driven accept link still works exactly as before; the CLI flow is an alternative entry point for users whose starting point is a terminal rather than an inbox.
skillrepo updatePulls the latest state of your library from the server using a delta sync. Writes new and updated skills, removes skills that were removed from the library, and skips skills that are unchanged. Uses ETag caching so repeat runs return 304 Not Modified when nothing has changed.
skillrepo update [--global] [--agent <list>] [--json]Flags
| Flag | Description |
|---|---|
--global | Write to the personal-scope path (~/.claude/skills/ or ~/.agents/skills/) instead of the project directory. |
--agent <list> | Comma-separated target override. Same values as init (claude, agents, none, or a vendor alias). |
--json | Emit a structured summary of what was added, updated, or removed. |
skillrepo getOne-shot fetch. Reads GET /api/v1/skills/{owner}/{name} and writes the skill to disk without mutating your library or the server. Use this to preview or pin a specific skill without adding it.
skillrepo get <@owner/name> [--global] [--agent <list>] [--json]Flags
| Flag | Description |
|---|---|
--global | Write to the personal-scope path. |
--agent <list> | Comma-separated target override. |
--json | Emit a structured summary including the resolved version and the on-disk path. |
skillrepo listRenders your library as a table — owner, name, version, description. Uses the same cached ETag as update, so a repeat call hits a 304 and reads from cache.
skillrepo list [--json]--json emits the same data as a JSON array, suitable for piping into jq or another script.
skillrepo searchQueries /api/v1/skills/search for public skills matching query. Returns the same metadata you see in the catalog UI.
skillrepo search <query> [--limit <n>] [--json] [--semantic]Flags
| Flag | Description |
|---|---|
--limit <n> | Cap the result count. Defaults to 20. |
--semantic | Accepted but currently a no-op. Semantic search is a planned backend feature; the flag is reserved so scripts written today keep working when it ships. |
--json | Emit results as a JSON array. |
skillrepo addPOSTs to /api/v1/library, then fetches the single skill directly and writes it to disk. Requires a write-scoped access key. On 409 (the skill is already in your library), re-fetches the current version so your local state stays consistent with the server.
skillrepo add <@owner/name> [--global] [--agent <list>] [--json]Same flags as get.
skillrepo removeDELETEs from /api/v1/library and removes the local directory. Requires a write-scoped access key. The local delete is immediate and does not wait for a follow-up sync.
skillrepo remove <@owner/name> [--global] [--agent <list>] [--json]Same flags as get.
skillrepo session-syncInstalls (or removes) a Claude Code SessionStart hook that runs skillrepo update every time you open a Claude Code session. The hook lives in .claude/settings.local.json (per-developer, gitignored by default) and shells out to your global skillrepo binary.
skillrepo session-sync enable [--global] [--json]
skillrepo session-sync disable [--global] [--json]skillrepo init offers to install this hook on first run; if you said no (or passed --no-session-sync), turn it on later with session-sync enable.
session-sync enable does not auto-install the global binary the way init --yes does. It assumes the global install already exists; under npx without one present, it prints a clear “install globally first” message rather than mutating your global package set.
The hook never blocks your session
The hook command runs update --session-hook, which exits 0 on every failure — network outage, revoked key, disk error — and prints a one-line failure message. On POSIX a || true backstop is appended for belt-and-suspenders. Session starts are never blocked by sync failures, and a 304 Not Modified response runs silently with no per-session noise.
Flags
| Flag | Description |
|---|---|
--global | Operate on ~/.claude/settings.local.json so the hook fires in every Claude Code session across every project on your machine. |
--json | Emit structured JSON with action, path, and command fields for scripting. |
skillrepo uninstallSurgically removes every SkillRepo artifact from the current project. Non-SkillRepo entries in shared files are preserved. Runs offline, so a revoked or missing access key is not a problem. Interactive by default — prints a full list of what will be removed and prompts before touching anything.
skillrepo uninstall [--dry-run] [--yes] [--global] [--json]What gets removed
mcpServers.skillrepofrom.mcp.json,.cursor/mcp.json, and.vscode/mcp.json(plus the matchinginputsprompt in the VS Code config)SKILLREPO_ACCESS_KEY=...lines from.env.local- The SkillRepo section of
.gitignore - The SkillRepo SessionStart hook from
.claude/settings.local.json(if present) - The
.claude/skills/directory
With --global, also removes mcpServers.skillrepo from ~/.codeium/windsurf/mcp_config.json, the ~/.claude/skills/ global skill cache, and the ~/.claude/skillrepo/ directory (stored credentials and sync cache). Without it, your credential and other projects’ integrations are left untouched.
Flags
| Flag | Description |
|---|---|
--dry-run, -n | Print what would be removed and exit without touching any file. |
--yes, -y | Skip the confirmation prompt. |
--global | Also remove user-global state. |
--json | Emit a structured summary with removed[] and errors[] arrays. Useful for scripting. |
The command is idempotent — a second run with nothing left to remove exits 0 and prints “Nothing to remove.” If any artifact fails to remove (e.g. a read-only file), the command processes the rest, surfaces every error at the end, and exits with code 3.
Skill placement
skillrepo init writes skills to one of two project paths depending on the agent. Six of the seven supported agents share .agents/skills/, so a single cohort write reaches every cohort agent — no per-vendor duplication on disk. Both paths are gitignored automatically; skills are a per-developer cache, not committed content. Pass --agent claude, --agent agents, or --agent claude,agents to override detection. --agent none writes config and gitignore but skips placement entirely.
| Agent | Project skill path | Personal (--global) path | Auto-refresh today |
|---|---|---|---|
| Claude Code | .claude/skills/<name>/ | ~/.claude/skills/<name>/ | Yes — SessionStart hook installed by init |
| Cursor | .agents/skills/<name>/ | ~/.agents/skills/<name>/ | Manual skillrepo update |
| Windsurf | .agents/skills/<name>/ | ~/.codeium/windsurf/skills/<name>/ | Manual skillrepo update |
| Gemini CLI | .agents/skills/<name>/ | ~/.agents/skills/<name>/ | Manual skillrepo update |
| Codex CLI | .agents/skills/<name>/ | ~/.agents/skills/<name>/ | Manual skillrepo update |
| Cline | .agents/skills/<name>/ | ~/.agents/skills/<name>/ | Manual skillrepo update |
| GitHub Copilot | .agents/skills/<name>/ | — | Manual skillrepo update |
Copilot cloud agent (Codespaces, GitHub-hosted runners) is not supported — gitignored content is invisible to those runners by design. Local Copilot (VS Code, Copilot CLI) works as listed.
Environment variables
The CLI reads four environment variables. Each one has a higher-precedence override (a CLI flag or the config file) so you only need them in environments where flags and config aren’t practical — typically CI.
| Variable | Purpose |
|---|---|
SKILLREPO_ACCESS_KEY | Access key for any command. Takes precedence over the config file but not over --key. Use this in CI where writing a config file would leave credentials on disk. |
SKILLREPO_URL | Server URL. Same precedence as SKILLREPO_ACCESS_KEY. Use for self-hosted instances or to point a session at staging. |
SKILLREPO_TIMEOUT_MS | Per-request fetch timeout in milliseconds. Defaults to 30000. Set to 0 to disable. Raise this on slow networks where the default is triggering false-positive timeouts. |
NO_COLOR | Set to any non-empty value to disable ANSI color in CLI output. The CLI also respects the variable when piping into a non-TTY consumer. |
Exit codes
Every command exits with a stable code so CI scripts can branch on the failure class. Pass --verbose to print stack traces and retry attempts when diagnosing a non-zero exit.
| Code | Meaning |
|---|---|
0 | Success |
1 | Network error (unreachable server, DNS, timeout, exhausted retries) |
2 | Auth error (invalid key, revoked, suspended account) |
3 | Disk error (cannot read or write a file or directory) |
4 | Scope error (key lacks the required registry:write scope) |
5 | Validation error (bad flag, malformed identifier, unknown vendor) |
Retries
The CLI automatically retries transient server failures on every idempotent API call — specifically POST /auth/validate, GET /library, GET /skills/:owner/:name, and GET /skills/search. The read-only commands (update, get, list, search) and the validate plus sync calls inside init benefit automatically.
- Triggered by:
429,502,503,504, and raw network errors (DNS, TCP reset, timeout). - Not triggered by: 4xx auth and validation errors — those never succeed on retry — and
500, which is treated as a real-bug signal that should surface loudly rather than be masked. - Backoff: exponential with full jitter, three attempts total, base 500 ms, capped at 8 s per sleep.
- Write endpoints (
add,remove) are single-shot. A503mid-POSTcan mean either “body never reached the server” or “body processed, response lost,” and the client cannot distinguish — so retrying would risk a duplicate library mutation.
Self-hosted
The CLI works against any SkillRepo instance that implements the v1 API. Point it at a custom host with --url on init:
skillrepo init --url https://skillrepo.internal.company.comOr persist it via environment variables in your shell profile so every command picks it up without flags:
export SKILLREPO_URL=https://skillrepo.internal.company.com
export SKILLREPO_ACCESS_KEY=sk_live_...Troubleshooting
No access key configured
Run skillrepo init, pass --key, or set SKILLREPO_ACCESS_KEY.
Invalid access key format
Keys must start with sk_live_. The CLI trims leading and trailing whitespace from keys in every path — both the interactive prompt in init and the Bearer header used by every subsequent command — so pasting from email or a browser with a trailing newline is safe.
No agents detected in this directory
When the picker fires no detection signals (active session env vars, HOME traces, or project dotfiles), both default rows (.claude/skills/ and .agents/skills/) are pre-checked — you can run init --yes on a fresh clone and get a working library. If you want to skip placement entirely, pass --agent none (config and gitignore still happen). To target one path explicitly, pass --agent claude or --agent agents.
Rate limit exceeded — retried automatically and still getting 429
The CLI already retried with backoff. Wait a minute and retry. Pass --verbose to see per-attempt timings.
Windows note: skill updates use a best-effort atomic-rename pattern. A crash mid-update may leave a partial state; the next update run fully overwrites it.
Next steps
Read the Connections Guide for the team-onboarding flow, dig into the MCP reference if you’re building an external agent that talks to SkillRepo’s remote endpoint, or browse the REST API for publishing, library management, and search.