Claude Code Skills: The Complete Guide
A practical guide to Claude Code skills: reusable instructions, invocation, frontmatter and examples, with explicit limits on permissions and hook guarantees.
What Are Skills?
Skills are reusable instruction sets packaged as Markdown files that extend Claude Code’s capabilities. Based on the open Agent Skills standard, they work across multiple AI tools — not just Claude Code.
Think of them as playbooks. You write a set of instructions once — how to deploy, how to review code, how to create a blog post — and then invoke it whenever you need it. Claude reads the playbook and executes it using all the tools at its disposal.
A skill is:
- A
.mdfile with YAML frontmatter (configuration) and Markdown body (instructions) - A self-contained unit that Claude can load automatically when relevant, or you invoke manually with
/skill-name - Available at multiple scopes: personal, project, enterprise, or packaged in plugins
- Discoverable by Claude through descriptions you provide
- Optionally executable in isolation via a subagent context
The key distinction: skills are prompt-based guidance. Claude reads them and follows them, but they’re instructions — not hard-enforcement rules like hooks or permissions. That’s a feature, not a bug. It means skills are flexible, composable, and easy to write.
Skills vs CLAUDE.md
This is the first question everyone asks: "If I can put instructions in CLAUDE.md, why do I need skills?" The answer is scope and loading.
The mental model is simple:
- CLAUDE.md = who you are and how you work (permanent context)
- Skills = what you do and when (on-demand playbooks)
Put your coding standards, build commands, and project architecture in CLAUDE.md. Put your deployment workflow, code review checklist, and PR template in skills. They complement each other — CLAUDE.md provides the rules, skills provide the actions.
Skill Types
Skills are classified along three dimensions: who can invoke them, where they run, and what they contain.
By Invocation Pattern
User-invocable (default) — You type /skill-name to run them. Claude can also invoke them automatically if the description matches your request.
Model-invocation disabled (disable-model-invocation: true) — Only you can invoke via /skill-name. Claude cannot trigger them automatically. Use this for workflows with side effects: deploying, committing, sending messages.
Hidden skills (user-invocable: false) — Only Claude can invoke them automatically. They don’t appear in the / menu. Use for background knowledge: legacy system docs, architectural context, domain conventions.
By Execution Context
Inline (default) — Runs in your main conversation. Claude can reference your conversation history. Results stay in the thread.
Forked (context: fork) — Runs in an isolated subagent. No access to conversation history. Results are summarized and returned. Perfect for high-volume operations like running test suites, processing large codebases, or deep research where you don’t want verbose output cluttering your context.
By Content Type
Reference skills contain knowledge or guidelines (API conventions, design patterns, style guides). They add context Claude applies to current work.
Task skills contain step-by-step instructions for specific actions (deploy, fix a bug, create a PR). They’re typically marked disable-model-invocation: true since you want to control when they run.
Where Skills Live
Skills can come from several locations. Inspect the loaded skill and its source when names collide; do not infer precedence from directory proximity.
Discovery Locations
# Personal
~/.claude/skills/<skill-name>/SKILL.md
# Project
.claude/skills/<skill-name>/SKILL.md
# Nested project scope
packages/frontend/.claude/skills/<skill-name>/SKILL.md
# Managed and plugin locations depend on deployment configuration.
# Inspect /skills for the loaded definition; this list is not a priority order.Use project skills for repository workflows, personal skills for local cross-project workflows, and managed or plugin distribution for shared installations. Loading also depends on workspace, account and version.
Directory Structure
Each skill is a directory with a required SKILL.md and optional supporting files:
my-skill/
├── SKILL.md # Required: frontmatter + instructions
├── reference.md # Optional: detailed docs
├── examples.md # Optional: usage examples
├── templates/ # Optional: templates
│ └── api-response.md
└── scripts/ # Optional: executable scripts
├── validate.sh
└── helper.pyOnly SKILL.md is required. Supporting files are loaded by Claude on-demand when referenced from the main file. This keeps your skill lightweight — the full reference material only enters context when Claude actually needs it.
Legacy Compatibility
The older .claude/commands/ directory still works and supports the same frontmatter. If both exist with the same name, .claude/skills/ takes precedence. New skills should always use the skills/ directory.
The Skill File Format
This is the core of the system. A SKILL.md file has two parts: YAML frontmatter (configuration) and Markdown body (instructions).
Complete Frontmatter Reference
---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
user-invocable: true
argument-hint: "[environment]"
allowed-tools: Bash, Read, Write
model: opus
effort: high
context: fork
agent: general-purpose
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./validate.sh"
---
Markdown body goes here — the actual instructions Claude follows.The table covers common frontmatter fields. The live documentation is the reference for additional fields and version-specific behavior.
String Substitutions
Skills support dynamic value substitution in both frontmatter and body:
Important: If $ARGUMENTS doesn’t appear anywhere in the skill content, Claude Code auto-appends ARGUMENTS: <value> to the end.
Shell Preprocessing
Skills can run shell commands and inject their output before Claude sees the prompt. Use the !`command` syntax:
---
name: pr-summary
---
## Pull Request Context
- PR diff: !`gh pr diff`
- PR comments: !`gh pr view --comments`
- Changed files: !`gh pr diff --name-only`
## Your Task
Summarize this pull request...Each !`command` executes immediately when the skill loads. The output replaces the placeholder. Claude receives the fully-rendered prompt with actual data — not the commands themselves. This is how you inject live context into skills.
The Body: Instructions
The Markdown body after the frontmatter is the instruction prompt Claude follows. It can contain:
- Plain text instructions and step-by-step workflows
- Markdown formatting (headings, lists, code blocks, bold, links)
- References to supporting files:
See [reference.md](reference.md) for details - Shell preprocessing commands (
!`command`) - Variable substitutions (
$ARGUMENTS,${CLAUDE_SKILL_DIR})
Keep SKILL.md under 500 lines. Move detailed reference material to separate files in the same directory.
Invoking Skills
Use the documented slash command for explicit invocation, or let Claude select a relevant skill when model invocation is enabled.
1. Slash Commands (Manual)
Type / followed by the skill name. Arguments go after:
/deploy production
/fix-issue 123
/explain-code src/auth/login.ts
/migrate-component SearchBar React VueType / alone to see a list of all available skills with autocomplete.
2. Auto-Invocation (Claude-Triggered)
Claude may select a skill when its description is relevant and model invocation is enabled. A matching phrase does not guarantee selection.
- Your prompt matches the skill’s
description - The skill doesn’t have
disable-model-invocation: true
A description such as “explains code with diagrams” can help Claude identify a relevant skill. Test both manual invocation and representative requests instead of assuming automatic selection.
Inspect Available Skills
Use /skills to inspect what the current session has loaded. Use /skill-name to invoke a user-invocable skill explicitly.
/skills
/code-reviewer review the current diffThe documented skill invocation mechanism is the slash command. This guide does not rely on an unverified @-mention syntax.
Invocation Control Matrix
Arguments and Parameters
Basic: Single Argument
---
name: fix-issue
argument-hint: "[issue-number]"
---
Fix GitHub issue $ARGUMENTS following our coding standards.
1. Read the issue description
2. Find and fix the bug
3. Write tests
4. Create a commit: "Fix #$ARGUMENTS"
Running /fix-issue 123 replaces every $ARGUMENTS with 123.
Multiple Arguments (Positional)
---
name: migrate-component
argument-hint: "[component] [from-framework] [to-framework]"
---
Migrate the $0 component from $1 to $2.
1. Analyze the current $1 implementation of $0
2. Create the equivalent $2 version
3. Preserve all behavior and tests
4. Update all importsRunning /migrate-component SearchBar React Vue:
$0= SearchBar$1= React$2= Vue$ARGUMENTS= SearchBar React Vue (the whole string)
Argument Hints
The argument-hint field shows in autocomplete when you type the skill name:
---
name: deploy
argument-hint: "[environment]"
---When you type /deploy, the CLI shows [environment] as a hint for what to type next.
Reference: Claude Code skills reference (documentation checked 20 September 2026).
Instruction loading: Claude Code memory scopes and loading.
Reference: Claude Code hook protocol (documentation checked 20 September 2026).
Built-in Skills
These are examples of bundled skills available in supported versions. Inspect the current session and documentation for the full set.
These are prompt-based skills, not hard-coded commands. They give Claude detailed playbooks and let it orchestrate work using tools. You can read their source to learn how to write effective skills.
Creating Your First Skill
Step 1: Choose Location
Decide the scope:
# Personal (all your projects):
mkdir -p ~/.claude/skills/my-skill
# Project-specific (shared with team):
mkdir -p .claude/skills/my-skillStep 2: Write SKILL.md
Start simple:
---
name: explain-code
description: Explains code with visual diagrams and analogies. Use when explaining how code works or teaching about a codebase.
---
When explaining code, always:
1. **Start with an analogy** — compare to something from everyday life
2. **Draw a diagram** — use ASCII art to show data flow or structure
3. **Walk through step-by-step** — explain what each key section does
4. **Highlight a gotcha** — call out common mistakes or misconceptions
Keep explanations conversational. Use multiple analogies for complex concepts.Step 3: Test It
Invoke manually to verify:
/explain-code src/auth/middleware.tsOr trigger auto-invocation:
How does the auth middleware work?Claude should now include analogies, ASCII diagrams, and gotchas in its explanation — because your skill told it to.
Step 4: Add Supporting Files (Optional)
As your skill grows, extract detailed content into separate files:
explain-code/
├── SKILL.md # Main instructions (keep under 500 lines)
├── patterns.md # Common explanation patterns
└── examples.md # Before/after examples of good explanationsReference them from SKILL.md:
See [patterns.md](patterns.md) for common explanation patterns.
See [examples.md](examples.md) for example explanations.Claude will read these files when it needs them, keeping the base skill lightweight.
Real-World Examples
These examples are starting templates. Adapt and test authorization, failure handling, release identification and recovery for the target project.
Deploy Skill (Task, Protected)
---
name: deploy
description: Prepare and deploy an explicitly authorized release
disable-model-invocation: true
argument-hint: "[environment] [unique-release-tag]"
---
Deploy to $0 using the explicitly selected unique tag $1.
1. Confirm the target, approved commit and environment-specific deployment procedure.
2. Check the branch and clean working tree. Fetch remote state and reconcile it
without silently overwriting local changes.
3. Run the required tests and build; stop on failure.
4. Validate the release tag, confirm it is absent locally and remotely, and create
an annotated tag at the approved commit. Never reuse an existing release tag.
5. Push only that explicit tag: `git push origin refs/tags/<unique-release-tag>`.
Substitute the validated tag; do not use --tags.
6. Run the project's reviewed deployment procedure for the selected environment.
7. Check health and smoke tests. On failure, use the project's tested rollback procedure.
This template does not supply the deployment or rollback implementation.disable-model-invocation prevents automatic skill invocation. allowed-tools preapproves the listed tools; it does not exclude every other tool or authorize a deployment outside the requested scope.
Code Review Skill (Reference, Auto-Invoked)
---
name: code-reviewer
description: Expert code review. Use when reviewing code for quality, security, and maintainability.
allowed-tools: Read, Grep, Glob
---
You are a senior code reviewer. Analyze the code with this checklist:
**Critical (must fix):**
- Security vulnerabilities (XSS, SQL injection, auth bypasses)
- Data loss risks
- Race conditions
**Major (should fix):**
- Performance problems (O(n²) where O(n) is possible)
- Missing error handling on external calls
- DRY violations (duplicated logic)
- Unclear naming or confusing control flow
**Minor (consider):**
- Style inconsistencies
- Missing edge case tests
- Overly complex one-liners
**Output format:**
For each finding:
- Severity (Critical / Major / Minor)
- File and line number
- What’s wrong
- How to fix it (with code example)
End with a summary: safe to merge, needs changes, or needs major rework.Read, Grep and Glob are preapproved here. That does not by itself make the session read-only. For enforced review isolation, use an execution environment without write access and without credentials that can mutate external systems.
PR Summary Skill (Dynamic Context Injection)
---
name: pr-summary
description: Summarize the current pull request with live GitHub data
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---
## Live PR Data
- Diff: !`gh pr diff`
- Comments: !`gh pr view --comments`
- Changed files: !`gh pr diff --name-only`
- PR metadata: !`gh pr view --json title,body,author,labels`
## Your Task
Summarize this pull request in 2–3 paragraphs:
1. **What changed** — high-level summary of the diff
2. **Why** — motivation based on PR description and comments
3. **Risk assessment** — what could break, what needs careful review
Highlight any files with >100 lines changed as needing extra attention.The !`gh pr diff` commands execute before Claude sees the prompt. Claude receives the actual diff, comments, and metadata — fully rendered with real data. The context: fork keeps the (potentially massive) diff out of your main conversation window.
Test Coverage Skill (Forked Subagent)
---
name: test-gaps
description: Analyze test coverage and identify gaps
context: fork
agent: Explore
allowed-tools: Read, Grep, Glob, Bash(npm test*, npx jest*)
---
Analyze test coverage for $ARGUMENTS (or the entire project if no args):
1. **Run coverage**: `npx jest --coverage --silent`
2. **Parse report**: Find files below 80% coverage
3. **Identify gaps**: What functions/branches are untested?
4. **Prioritize**: Rank by risk (auth > utils, write paths > read paths)
Output:
- Top 5 files needing tests, with specific functions to test
- For each, suggest 2–3 test cases with expected behavior
- Estimated effort: quick (<30min), medium (<2hr), or deep (>2hr)Blog Post Skill (Complex Multi-Step Workflow)
---
name: create-post
description: Create a new Ghost blog post with the full workflow
disable-model-invocation: true
allowed-tools: Read, Write, Bash(python3 *)
argument-hint: "[title]"
---
Create a new blog post: "$ARGUMENTS"
Follow the full 11-step workflow from CLAUDE.md:
1. **Gather content**: title, slug, excerpt, featured image, tag
2. **SEO fields**: meta title, meta description, OG image
3. **Signup card**: append the standard card
4. **Create as draft**: via Ghost Admin API, share preview link
5. **Iterate**: get feedback, make changes
6. **Publish + email**: set status to published, email all subscribers
7. **Update Start Here**: add to the correct section
8. **Cross-link**: add related reading links
9. **LinkedIn draft**: write a standalone companion post
10. **Cleanup**: delete temp files
11. **Update docs**: update ctx.md, commit, push
Always confirm slug, tag, and image with the user before creating.
Never publish without explicit approval.This skill encapsulates an entire workflow. By using disable-model-invocation: true, it only runs when you explicitly type /create-post My Article Title.
Advanced Patterns
Hooks Inside Skills
Skill hooks follow the native lifecycle documented for the installed version. Current documentation says registered skill hooks can remain for the rest of the session; do not assume they stop as soon as the skill text finishes.
---
name: inspect-query
description: Inspect a database query without executing it
allowed-tools: Read, Grep, Glob
---
Explain the query and its expected effects. Do not execute it.
Treat this instruction as workflow guidance, not an access-control mechanism.
Use database credentials that cannot write when execution is authorized.
$ARGUMENTSFor a PreToolUse command hook, exit 2 is a blocking response; a generic nonzero exit such as 1 is not equivalent. A supported deny JSON response is another explicit decision mechanism. An omitted validator is not a safety guarantee. Test any validator against the actual hook protocol, and enforce database restrictions with database privileges.
MCP Server Integration
Skills can use MCP (Model Context Protocol) server tools. MCP tools follow the naming pattern mcp__<server>__<tool>:
---
name: github-search
description: Search GitHub repositories, issues, and code
allowed-tools: mcp__github__*, Read
---
Search GitHub for: $ARGUMENTS
Available tools:
- mcp__github__search_repositories: Find repos by keyword
- mcp__github__search_code: Find code snippets
- mcp__github__get_issue: Get issue details by number
Report findings with links to relevant repositories and files.The mcp__github__* wildcard grants access to all tools from the GitHub MCP server.
Tool Preapproval Patterns
Use allowed-tools to control which tools need no additional approval while the skill grant applies. Use independent permissions and execution boundaries for restrictions.
# Preapprove reading tools; this is not an exclusive allowlist
allowed-tools: Read, Grep, Glob
# Preapprove the named tool patterns, subject to applicable policy
allowed-tools: Read, Write, Edit, Bash(npm test*)
# Preapprove matching Git commands; Git can mutate local and remote state
allowed-tools: Bash(git *)
# For actual read-only isolation, use a read-only checkout/container and
# credentials without write privileges. Skill instructions alone are not a boundary.Extended Thinking
To enable extended thinking (deep reasoning mode) within a skill, include the word ultrathink anywhere in the skill content:
---
name: architecture-review
description: Deep architectural analysis with extended reasoning
---
Use ultrathink to deeply analyze the architecture of $ARGUMENTS.
Consider:
- Component dependencies and coupling
- Data flow and state management
- Scalability bottlenecks
- Security boundariesSkill-Scoped Permissions
Control which skills Claude can invoke via your settings.json:
{
"permissions": {
"allow": ["Skill(fix-issue)", "Skill(deploy *)"],
"deny": ["Skill(destructive *)"]
}
}Use Skill(name) for exact match, Skill(name *) for prefix match. To disable all skills: "deny": ["Skill"].
Skills vs CLAUDE.md vs Hooks: The Decision Framework
These three systems serve different purposes. Here’s when to use each:
The decision framework:
- If it’s a rule that should always apply (coding standards, naming conventions, build commands) → CLAUDE.md
- If it’s a workflow you trigger when needed (deploy, review, create PR) → Skill
- For an action at a defined lifecycle event, use a tested hook and account for matching, timeouts and failure responses.
- If Claude needs to know about it but only sometimes (legacy system context, API patterns) → Hidden Skill (
user-invocable: false)
They’re complementary. CLAUDE.md tells Claude how to behave. Skills tell Claude what to do. Hooks enforce guardrails. A well-configured project uses all three.
Best Practices
- Write clear descriptions. The description is the most important field. Claude uses it to decide when to load your skill. Be specific: "Deploy the application to production" not "Deploy tool".
- Preapprove only the tools the workflow needs. allowed-tools reduces approval prompts; use separate permissions, a read-only environment and appropriately scoped credentials when writes must be impossible.
- Use disable-model-invocation for side effects. Anything that deploys, commits, sends messages, or modifies external state should require explicit invocation.
- Keep SKILL.md under 500 lines. Extract detailed reference material into supporting files. Claude reads them on-demand.
- Use forked context for heavy operations. Test suites, deep research, large diffs — anything that produces verbose output belongs in a
context: forkskill. - Number your steps. Task skills are clearer when steps are explicitly numbered. Claude follows numbered sequences more reliably.
- Include failure handling. Tell Claude what to do when a step fails. "If tests fail, stop and report the errors" prevents runaway execution.
- Test with manual invocation first. Before relying on auto-invocation, test with
/skill-nameto verify the skill works as expected.
Common Gotchas
- Skills provide guidance. Hooks can implement programmatic checks, but their coverage and failure behavior still need validation.
- Descriptions consume context. Available model-invocable skills normally contribute descriptions to context; disable-model-invocation: true excludes that description. Keep descriptions concise and inspect the active configuration.
- Auto-invocation is probabilistic. Claude uses the description to decide. Phrasing matters. If your skill isn’t being auto-invoked, try rewording the description with keywords users would naturally say.
- Forked skills have no conversation history. A
context: forkskill runs in isolation. It can’t reference what you discussed earlier. Write the skill content to be fully self-contained. - Subagents can’t nest. A skill running in a forked subagent cannot spawn another subagent. Keep this in mind when designing complex workflows.
- Plugin capabilities depend on their supported manifest and client version. Plugins can bundle hooks and MCP configuration; inspect the installed package instead of assuming plugin skills cannot use them.
- User skills don’t sync. Skills in
~/.claude/skills/are local to your machine. They won’t be on your other workstation unless you sync them manually. - Validate YAML frontmatter. Malformed metadata may be ignored while the body still loads, so a command appearing in the menu does not prove that every field parsed correctly.
Quick Reference
Skills are one of Claude Code’s most powerful features — and one of its most underused. Start with one simple skill for a workflow you repeat often. Once you see how much time it saves, you’ll never go back to explaining the same process twice.