Claude Code Skills
Create reusable workflows with just-in-time loading, bundled scripts, and automatic invocation
Claude Code Skills
Skills are Claude Code's reusable workflow engine. Unlike CLAUDE.md (which loads into every session), skills load just-in-time — Claude sees only the name and description until a skill is needed, then loads the full instructions on demand. This keeps your context window clean while giving Claude access to dozens of capabilities.
A skill can be as simple as a set of instructions or as powerful as a multi-file package with bundled scripts, templates, and reference docs.
Pro Tip
Custom slash commands have been merged into skills. Your existing .claude/commands/ files keep working. Skills add optional features: a directory for supporting files, frontmatter to control invocation, and automatic loading when Claude determines a skill is relevant.
Quick Start
- 1
Create the skill directory
Bashmkdir -p .claude/skills/fix-issue - 2
Write SKILL.md
Create
.claude/skills/fix-issue/SKILL.md:YAML---name: fix-issuedescription: "Fixes a GitHub issue by reading it, locating the code, implementing a fix, and writing tests."---Fix GitHub issue #$ARGUMENTS:1. Read the issue description with `gh issue view $ARGUMENTS`2. Locate the relevant code3. Implement a fix following project conventions4. Write tests covering the fix5. Create commit: "fix: Description (closes #$ARGUMENTS)" - 3
Use it
Invoke directly:
Bash/fix-issue 1234Or let Claude invoke it automatically — if you say "there's a bug in issue 1234," Claude recognizes the skill's description matches and loads it.
Where Skills Live
Where you store a skill determines who can use it:
| Location | Path | Applies To |
|---|---|---|
| Enterprise | Managed settings | All users in your organization |
| Personal | ~/.claude/skills/skill-name/SKILL.md | All your projects |
| Project | .claude/skills/skill-name/SKILL.md | This project only |
| Plugin | plugin/skills/skill-name/SKILL.md | Where plugin is enabled |
Priority (highest to lowest): Enterprise > Personal > Project. If a skill and a legacy command (.claude/commands/) share the same name, the skill takes precedence.
Note
Monorepo support: Claude Code automatically discovers skills from nested .claude/skills/ directories. If you're editing files in packages/frontend/, it also finds skills in packages/frontend/.claude/skills/.
Backward Compatibility
Your .claude/commands/ files still work and support the same frontmatter. The mapping is straightforward:
| Legacy Commands | Skills |
|---|---|
.claude/commands/review.md | .claude/skills/review/SKILL.md |
~/.claude/commands/standup.md | ~/.claude/skills/standup/SKILL.md |
.claude/commands/git/squash.md | .claude/skills/git-squash/SKILL.md |
Both create /review, /standup, /git-squash and work the same way. Skills add the ability to bundle supporting files alongside SKILL.md.
Skill Anatomy
Every skill is a directory with SKILL.md as the entrypoint:
my-skill/├── SKILL.md # Main instructions (required)├── template.md # Template for Claude to fill in├── examples/│ └── sample.md # Example output showing expected format└── scripts/ └── validate.sh # Script Claude can executeSKILL.md Format
Two parts: YAML frontmatter (between --- markers) and markdown content with instructions.
---name: deploydescription: Deploy the application to productiondisable-model-invocation: trueallowed-tools: Bash(npm *), Bash(git *)--- Deploy $ARGUMENTS to production: 1. Run `npm test` — if any test fails, STOP2. Run `npm run build`3. Run `npm run deploy:prod`4. Verify the deployment succeeded5. Report the deployment URL IMPORTANT: Get confirmation before deploying.NEVER: Deploy if tests are failing.Frontmatter Reference
All fields are optional. Only description is recommended so Claude knows when to use the skill.
| Field | Description | Default |
|---|---|---|
name | Display name and /slash-command. Lowercase letters, numbers, hyphens (max 64 chars). Falls back to directory name. | Directory name |
description | What the skill does and when to use it. Claude uses this to decide when to load the skill automatically. | First paragraph of content |
argument-hint | Hint shown during autocomplete. e.g. [issue-number] or [filename] [format]. | None |
disable-model-invocation | Set true to prevent Claude from auto-loading this skill. User must invoke with /name. | false |
user-invocable | Set false to hide from the / menu. Use for background knowledge Claude should apply automatically. | true |
allowed-tools | Tools Claude can use without asking permission when this skill is active. | None |
model | Model to use when this skill is active. | Inherited |
context | Set to fork to run in an isolated subagent context. | Inline |
agent | Which subagent type to use when context: fork is set (Explore, Plan, general-purpose, or custom). | general-purpose |
hooks | Hooks scoped to this skill's lifecycle. | None |
Controlling Who Invokes a Skill
By default, both you and Claude can invoke any skill. Two frontmatter fields restrict this:
| Frontmatter | You Can Invoke | Claude Can Invoke | When Loaded |
|---|---|---|---|
| (default) | Yes | Yes | Description always in context, full skill loads when invoked |
disable-model-invocation: true | Yes | No | Description not in context, loads only when you invoke |
user-invocable: false | No | Yes | Description always in context, loads when Claude decides |
Use disable-model-invocation: true for workflows with side effects — deploy, commit, send messages. You don't want Claude deciding to deploy because your code looks ready.
Use user-invocable: false for background knowledge — legacy system context, domain expertise, coding conventions. Claude should know this when relevant, but /legacy-context isn't a meaningful action for users.
Arguments and Substitutions
Skills support several dynamic placeholders:
| Variable | Description | Example |
|---|---|---|
$ARGUMENTS | All arguments passed when invoking | /fix-issue 1234 → "1234" |
$ARGUMENTS[N] | Specific argument by index (0-based) | $ARGUMENTS[0] → first arg |
$N | Shorthand for $ARGUMENTS[N] | $0 → first arg, $1 → second |
$${CLAUDE_SESSION_ID} | Current session ID for logging/tracking | logs/abc123.log |
Positional arguments example:
---name: migrate-componentdescription: Migrate a component from one framework to another--- Migrate the $0 component from $1 to $2.Preserve all existing behavior and tests./migrate-component SearchBar React VueIf a skill doesn't include $ARGUMENTS, arguments are appended as ARGUMENTS: <value> automatically.
Types of Skills
Reference Skills (Background Knowledge)
Add knowledge Claude applies to current work — conventions, patterns, style guides. These run inline alongside your conversation.
---name: api-conventionsdescription: API design patterns for this codebaseuser-invocable: false--- When writing API endpoints:- Use RESTful naming conventions- Return consistent error formats using ApiResponse<T>- Validate all inputs with Zod schemas- Include authentication middleware on all routesTask Skills (Workflows)
Step-by-step instructions for specific actions. Often invoked manually with /skill-name.
---name: pr-readydescription: Prepare changes for a pull requestdisable-model-invocation: true--- Prepare the current branch for PR: 1. Run `npm run lint` — fix any issues2. Run `npm test` — all must pass3. Run `npm run build` — must succeed4. Write a commit message following conventional commits5. Push to remote with `git push -u origin HEAD`6. Create PR with `gh pr create` IMPORTANT: Stop and report if any step fails.Real-World Examples
Development Workflow
Code Review — .claude/skills/review/SKILL.md:
---name: reviewdescription: Review current changes for bugs, security issues, and code qualitydisable-model-invocation: trueallowed-tools: Bash(git diff*), Read, Grep, Glob--- Review the current changes: 1. Run `git diff` to see all changes2. For each file changed, analyze for: - Logic errors and edge cases - Security vulnerabilities (injection, auth, secrets) - Performance issues (N+1 queries, memory leaks) - Missing tests for new behavior3. Provide feedback: ## Review Summary**Status:** Approved / Needs Changes ### Issues Found- **[severity]** Issue description (file:line) ### Suggestions- Improvement suggestions IMPORTANT: Be specific with file paths and line numbers.YOU MUST: Explain *why* something is an issue, not just *what*.Bug Investigation — .claude/skills/investigate/SKILL.md:
---name: investigatedescription: Investigate a bug by understanding, reproducing, and analyzing root causedisable-model-invocation: true--- Investigate: $ARGUMENTS ## Understand1. Parse the bug description2. Identify expected vs actual behavior ## Reproduce1. Find reproduction steps2. Add logging if needed to trace the issue ## Analyze1. Search codebase for related code2. Check git history for recent changes to affected files3. Identify root cause ## Report- **Behavior:** What happens- **Expected:** What should happen- **Root Cause:** Technical explanation- **Files Affected:** List with line numbers- **Proposed Fix:** Approach and risk assessment DO NOT fix yet — wait for approval.Git Workflow
Smart Commit — .claude/skills/commit/SKILL.md:
---name: commitdescription: Stage changes and create a well-formatted conventional commitdisable-model-invocation: true--- Create a commit for the current changes: 1. Run `git status` and `git diff` to understand all changes2. Stage relevant files (not .env or credentials)3. Write a commit message: - Type: feat/fix/refactor/docs/test/chore - Scope: affected area in parentheses - Subject: imperative, lowercase, no period - Body: explain *why*, not *what*4. Create the commit5. Show `git log --oneline -3` to confirm Format: `type(scope): subject`Example: `fix(auth): handle expired refresh tokens`Daily Workflow
Standup Summary — ~/.claude/skills/standup/SKILL.md:
---name: standupdescription: Generate a standup summary from yesterday's git activitydisable-model-invocation: true--- Generate standup summary: 1. Get yesterday's commits: `git log --since="yesterday" --author="$(git config user.name)" --oneline`2. Check current branch and status3. Look for any failing tests ## Standup — [Today's Date] ### Yesterday- [List from commits] ### Today- [Current branch/task] ### Blockers- [Any issues found]Code Generation
API Endpoint — .claude/skills/api-endpoint/SKILL.md:
---name: api-endpointdescription: Generate a new API endpoint following project conventionsdisable-model-invocation: true--- Create an API endpoint for: $ARGUMENTS ## Our Patterns- Inputs validated with Zod- Responses use ApiResponse<T>- Authentication via middleware- Proper error handling with status codes ## Steps1. Create src/app/api/$0/route.ts2. Define request/response Zod schemas3. Add authentication check4. Implement business logic5. Add error handling6. Create test file IMPORTANT: Follow existing patterns in src/app/api/Advanced Patterns
Dynamic Context Injection
The !`command` syntax runs shell commands before the skill content is sent to Claude. The output replaces the placeholder, so Claude receives real data.
---name: pr-summarydescription: Summarize changes in a pull requestcontext: forkagent: Exploreallowed-tools: Bash(gh *)--- ## Pull request context- PR diff: !`gh pr diff`- PR comments: !`gh pr view --comments`- Changed files: !`gh pr diff --name-only` ## Your taskSummarize this pull request: what changed, why, and any concerns.When this skill runs, each !`command` executes immediately, output replaces the placeholder, and Claude receives the fully-rendered prompt with actual PR data.
Running Skills in a Subagent
Add context: fork to run a skill in an isolated context. The skill content becomes the prompt driving the subagent — it won't have access to your conversation history.
---name: deep-researchdescription: Research a topic thoroughly across the codebasecontext: forkagent: Explore--- Research $ARGUMENTS thoroughly: 1. Find relevant files using Glob and Grep2. Read and analyze the code3. Map dependencies and relationships4. Summarize findings with specific file referencesThe agent field determines the execution environment. Options: Explore, Plan, general-purpose, or any custom subagent from .claude/agents/.
Warning
context: fork only makes sense for skills with explicit tasks. If your skill contains guidelines without an action (like "use these API conventions"), the subagent receives guidelines but no task and returns without meaningful output.
Bundling Scripts
Skills can include executable scripts for deterministic tasks. The script does the heavy lifting while Claude handles orchestration.
codebase-visualizer/├── SKILL.md└── scripts/ └── visualize.pySKILL.md:
---name: codebase-visualizerdescription: Generate an interactive tree visualization of the codebaseallowed-tools: Bash(python *)--- Generate an interactive HTML tree view of the project structure: ```bashpython ~/.claude/skills/codebase-visualizer/scripts/visualize.py .``` This creates `codebase-map.html` and opens it in your browser.This pattern works for any visual output: dependency graphs, test coverage reports, API documentation, or database schema diagrams.
Supporting Files
Keep SKILL.md focused (under 500 lines) and move detailed reference material to separate files. Claude loads them only when needed.
api-generator/├── SKILL.md # Overview and navigation├── reference.md # Detailed API spec (loaded on demand)├── examples.md # Example outputs└── templates/ └── route-template.ts # Boilerplate templateReference supporting files from SKILL.md:
## Additional resources- For complete API details, see [reference.md](reference.md)- For usage examples, see [examples.md](examples.md)Best Practices
Writing Effective Descriptions
The description field is how Claude decides whether to load your skill. Write it like a search query match:
# Good — specific triggersdescription: "Fixes a GitHub issue by reading it, finding the code, and implementing a fix with tests. Use when someone mentions a bug or issue number." # Bad — too vaguedescription: "Helps with issues"Context Efficiency
- Skill descriptions use ~50 tokens each during metadata scanning
- Full skill content loads only when invoked (typically under 5k tokens)
- The description budget scales at 2% of the context window (fallback: 16,000 chars)
- Override with
SLASH_COMMAND_TOOL_CHAR_BUDGETenv var if you have many skills
Pro Tip
Run /context to check for warnings about excluded skills if you have a large skill library.
Structure and Safety
- Use sections — Break skills into Understanding, Steps, Output Format, and Safety Checks
- Include safety rails — Add
IMPORTANT:andNEVER:directives for destructive operations - Define output format — Tell Claude exactly what the result should look like
- Handle errors — Tell Claude what to do when a step fails (stop? retry? report?)
Invocation Control
- Destructive actions (deploy, delete, send): Use
disable-model-invocation: true - Background knowledge (conventions, domain context): Use
user-invocable: false - General workflows (review, research): Leave defaults — let both you and Claude invoke
Restrict Tools
Limit what Claude can do during a skill for safety:
---name: safe-readerdescription: Read and analyze files without making changesallowed-tools: Read, Grep, Glob---Permission Control
Control which skills Claude can invoke through permission rules:
# Allow only specific skillsSkill(commit)Skill(review-pr *) # Deny specific skillsSkill(deploy *)Syntax: Skill(name) for exact match, Skill(name *) for prefix match with any arguments.
Sharing Skills
With Your Team
Commit project skills to git:
git add .claude/skills/git commit -m "feat: add team workflow skills"As a Plugin
Package skills with other extensions in a plugin's skills/ directory. Plugin skills use plugin-name:skill-name namespacing to avoid conflicts.
Community Skills
Skills follow the Agent Skills open standard, which works across multiple AI tools. Browse community skills at github.com/anthropics/skills.
Troubleshooting
Skill Not Triggering
- Check the
descriptionincludes keywords users would naturally say - Verify the skill appears when you ask "What skills are available?"
- Try invoking directly with
/skill-name - Check that
disable-model-invocationisn't set totrue
Skill Triggers Too Often
- Make the
descriptionmore specific - Add
disable-model-invocation: truefor manual-only invocation
Skill Not Found
- Verify
SKILL.mdexists in the skill directory - Check directory location (
.claude/skills/name/SKILL.mdor~/.claude/skills/name/SKILL.md) - For legacy commands: file exists in
.claude/commands/with.mdextension - Filename/directory matches the command name (kebab-case)
Too Many Skills Excluded
If Claude doesn't see all your skills, the description budget may be exceeded:
- Run
/contextto check for warnings - Set
SLASH_COMMAND_TOOL_CHAR_BUDGETto a higher value - Shorten descriptions or consolidate related skills
Quick Reference
Skill Directory Structure
.claude/skills/my-skill/├── SKILL.md # Required — main instructions├── reference.md # Optional — detailed docs├── templates/ # Optional — boilerplate files├── examples/ # Optional — example outputs└── scripts/ # Optional — executable scriptsMinimal SKILL.md Template
---name: skill-namedescription: What this skill does and when to use it--- Instructions for Claude when this skill is invoked. 1. First step2. Second step3. Third step ## Output FormatExpected output format. IMPORTANT: Critical rules.NEVER: Prohibited actions.Keyword Directives
| Keyword | Effect |
|---|---|
IMPORTANT: | High priority instruction |
YOU MUST: | Required behavior |
NEVER: | Prohibited action |
CRITICAL: | Absolute requirement |
Next Steps
- Start with one skill — automate something you do weekly
- Test both invocation paths — try
/skill-nameand natural language - Add supporting files — templates and scripts for complex workflows
- Share with your team — commit to
.claude/skills/and push
Related Topics:
- Best Practices — Optimize your Claude Code workflows
- Multi-Agent Architectures — Combine skills with subagents and teams
- MCP and Cursor — Extend capabilities with MCP servers
Success
Skills are the compound interest of Claude Code. Each one saves a few minutes per use, but across weeks and team members, that compounds into hours. Start with your most repeated workflow and build from there.