Overview
Skills are named, user-invocable procedures that Claude Code can execute on demand. A skill packages a prompt, a set of tool calls, and optional hook sequences into a single slash command: /review, /deploy, /fix-lint. Store skills in .claude/skills/ or as a user-level library at ~/.claude/skills/. See claude-code for context on how skills fit into the broader workflow.
Lay out the skills directory under .claude
The canonical layout is flat. Each skill is a directory named after the command.
.claude/
└── skills/
├── review/
│ └── SKILL.md
├── deploy/
│ └── SKILL.md
└── fix-lint/
└── SKILL.md
The directory name is the slash command. /review loads .claude/skills/review/SKILL.md. Nested commands use path separators: .claude/skills/seo/audit/SKILL.md becomes /seo/audit.
User-level skills live at ~/.claude/skills/. They are always available regardless of project. Project-level skills override user-level on name collision.
Write SKILL.md as an executable instruction set
Each SKILL.md is the prompt Claude receives when the user invokes the skill. Write it as instructions, not documentation.
# /review
Review the staged diff for this project.
1. Run `git diff --staged` and read the output.
2. Check that every changed file passes `npm run lint`.
3. Summarize findings as a markdown checklist grouped by severity: blocking, warning, suggestion.
4. Do not suggest refactors outside the staged diff.
5. Do not modify any files.Lead with the task. State the output format explicitly. Add explicit non-goals; skills without non-goals invite scope creep the same way prompts do. See prompt-design for the non-goals rule.
User-invocable skills replace repetitive prompt pasting
The value of a skill over a copy-pasted prompt is consistency. Every invocation uses the same instructions, the same tool sequence, and the same output format. Teams share skills via the project .claude/ directory; changes are reviewed in PRs like any other config.
Good skill candidates:
- Repeated review procedures (
/review,/security-review). - Phased setup sequences (
/init,/session-start). - Format-then-lint pipelines (
/fix-lint). - Deploy preflight checks (
/deploy-check).
Bad skill candidates: one-off tasks you will never repeat; tasks that vary significantly by invocation. One-off tasks belong in the user message; variable tasks belong in parameterized prompts.
Pass arguments from the slash command to the skill
When the user types /review main..HEAD, the text after the command name is available to the skill as $ARGS.
# /review
Review the diff for `$ARGS` (default: `--staged` if empty).
Run `git diff $ARGS` and analyze the output.Keep the interface narrow. Skills with more than two or three meaningful arguments are better expressed as an agent invoked with a brief. See claude-code-subagents for when to escalate to a subagent.
Choose a skill over a bare agent for repeatable, bounded tasks
The decision tree between a skill and a standalone agent:
- Bounded, deterministic, reusable: skill.
- Open-ended, project-specific, needs worktree isolation: agent via claude-code-subagents.
- Cross-session, durable context: anchor files via claude-code-claude-md.
A /deploy-check that runs the same five shell commands every time is a skill. A “build me this feature from this brief” task is an agent. Skills are cheap to invoke and cheap to reason about; agents are powerful but expensive.
Namespace skills to avoid collisions
User-level skills ship with generic names (/review, /init). Project skills should use project-specific names or subdirectories.
~/.claude/skills/review/ → /review (generic)
.claude/skills/myapp/review/ → /myapp/review (project-scoped)
Prefix project skills with the project name or domain when deploying skills users will also have globally. The project-level skill wins, but an explicit namespace makes the collision visible.