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

CommandAliasPurpose
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
listlsList installed skills with their scope, agents, and source
remove [names...]rmRemove 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]submitPublish a skill to the registry
loginStore a personal access token
logoutRemove 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.

FlagEffect
--jsonPrint 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-httpAllow an http:// API base. Required for one, and only meant for local development.
--versionPrint 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 ..

FlagEffect
--format <fmt>text, json, sarif, or github. Default text.
--strictTreat warnings as failures
--fail-on-warningExit non-zero if any warning is reported
--fixApply safe fixes automatically, such as inserting a missing license
--errors-onlySuppress 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 ..

FlagEffect
--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].

FlagEffect
--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, --yesSkip 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.

FlagEffect
--category <slug>Restrict to one category
--verifiedRestrict to skills that passed safety review
--type <type>single or pack
--min-rating <n>Minimum rating threshold
--limit <n>Maximum results. Default 20.
--jsonMachine-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/repo or gh:owner/repo — read a bare owner/name as GitHub instead of a registry slug.
  • A GitHub tree/ or blob/ 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.

FlagEffect
-g, --globalInstall to your user-level skills directories, available in every project
-p, --projectInstall 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, --listList 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.
--forceReplace a skill that was installed from a different source, or a directory the lock file doesn't track
-y, --yesSkip prompts. The scope is auto-detected, see below.
--skip-lintSkip the pre-install lint check
--deny <flags...>Refuse to install if a scan flag is present, for example network_access
--insecure-httpAllow 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:

ScopeFlagCanonical copyAgent linksLock 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.

FlagEffect
-g, --globalOnly your user-level skills
-p, --projectOnly this project's skills
-a, --agent <agents...>Only skills linked into these agents
--jsonMachine-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.

FlagEffect
-g, --globalOnly your user-level skills
-p, --projectOnly this project's skills
-a, --agent <agents...>Unlink from these agents only. The canonical copy stays.
--allRemove every skill in the scope. Can't be combined with names.
-y, --yesSkip the confirmation
--jsonMachine-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.

FlagEffect
--checkReport what has updates and write nothing
-g, --globalOnly your user-level skills
-p, --projectOnly this project's skills
--jsonMachine-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 ..

FlagEffect
--type <type>single or pack. Default single.
--forcePublish despite lint warnings. Does not override lint errors.
--dry-runRun 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.

FlagEffect
--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