skills-manager CLI
CLI companion to vercel-labs/skills — backup, restore, and symlink AI agent skills via GitHub.
Scope boundary: This tool backs up and syncs skills you already have. It does NOT install new skills from the registry — that'snpx skills add. If the user wants to install a new skill, point them tonpx skills add <repo>instead.
Quick Reference
| Goal | Command |
|---|---|
| Backup skills to GitHub | sm push |
| Restore skills on new machine | sm pull --repo owner/name |
| Re-link skills to agents | sm link |
| Link skills to a project | sm link --project |
Invocation
# If globally installed
sm push # short alias
skills-manager push # full name
# Without installing — use the bundled wrapper script
export SM="$HOME/.agents/skills/skills-manager/scripts/sm.sh"
"$SM" pushRequires Node.js >= 20. GitHub CLI (gh) recommended for auth.
If neither sm nor skills-manager is found, install first:
npm install -g @tc9011/skills-managerKey Paths
| Path | Purpose |
|---|---|
~/.agents/ | Git repo root (push/pull target) |
~/.agents/skills/ | Canonical skills directory |
~/.agents/.skill-lock.json | Lock file (READ ONLY — owned by vercel-labs/skills) |
Authentication
Auth is optional. If git already has credentials configured (SSH keys, macOS Keychain, credential manager, etc.), push/pull work without any extra setup.
When git cannot authenticate on its own, the CLI looks for a token in this order:
gh auth token— GitHub CLI (recommended)$GITHUB_TOKEN— environment variable$GH_TOKEN— environment variable
If none are found, git attempts the operation without a token — this works for public repos but fails for private ones.
The link command never requires authentication.
Fixing Auth Failures
If push/pull fails with a permission or authentication error:
- Check if
ghis installed: rungh --version - If
ghexists: rungh auth loginto authenticate, then retry - If
ghmissing: set a token:export GITHUB_TOKEN=ghp_your_token_here, then retry - If using SSH: ensure
~/.ssh/has a valid key added to GitHub andoriginuses thegit@github.com:URL format
Tokens are used transiently in-memory — they are never persisted to .git/config.
Commands
push
Commit and push ~/.agents/ to GitHub.
sm push # auto-generated commit message
sm push -m "add new skill" # custom messageFirst-time behavior:
- If
~/.agents/is not a git repo, auto-runsgit init - If no
originremote exists, prompts forowner/name - If
ghCLI is installed, offers to create the repo on GitHub automatically - If
ghis not installed, shows a note telling the user to create the repo manually at https://github.com/new
Possible outcomes:
Skills pushed successfully!— new commit created and pushedUnpushed commits pushed successfully!— working tree clean, but local was aheadNo changes to push — already up to date.— nothing newPush rejected— see Troubleshooting below
pull
Pull from GitHub. Auto-runs link afterward unless --skip-link is passed.
sm pull --repo owner/name # first time — specify repo
sm pull # subsequent runs — uses existing remote
sm pull --skip-link # pull only, don't re-linkFirst-time behavior:
- If no
--repoand no existingoriginremote, prompts forowner/name - If
~/.agents/doesn't exist yet, clones into it
Possible outcomes:
Skills cloned successfully!— fresh clone on new machine, auto-runs linkSkills updated from remote.— pulled new changes, auto-runs linkAlready up to date.— no new changes, skips linkRebase conflict— see Troubleshooting below
link (global mode)
Read .skill-lock.json, create relative symlinks from each agent's global skills directory to ~/.agents/skills/.
sm link # interactive prompt
sm link --agents cursor opencode # non-interactive, skip promptInteractive behavior:
The agent selector has two sections:
- Locked section — 10 universal agents (amp, cline, codex, cursor, gemini-cli, github-copilot, kimi-cli, opencode, replit, universal) are always included because they share
~/.agents/skills/as their path. - Searchable list — 31 non-universal agents. Type to search/filter.
Pre-selection priority: saved config > .skill-lock.json > agents already existing on disk.
When --agents is provided, the interactive prompt is skipped entirely. Use this for scripting and AI agent automation:
sm link --agents cursor opencode claude-codelink --project
Link or copy skills to the current working directory.
sm link --project # interactive
sm link --project --agents cursor claude-code --skills my-skill # non-interactive (copy is default)
sm link --project --agents cursor claude-code --skills my-skill --mode symlink # explicit symlinkInteractive flow (3 steps):
- Select skills (
--skillsto skip) — choose which skills to include - Select copy/symlink — in practice this prompt is skipped because
--modedefaults tocopyin the CLI. Only appears iflinkCommandis called programmatically without defaults - Select agents (
--agentsto skip) — same searchable multiselect with locked universal section
Copy vs symlink:
copy(default, recommended) — creates independent files in project. Overwrites existing skill dirssymlink— creates absolute symlinks pointing to~/.agents/skills/. Existing non-symlink dirs are skipped
Agents that share the same projectPath (e.g., trae and trae-cn both use .trae/skills) are deduplicated — one operation per unique path.
For AI agents: the fully non-interactive version is almost always what you want:
sm link --project --agents cursor opencode claude-code --skills my-skill --mode copyCommon Workflows
First-time setup on a new machine
npm install -g @tc9011/skills-manager
sm pull --repo owner/my-skills # clone + auto-linkDaily sync
sm pull # fetch latest + re-link
sm push # backup local changesProject-level skills
cd /path/to/project
sm link --project --skills my-skill --agents cursor opencode claude-codeRe-link after installing new skills
npx skills add some-repo # install via vercel-labs/skills
sm link # re-link to all agents
sm push # backup the new skillTroubleshooting
Push rejected (remote ahead)
Error: Push rejected — remote contains commits that you do not have locally.
Fix:
sm pull # pulls and rebases
sm push # retryOr manually:
cd ~/.agents
git pull --rebase origin main
sm pushRebase conflict on pull
Error: Rebase conflict detected. Your local skills have diverged from the remote.
The CLI auto-aborts the failed rebase. To resolve:
cd ~/.agents
git fetch origin
git rebase origin/main # resolve conflicts manually
# OR if you want to discard local changes:
git reset --hard origin/mainNo skills found
Error: No skills found in ~/.agents/skills.
This means ~/.agents/skills/ is empty or doesn't exist. Either:
- Run
sm pull --repo owner/nameto restore from backup - Install skills via
npx skills add <repo>
Unknown agent IDs
Error: Unknown agent ID(s): foo. Run with no --agents to see available IDs.
The --agents flag only accepts valid agent IDs from the 46-agent registry. Run sm link without --agents to see the interactive list.
Auth failure during push/pull
Symptom: Git errors like Authentication failed, Permission denied, or Repository not found.
This means git has no credentials and no token was found. See the "Fixing Auth Failures" section above.
~/.agents/ is not a git repo
On first push or pull, the CLI auto-initializes git. If this somehow fails:
cd ~/.agents
git init
git remote add origin https://github.com/owner/my-skills.git
sm pushSupported Agents (41)
- 10 universal (always locked in interactive prompts): amp, cline, codex, cursor, gemini-cli, github-copilot, kimi-cli, opencode, replit, universal
- 31 non-universal (appear in searchable list): claude-code, windsurf, trae, roo, augment, continue, goose, kilo, kode, and more
Constraints
.skill-lock.jsonis READ ONLY — never create, modify, or delete it~/.agents/is the git repo root (not~/.agents/skills/)- Global link = relative symlinks; project link = absolute symlinks or copies
- Auth tokens are transient in-memory only — never persisted to
.git/config - This tool does NOT install skills from the registry — use
npx skills addfor that