Welcome
What skl is, a 60-second quick start, and how to install the CLI.
An Agent Skill is a folder of instructions (a SKILL.md file) that teaches an AI coding
agent — Claude Code, Copilot, Cursor, Gemini, Junie, Kiro, plus every agent on the shared
.agents/skills/ standard (Codex, Zed, Goose, Amp, OpenCode, Roo, …) — how to do a specific
task, like reviewing a diff or writing a changelog.
skl manages them. You save a skill once, install it into any of those
agents, and a checked-in skl.json file lets you rebuild the exact same set of skills on
another machine with one command.
Quick start
Get a skill into your agent in under a minute — no account needed for public skills:
# 1 — install the CLI (macOS / Linux)
curl -fsSL https://useskl.com/install.sh | sh
# 2 — add a skill to your project
skl install alice/test-writer
The first install in a project asks which agents you use (the popular agents — Claude Code,
Codex, Cursor, Gemini, Copilot — are always listed, anything else it detects is added, and
Claude Code is pre-checked) — pick them and you're done. alice/test-writer is now copied
into .claude/skills/ (and every other agent you picked) and recorded in a skl.json you can
commit. Open your coding agent and the skill is there.
Prefer Homebrew or npm? See Install the CLI just below. Ready to save your own skill? See Saving & publishing.
Install the CLI
skl is a single command named skl, for macOS and Linux (arm64 and x64). Pick any
one channel below — they all install the same skl.
curl (quickest):
curl -fsSL https://useskl.com/install.sh | sh
Homebrew:
brew install loopdoop/tap/skl
npm:
npm install -g useskl
The npm package is named useskl, but the command it installs is skl — use skl
everywhere.
Direct download / Debian: grab a binary or .deb from the
releases page.
Check it worked with skl --version. Update any time with skl upgrade. (Windows and
Alpine/musl Linux aren't supported yet.)
What's next
The whole loop is install → rebuild → save. You've done install; here's where the rest
lives:
- Installing skills — add and manage skills, rebuild on another machine with
skl install, pin or float versions, and theskl.jsonfile. - Saving & publishing — sign in, save your own skills (private), set versions and visibility, and publish publicly.
- Reference — every command, the seven agent targets, the
SKILL.mdformat, and troubleshooting.
Commit skl.json to your repo and teammates rebuild the same skills with one skl install.
Installing skills
Add and rebuild skills, pin or float versions, and manage your skl.json.
Two commands install skills — and neither needs an account when the skills are public. Log in only to install a private skill.
skl install <skill> — add one skill
skl install <name> installs a skill into the current project and records it in skl.json. It
downloads the skill once and copies it into every agent you target. If there's no skl.json
yet, it creates one for you (asking which agents to target). (skl add is the same command —
install <name> routes to it.)
$ skl install alice/test-writer
✓ Installed alice/test-writer at latest (version 2)
alice/test-writer@2 → ./.claude/skills/test-writer/
↻ Restart your code agent or reload skills to take effect
skl install — rebuild everything
skl install re-installs all skills from skl.json — the command to run on a fresh
checkout or a new machine. Pinned entries re-land the exact recorded version; floating entries
re-resolve to the newest version, and GitHub URL entries are re-fetched from GitHub (see
Pin or float a version below). A skill
that is already installed and unchanged is left as-is (no re-download); a skill you've
edited locally is protected — it's skipped with a warning rather than overwritten (re-run
with --force to overwrite).
$ skl install
Rebuilding 2 skills from ./skl.json …
✓ alice/test-writer@2 → ./.claude/skills/test-writer/
✓ bob/changelog@1 → ./.claude/skills/changelog/ (up to date)
↻ Restart your code agent or reload skills to take effect
✓ Rebuilt ./skl.json — 1 installed, 1 up to date.
Coming from npm?
npm install <pkg>adds one package;npm installrebuilds everything. skl works the same way:skl install alice/test-writeradds a single skill (it just routes toskl add), while bareskl installrebuilds the whole project. See the npm cheat sheet.
Install straight from a GitHub URL
Found a skill on GitHub? Install it without cloning — just give skl install the repo URL:
skl install https://github.com/owner/repo
skl install https://github.com/owner/repo/tree/main/skills/my-skill
skl finds the SKILL.md in the repo (or the subfolder you point at) and asks what to do:
$ skl install https://github.com/owner/repo
? Save https://github.com/owner/repo to your registry as a private skill? (No = install locally only) › No
✓ Installed my-skill from GitHub (version 1.0)
my-skill@1.0 → ./.claude/skills/my-skill/
Tracked in skl.json as https://github.com/owner/repo
↻ Restart your code agent or reload skills to take effect
You get two choices:
- Install locally only (the default) — skl copies the skill straight from GitHub into your
agents and records the URL in
skl.json. No account needed. On askl installrebuild, skl re-fetches it from GitHub each time. - Save to your registry as a private skill — skl imports the repo to useskl.com as a private skill (under your namespace), then installs it like any other saved skill. This needs an account with a verified email. Use it to keep your own copy you can version and share.
Skip the prompt with a flag:
skl install https://github.com/owner/repo --local # local only, record the URL
skl install https://github.com/owner/repo --private # save to your registry, then install
In a script or CI (no terminal to prompt), skl install <url> defaults to local. If you choose
to save but aren't logged in, skl tells you to run skl login first (or install locally without an
account).
If you choose to save but already have a skill with that name in your registry, skl won't make you rename it — it asks what you actually meant:
You already own you/my-skill in your registry. What would you like to do?
> Install your registry skill (you/my-skill)
Download this skill from GitHub directly (local only, not saved)
Pick the first to install the copy you already have, or the second to grab this GitHub version locally.
A locally-installed GitHub skill is untracked — it has no saved version, so skl always re-fetches it on rebuild and can't tell if you've edited it locally. If you want versioning, drift detection, and sharing, use
--private(or save it withskl save).
If the URL points at a repo with more than one skill, skl asks you to be more specific — point
the URL at the skill's folder with …/tree/<branch>/<path-to-the-skill>.
Install for yourself, everywhere (-g)
Everything above installs into one project. To make a skill available in every project,
install it globally with -g/--global — it lands in the agent's personal skills folder
under your home directory (e.g. ~/.claude/skills/) instead of the project:
$ skl install alice/test-writer -g
✓ Installed alice/test-writer globally (version 2)
alice/test-writer@2 → ~/.claude/skills/test-writer/
Global installs aren't tracked in skl.json — delete the folder to remove.
↻ Restart your code agent or reload skills to take effect
- skl asks which agents to target (same picker as
skl init: the popular agents always listed plus any it detects on your machine,claudepre-checked); pass--targets claude,cursorto skip the prompt. In a script (no terminal), it defaults toclaude. - Global installs are untracked — no
skl.jsonis read or written, so there's nothing to rebuild (skl install -gwith no name is an error) and nothing to commit. To remove a global skill, delete its folder. - Installing a GitHub URL with
-gisn't supported yet — install it into a project instead, or save it to your registry first.
Re-installing is safe
Running skl install again (single skill or the whole project) does the least work needed:
- Already up to date — if the exact version is already installed and unchanged, it's a
no-op: skl reports
already up to dateand doesn't re-download or re-copy anything. - Locally edited — if you've hand-edited a skill's files after installing, skl won't
silently overwrite them. A single
skl install <name>asks what to do (abort and save your edits first, or discard them); a project-wideskl installskips that skill with a warning and leaves your edits in place. Re-run with--force(-f) to overwrite.
✓ skl/skl is already up to date (version 2)
skl/skl@2 → ./.claude/skills/skl/
Already installed — nothing to do (use --force to reinstall).
Public vs. private skills
Public skills install with no login. Sharing a project is as simple as committing
skl.json — anyone can skl install it.
Private skills need a login, and you must be the owner (or someone it's shared with):
-
skl install <skill>of a private skill while logged out tells you to log in:✗ Can't install "acme/secret" — it's private or doesn't exist. If it's private, run `skl login` to install skills you have access to. -
skl installon a mix of public and private skills while logged out installs the public ones, skips the private ones with a warning, and still succeeds:Rebuilding 2 skills from ./skl.json … ✓ alice/test-writer@2 → ./.claude/skills/test-writer/ ⚠ acme/secret@1 — private, skipped (run `skl login`) ↻ Restart your code agent or reload skills to take effect ✓ Rebuilt ./skl.json — 1 installed. ⚠ 1 skill requires permission — run `skl login` to install private skills you have access to.Log in and re-run
skl installto pick up the private ones.
Pin or float a version
Each skill in skl.json is either pinned to an exact version or floating on the
latest:
- Pin = always install this exact version (e.g.
2). Every machine gets identical results.skl install alice/test-writer@2pins2, and--lock-version(-l) pins whatever the current version resolves to. - Float = always grab the newest version. Handy, but it can differ between machines and
over time. A bare
skl install alice/test-writerfloats — this is the default.
A bare skl install alice/test-writer floats to latest (no prompt); add --lock-version/-l
to pin instead. To move a pinned skill to a newer version, skl install it again at the new
version (e.g. @3).
The skl.json file
skl.json lives in your project root and records what the project installs — commit it so
teammates and other machines rebuild the same set. It looks like this:
{
"schemaVersion": 1,
"targets": ["claude", "agents"],
"skills": [
"alice/test-writer@2",
"bob/changelog",
"https://github.com/owner/repo"
]
}
targets— which agents every skill is copied into (see Reference → Targets).skills— each entry is either a"username/skill-name"(with an optional@versionto pin; no@versionfloats to the latest) or a GitHub URL (added byskl install <url> --local, re-fetched from GitHub on every rebuild).
Other commands
-
skl list— list the skills installed in this project. -
skl uninstall <name>— remove a skill (its files and itsskl.jsonentry).skl removeis an alias. If you hand-edited the installed copy and haven't saved the change,uninstallwon't silently delete it — it warns and asks first (or stops in a script); pass--force/-fto delete anyway. -
skl scan(aliasskl outdated) — check the project's skills for drift (edited-since-save, updates available, missing or extra folders). Read-only; it changes nothing. It's broader thannpm outdated— it reports local edits and missing folders too, not just newer versions.
Saving & publishing
Sign in, save a skill to your own registry, set version numbers and visibility, publish publicly, and delete a skill.
Saving puts your own skill into your registry on useskl.com — private by default, yours to install anywhere. Publishing is the same thing made public so others can find it. Both need an account; installing public skills does not.
Sign in
-
Create an account at useskl.com: pick a username (it becomes the prefix for everything you save — so
acmesavesacme/code-review) and a password. -
Verify your email by clicking the link in the sign-up email. This is required before you can save or publish.
-
Log in:
$ skl login acme ? Password for "acme": ▪▪▪▪▪▪▪▪▪▪ ✓ Logged in as acme → https://useskl.com • `skl publish` will use this server ("default").
skl login signs you in and sets this machine up automatically — there's nothing to copy or
paste. (The password is masked as you type.) Run skl logout to sign out of this machine.
Signed up with GitHub or Google? Your account has no password, so log in with a pairing code instead: on useskl.com go to Settings → Devices → Link a new device to get a single-use code (valid 10 minutes), then run:
skl login --code
and paste the code when prompted. A bare skl login (no username) also works — it asks which
way you want to log in (password or pairing code).
Save a skill
A skill is a folder with a SKILL.md at its root. The top section (the part between the
--- lines) sets a name and a version:
$ cat my-skill/SKILL.md
---
name: code-review
description: Reviews a diff for correctness and style.
metadata:
version: "1"
---
# Code Review
...
$ skl save ./my-skill
✓ Yay! Skill acme/code-review@1 is published successfully. (8 files, 3.4 KB) [private]
The saved name comes from name: in SKILL.md — with username acme, it lands as
acme/code-review. A saved skill is private: yours alone until you choose to publish it.
Preview without uploading with --dry-run (no account needed):
$ skl save ./my-skill --dry-run
Dry run — nothing uploaded.
Would publish: code-review@1
Visibility: private
Full name (your-username/code-review) is set from your token at publish.
Files: 8 Size: 3.4 KB
Digest: sha256:9f2c…
Tokens: 812 (cl100k)
(.skl tracking file is generated on a real publish, not a dry run)
✓ frontmatter valid ✓ no symlinks ✓ name ok
Version numbers
Version numbers are yours to choose. The simplest convention is to start at 1 and bump by
one each release — 1, 2, 3, 4. If a skill already uses semantic versions like
0.1.2, keep that style. The newest version you save is the "latest" that floating
installs pick up.
Always quote the version (version: "1", version: "1.10"). Unquoted, 1.10 is read as
the number 1.1.
Versions can't be changed once saved. Re-saving the same version with different content fails — bump the version instead:
✗ acme/code-review@1 already exists — versions are immutable.
Bump metadata.version in SKILL.md and publish again.
skl never bumps the version silently — in a terminal it offers the next number ("Bump
metadata.version to "2" and publish?") and only writes it when you say yes; in a script it
just fails with the error above. Likewise, if your SKILL.md has no metadata.version yet,
save/publish offers to add "1" for you. Re-saving a version whose content hasn't changed
is a friendly no-op, not an error.
Public or private
A skill you skl save is private — visible only to you, hidden from others' catalogs, and
installable only by you or people you share it with.
To share a skill with the world, publish it public — either flip the visibility on the skill's page on useskl.com, or pass the explicit flag:
$ skl publish ./my-skill --public
✓ Yay! Skill acme/code-review@1 is published successfully. (8 files, 3.4 KB)
How the visibility of a skill is decided:
- First publish of a brand-new skill:
skl savemakes it private;skl publishwith no flag makes it public. - Re-publishing an existing skill:
skl publishwith no flag keeps the current visibility — so publishing a new version of a private skill does not make it public. To change visibility from the CLI, pass--publicor--privateexplicitly (an explicit flag always wins). skl saveis always explicitly private — re-saving a skill you've since made public flips it back to private. Once a skill is public, publish new versions withskl publish.- You can also change visibility any time from the skill's page on useskl.com.
Delete a skill
Delete a skill from its page on useskl.com → Manage → Danger zone. As a guard, you retype the full name to confirm.
- The skill becomes unavailable to everyone, including you — it leaves the catalog and can no longer be installed. Copies already on machines keep working.
- The name is freed; you can save a new skill under it later.
- There is no undo — treat deletion as permanent. To just hide a public skill, make it private instead.
Reference
Command reference, the seven agent targets, the SKILL.md format, and troubleshooting.
This page covers the everyday surface. Every command documents its full flag set — run
skl <command> --help.
Commands
| Command | What it does | Aliases |
|---|---|---|
skl install <name|github-url> | Install one skill (from useskl.com or a GitHub URL) and record it | i, in, a, add |
skl install | Re-install all skills from skl.json | i, in, a, add |
skl uninstall <name> | Remove a skill (files + skl.json entry); guards unsaved local edits — --force/-f to override | remove, rm, un, r |
skl list | List the skills in this project | ls, la, ll |
skl scan | Check the project's skills for drift (read-only) | outdated |
skl info <name> | Show a skill's details | view, show |
skl save <folder> | Save a skill folder to your registry as private (the privacy-first default) | |
skl publish <folder> | Publish a skill folder to useskl.com — public on first publish; re-publish keeps the current visibility (--public/--private to change it) | pub |
skl login [username] | Sign in with your password, or --code with a website pairing code (GitHub/Google accounts) | adduser, add-user |
skl logout | Sign out on this machine | |
skl config | Manage backend servers | c |
skl init | Create a skl.json (choose which agents to target) | |
skl upgrade | Update the skl CLI itself | up |
The aliases mirror npm's own shortcuts so npm habits carry over — see the
npm cheat sheet. install is the one install verb (add/a are aliases of it):
skl install <name> adds one skill (like npm install <pkg>) while bare skl install rebuilds
everything from skl.json (like npm ci) — and so skl add foo/bar installs one while bare
skl add rebuilds. There is no skl update→upgrade alias, because skl upgrade updates the CLI
itself, not your skills.
Common flags: --help on any command, --json for machine-readable output, --quiet,
--verbose. skl install --prune deletes skill folders left behind by an agent you no
longer target.
Install flags (skl install <name> / skl add <name>, also passed through by skl install):
--lock-version/-l— pin the resolved version inskl.jsoninstead of floating to latest (the default). Equivalent to writing@<version>yourself.--latest— explicitly float to latest (the default; kept for clarity in scripts).--force/-f— overwrite a locally-edited skill folder instead of skipping/prompting.--private/--local— only for a GitHub URL.--privatesaves the repo to your registry as a private skill, then installs it;--localinstalls it locally only and records the URL. Without a flag, skl prompts (and defaults to local in a script). See Installing → Install straight from a GitHub URL.-g/--global— install into the agents' personal skills folders under your home directory (e.g.~/.claude/skills/) instead of the project. Untracked (noskl.json). See Installing → Install for yourself, everywhere.--targets <ids>— pick the agent targets non-interactively (comma-separated target ids) when skl would otherwise prompt: bootstrapping a newskl.json, or a-ginstall.
A re-install does the least work: a skill already installed at the target version and
unchanged is reported up to date and not re-downloaded; a skill you've edited locally is
protected (skipped/prompted, not silently overwritten) unless you pass --force.
Coming from npm
If you know npm, skl's verbs map almost one-to-one:
| You'd type in npm | In skl | Notes |
|---|---|---|
npm install | skl install | Rebuild everything from the manifest (npm ci equivalent). |
npm install <pkg> | skl install <name> or skl add <name> | Both add one skill; install is canonical, add is an alias. |
npm uninstall <pkg> | skl uninstall <name> | remove is an alias. |
npm ls | skl list | |
npm view <pkg> | skl info <name> | |
npm outdated | skl scan (skl outdated) | skl's check is broader (drift + missing + updates). |
npm publish | skl publish <folder> | Versions are immutable; bump by hand. |
npm login | skl login | Mints a device-bound key. |
npm config | skl config | skl config manages backend servers. |
npm install -g npm (self-update) | skl upgrade | Note: not skl update. |
skl has no analog for npm run, npm test, npm version, or npx. Forking a skill into your
namespace is a website feature (there is no skl fork CLI command).
Targets (the seven canonical targets)
A target is which agent a skill is copied into. Targets are set once per project (in
skl.json), and every skill is copied into each one. Each maps to a folder in your project:
| Target | Folder | Agent |
|---|---|---|
claude | .claude/skills/ | Claude Code (also read by Goose, Amp, OpenCode) |
copilot | .github/skills/ | GitHub Copilot |
cursor | .cursor/skills/ | Cursor (2.4+) |
gemini | .gemini/skills/ | Gemini CLI |
junie | .junie/skills/ | JetBrains Junie |
kiro | .kiro/skills/ | Kiro (Amazon Q successor) |
agents | .agents/skills/ | The cross-agent standard — Codex, Zed, Goose, Amp, OpenCode, Roo, pi, grok |
Legacy
codex/groktarget ids are still accepted as input (inskl.jsonor--targets) and canonicalize toagents— they are no longer separate canonical targets.
A skill named acme/code-review lands as code-review/ inside each target's folder. Skills
are copied, never symlinked, so each agent reads its own copy.
skl init sets a project's targets up front (and re-running it reconfigures them):
The SKILL.md format
A skill folder must contain a SKILL.md at its root. The block between the --- lines (the
frontmatter) sets these fields:
---
name: code-review
description: Reviews a diff for correctness and style.
metadata:
version: "1"
---
# Code Review
Instructions the agent reads…
| Field | Required | Notes |
|---|---|---|
name | yes | The skill's short name; the full name is username/name once saved |
description | yes | One-line summary shown in catalogs and skl info |
metadata.version | yes | Your version number. Quote it ("1", "1.10") |
The folder may contain any files the skill needs, but no symlinks, and nothing oversized.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Can't install "…" — it's private or doesn't exist | Installing a private skill while logged out (public skills need no login) | Run skl login — you must own the skill or have it shared with you |
… — private, skipped (run skl login) during install | A private entry in the manifest, and you're logged out | install lands the public skills anyway; skl login and re-run to add the private ones |
… — modified locally, skipped (use --force …) during install | A landed skill folder was edited after install; skl won't silently overwrite it | Save your edits, or re-run with --force to discard them and reinstall |
Your email address is not verified | Saving and publishing need a verified email | Click the link in your sign-up email (or re-send it from useskl.com), then try again |
… already exists — versions are immutable | Re-saving a version with changed content (versions can't change) | Bump the version in SKILL.md and try again (in a terminal, skl offers the bump for you) |
Incorrect username or password | Wrong sign-in details | Check them, or reset your password on useskl.com |
No skl.json in this directory | install / uninstall / list need a project manifest | Run skl init (or skl add) first, or cd to the project root |
| A skill folder is left behind after dropping a target | install never deletes silently | Run skl install --prune |
That location contains more than one skill (GitHub URL) | The repo URL points at a folder with several skills | Point the URL at the skill's folder: …/tree/<branch>/<path-to-the-skill> |
No SKILL.md was found at that GitHub location | The repo (or subfolder) has no SKILL.md | Check the URL points at a skill folder; add /tree/<branch>/<path> if it's nested |
GitHub repository not found (or private) | Bad URL, or a private repo | skl installs only from public GitHub repos; check the URL |
You already own … when saving a GitHub URL (--private) | The repo's skill name matches a skill you already have | Not an error to fix — skl asks whether to install your existing skill or fetch this one from GitHub directly. Non-interactively (--json): run skl install <you>/<name>, or re-run with --local |
Always quote the version in
SKILL.md. Unquoted,1.10is read as the number1.1.
