CLI reference
This page documents every skillmd command, its arguments, and its flags. If a flag isn't listed here, it doesn't exist.
Install
The package is skillmds on npm. It installs a binary named skillmd. You need Node 18 or later.
npm i -g skillmds Running skillmd with no arguments opens an interactive menu when you're in a terminal. Every command below also works non-interactively, which is what you want in scripts and CI.
Command overview
| Command | Alias | Purpose |
|---|---|---|
lint [target] | Validate a SKILL.md and print a quality score | |
scan [target] | Scan for scripts, network calls, and secret access | |
rules [id] | List lint rules, or show details for one | |
init [name] | Scaffold a new SKILL.md | |
search <query> | Search the registry | |
info <slug> | Show registry details for one skill | |
add <source> | Install a skill from the registry, GitHub, a gist, or a local path | |
list | ls | List installed skills with their scope, agents, and source |
remove [names...] | rm | Remove installed skills, or unlink them from one agent |
update [names...] | Re-fetch installed skills from the source they came from | |
check [names...] | Report which installed skills have updates | |
publish [target] | submit | Publish a skill to the registry |
login | Store a personal access token | |
logout | Remove the stored token |
check is its own command as of 1.2.0. It used to be a second name for lint, so a script that runs skillmd check . to validate a skill should now run skillmd lint ..
Global options
These work with any subcommand. Put them after the subcommand name.
| Flag | Effect |
|---|---|
--json | Print machine-readable output instead of text |
--token <token> | Use this token for this call instead of the stored one |
--api <url> | Use this API base URL instead of the default |
--insecure-http | Allow an http:// API base. Required for one, and only meant for local development. |
--version | Print the installed CLI version |
skillmd lint . --json
skillmd add anthropic/pdf --token sk_live_xxxxx --api https://staging.skillmd.com Only publish requires a token. Every other command works unauthenticated. The CLI resolves the token in this order: --token, then the SKILLMD_TOKEN environment variable, then ~/.skillmd/config.json, then nothing. It resolves the API base the same way: --api, then SKILLMD_API, then the stored config, then https://api.skillmd.com. A stored token records the API base it was saved for and is only ever sent there, so pointing the CLI at another registry never leaks it. Prefer skillmd login or SKILLMD_TOKEN over --token: a token typed on the command line lands in your shell history and in every process listing on the machine, and the CLI says so.
lint
Validates a SKILL.md against the format rules and prints a quality score.
Argument: [target], a local path or GitHub source. Defaults to ..
| Flag | Effect |
|---|---|
--format <fmt> | text, json, sarif, or github. Default text. |
--strict | Treat warnings as failures |
--fail-on-warning | Exit non-zero if any warning is reported |
--fix | Apply safe fixes automatically, such as inserting a missing license |
--errors-only | Suppress warnings from the output |
skillmd lint ./my-skill
skillmd lint ./my-skill --format sarif
skillmd lint . --strict --fail-on-warning Use --format sarif or --format github to feed lint results into CI annotations.
scan
Runs a security scan over a skill: scripts it executes, network calls it makes, and secret access it declares.
Argument: [target], defaults to ..
| Flag | Effect |
|---|---|
--deny <flags...> | Exit non-zero if any of the named flags is present, for example executes_scripts |
--format <fmt> | text or json |
skillmd scan .
skillmd scan . --deny executes_scripts network_access --deny is what you wire into a CI gate: fail the build if a skill executes scripts or reaches the network, without reading the full report by hand.
rules
Lists every lint rule the CLI checks, or shows one rule in detail.
Argument: [id], a rule id such as SK010.
Flag: --json.
skillmd rules
skillmd rules SK010 --json Run skillmd rules with no argument when a lint error references a rule id you don't recognize.
init
Scaffolds a new SKILL.md from a template.
Argument: [name].
| Flag | Effect |
|---|---|
--name <name> | Skill name, if you didn't pass it as the argument |
--description <text> | Description written into the frontmatter |
--license <license> | License identifier. Default MIT. |
-y, --yes | Skip prompts and use the values passed as flags |
skillmd init my-skill --description "Helps with X" --yes
skillmd init --name my-skill --license Apache-2.0 The file is written to <dir>/<slug>/SKILL.md, where <slug> is derived from the name.
search
Searches the public registry.
Argument: <query>, required.
| Flag | Effect |
|---|---|
--category <slug> | Restrict to one category |
--verified | Restrict to skills that passed safety review |
--type <type> | single or pack |
--min-rating <n> | Minimum rating threshold |
--limit <n> | Maximum results. Default 20. |
--json | Machine-readable output |
skillmd search "pdf extraction" --verified --limit 10
skillmd search "changelog" --category writing --type single info
Shows registry details for one skill: description, rating, verification status, and version history.
Argument: <slug>, required, in <owner>/<name> form.
This command only takes the global options.
skillmd info anthropic/pdf
skillmd info anthropic/pdf --json add
Installs a skill from a registry slug, a GitHub source, a gist, or a local path. The CLI lints the skill before writing it to disk.
Argument: <source>, required. One of:
owner/name— a registry slug.owner/repo#ref— a GitHub repo at a branch, tag, or commit.owner/repo/sub/path— a subdirectory of a repo.owner/repo@skill— one named skill inside a repo or pack.github:owner/repoorgh:owner/repo— read a bareowner/nameas GitHub instead of a registry slug.- A GitHub
tree/orblob/URL. The ref in the URL is kept. - A gist URL.
- A local directory.
GitLab and git@ sources aren't supported; the CLI says so and tells you to clone the repo and install from the path.
| Flag | Effect |
|---|---|
-g, --global | Install to your user-level skills directories, available in every project |
-p, --project | Install into the current directory's agent folders, committed with the project |
-a, --agent <agents...> | Target one or more agents by name (default: every agent detected on your machine) |
-s, --skill <names...> | From a pack, install only the named skills. Use * for all. |
-l, --list | List the skills the source contains and install nothing |
--ref <ref> | Branch, tag, or commit to read a GitHub source at. Overrides a #ref in the source. |
--mode <mode> | link (default) links each agent directory to one canonical copy; copy writes real files into every agent directory. --copy is still accepted as the old spelling. |
--force | Replace a skill that was installed from a different source, or a directory the lock file doesn't track |
-y, --yes | Skip prompts. The scope is auto-detected, see below. |
--skip-lint | Skip the pre-install lint check |
--deny <flags...> | Refuse to install if a scan flag is present, for example network_access |
--insecure-http | Allow an http:// API base for this install (local development) |
skillmd add anthropic/pdf
skillmd add anthropic/pdf -a claude-code cursor -g
skillmd add anthropic/pdf-pack -s changelog release-notes
skillmd add owner/repo/skills/pdf#main -p
skillmd add owner/repo --list
skillmd add ./local-skill --skip-lint
skillmd add owner/repo --deny executes_scripts Where skills land
A skill's files are written once, to a canonical location, and each agent you chose gets a link to that one copy:
| Scope | Flag | Canonical copy | Agent links | Lock file |
|---|---|---|---|---|
| Project | -p, --project | .agents/skills/<name> | ./<agent-dir>/skills/<name> | skills-lock.json, commit it |
| Global | -g, --global | ~/.agents/skills/<name> | ~/<agent-dir>/skills/<name> | ~/.skillmd/lock.json |
The link is a junction on Windows and a symlink everywhere else, so one update reaches every agent at once. If the filesystem refuses to make one, the CLI copies the files instead and tells you. --mode copy asks for copies up front. A project install only writes into agents the project already uses, or the ones you name with -a, so it never invents a folder for an agent you don't run.
In a terminal, add asks for the scope, Project or Global, then which of your detected agents to link into, and remembers the agent choice for next time. When there's no one to ask — -y, --json, piped input, or a run inside a coding agent or CI — the scope is auto-detected: project if the current directory carries .git, package.json, pyproject.toml, Cargo.toml, go.mod, AGENTS.md, CLAUDE.md, skills-lock.json, or an agent folder, and global otherwise. The run says which it picked. A piped run with neither -y nor a scope flag exits 1 with a hint rather than guessing, so running add from your Desktop never scatters agent folders there.
add won't replace a skill that came from a different source, or a directory that isn't in the lock file, unless you pass --force.
list
Alias: ls. Lists installed skills across both scopes by default, one row per skill: name, scope, the agents it's linked into, the link mode, and the source it came from.
| Flag | Effect |
|---|---|
-g, --global | Only your user-level skills |
-p, --project | Only this project's skills |
-a, --agent <agents...> | Only skills linked into these agents |
--json | Machine-readable output |
skillmd list
skillmd list -p -a claude-code
skillmd list -g --json A skill that's on disk but has no lock entry — installed by hand, or by a CLI older than 1.2.0 — is tagged untracked. update skips those; re-run skillmd add on one to start tracking it.
remove
Alias: rm. Removes installed skills: the agent links, the canonical copy, and the lock entry.
Argument: [names...], optional. With no names you get a picker.
| Flag | Effect |
|---|---|
-g, --global | Only your user-level skills |
-p, --project | Only this project's skills |
-a, --agent <agents...> | Unlink from these agents only. The canonical copy stays. |
--all | Remove every skill in the scope. Can't be combined with names. |
-y, --yes | Skip the confirmation |
--json | Machine-readable output |
skillmd remove
skillmd remove my-skill
skillmd remove my-skill -a cursor
skillmd rm my-skill other-skill -g
skillmd rm --all -p -y Both scopes are searched unless you narrow them. Without -y it confirms first, and it exits 1 when nothing matched.
update
Re-fetches each skill's full set of files from the source recorded for it in the lock file, re-lints it, and rewrites it on disk if it changed. A skill whose recorded commit hasn't moved is left alone.
Argument: [names...], defaults to every tracked skill.
| Flag | Effect |
|---|---|
--check | Report what has updates and write nothing |
-g, --global | Only your user-level skills |
-p, --project | Only this project's skills |
--json | Machine-readable output |
skillmd update
skillmd update anthropic-pdf -g
skillmd update --check --json Untracked skills are listed and skipped — re-run skillmd add on one to bring it under the lock file. Exit code is 0 when every skill was handled and 1 if any failed, which makes it safe to run in a scheduled job.
check
Reports which installed skills have updates available, without touching anything. Same as update --check.
Argument: [names...], defaults to every tracked skill.
Flags: -g, -p, and --json, exactly as on update.
skillmd check
skillmd check -p --json publish
Alias: submit. Publishes a skill to the registry. Requires a stored token, and refuses to publish if lint reports errors.
Argument: [target], defaults to ..
| Flag | Effect |
|---|---|
--type <type> | single or pack. Default single. |
--force | Publish despite lint warnings. Does not override lint errors. |
--dry-run | Run the lint check only, without publishing |
skillmd publish ./my-skill --dry-run
skillmd publish ./my-skill --type pack
skillmd submit ./my-skill --force Every publish goes through a safety review before it becomes visible in search. --dry-run is how you check lint status ahead of time without triggering that review.
login
Stores a personal access token for authenticated commands.
| Flag | Effect |
|---|---|
--token <token> | Pass the token directly instead of typing it at a masked prompt |
--api <url> | Store this API base alongside the token |
skillmd login
skillmd login --token sk_live_xxxxx --api https://api.skillmd.com The token is written to ~/.skillmd/config.json with file mode 0600.
logout
Removes the stored token. Takes no arguments beyond the global options.
skillmd logout