On this page
Lesson 11 of 30

Lesson 10: Skills

What Are Skills?

Skills are reusable prompt templates that extend what Claude Code can do. You create a SKILL.md file with instructions, and Claude adds it to its toolkit — loading the skill automatically when relevant, or letting you invoke it directly with /skill-name.

Think of skills as building blocks for Claude's behavior. A CLAUDE.md file tells Claude how to work in your project. A skill tells Claude how to perform a specific task. If you find yourself typing the same kind of prompt repeatedly — code reviews, deploys, commit messages — that prompt belongs in a skill.

Skills follow the Agent Skills open standard, which works across multiple AI tools. Claude Code extends the standard with features like invocation control, subagent execution, and dynamic context injection.

Migrating from commands? If you have files in .claude/commands/, they still work. Skills are the evolution of commands — same concept, more capabilities. A file at .claude/commands/review.md and a skill at .claude/skills/review/SKILL.md both create /review and work the same way. If both exist with the same name, the skill takes precedence.


The SKILL.md Architecture

Each skill lives in its own directory with a SKILL.md file 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 execute

The SKILL.md file has two parts:

  1. YAML frontmatter (between --- markers) — metadata that tells Claude when and how to use the skill
  2. Markdown content — the instructions Claude follows when the skill is invoked

Here is a minimal example:

YAML
---
name: explain-code
description: Explains code with visual diagrams and analogies. Use when explaining how code works or when the user asks "how does this work?"
---

When explaining code, always include:

1. **Start with an analogy**: Compare the code to something from everyday life
2. **Draw a diagram**: Use ASCII art to show the flow or relationships
3. **Walk through the code**: Explain step-by-step what happens
4. **Highlight a gotcha**: What's a common mistake or misconception?

Keep explanations conversational. For complex concepts, use multiple analogies.

The only required file is SKILL.md. Supporting files (templates, examples, scripts, reference docs) are optional and let you build more powerful skills without bloating the main file.

Tip: Keep SKILL.md under 500 lines. Move detailed reference material to separate files and reference them so Claude knows when to load them.


Where Skills Live

Where you store a skill determines who can use it:

Location Path Applies To
Enterprise Managed settings (see Anthropic docs) 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

When skills share the same name across levels, higher-priority locations win: enterprise > personal > project. Plugin skills use a plugin-name:skill-name namespace, so they never conflict with other levels.

Monorepo support

When you work with files in subdirectories, Claude Code automatically discovers skills from nested .claude/skills/ directories. If you are editing a file in packages/frontend/, Claude Code also looks for skills in packages/frontend/.claude/skills/. This is ideal for monorepos where packages need their own specialized skills.

Skills from additional directories

Skills defined in .claude/skills/ within directories added via --add-dir are loaded automatically and picked up by live change detection, so you can edit them during a session without restarting.


Frontmatter Reference

All frontmatter fields are optional. Only description is strongly recommended so Claude knows when to use the skill.

YAML
---
name: my-skill
description: What this skill does and when to use it
argument-hint: "[issue-number]"
disable-model-invocation: false
user-invocable: true
allowed-tools: Read, Grep, Glob
model: claude-sonnet-4-20250514
context: fork
agent: Explore
---
Field Description
name Display name for the skill. If omitted, uses the directory name. Lowercase letters, numbers, and hyphens only (max 64 characters).
description What the skill does and when to use it. Claude uses this to decide when to load it automatically. If omitted, uses the first paragraph of content.
argument-hint Hint shown during autocomplete, e.g. [issue-number] or [filename] [format].
disable-model-invocation Set to true to prevent Claude from automatically loading this skill. For manual-only workflows. Default: false.
user-invocable Set to false to hide from the / menu. For background knowledge Claude should use but users should not invoke directly. Default: true.
allowed-tools Tools Claude can use without asking permission when this skill is active.
model Model to use when this skill runs.
context Set to fork to run in an isolated subagent context.
agent Which subagent type to use when context: fork is set (e.g. Explore, Plan, general-purpose, or a custom agent).
hooks Hooks scoped to this skill's lifecycle.

Automatic Invocation

This is the key difference from the old commands system: Claude can load skills automatically based on context.

Here is how it works:

  1. Description indexing — When a session starts, Claude reads the description field from every available skill. These descriptions stay in context so Claude knows what is available.
  2. Context matching — When you ask Claude something, it checks whether any skill descriptions match what you need.
  3. Automatic loading — If a skill matches, Claude loads the full SKILL.md content and follows its instructions.

For example, if you have a skill with this description:

YAML
description: API design patterns for this codebase. Use when writing API endpoints or reviewing API code.

Then when you say "Add a new endpoint for user preferences," Claude recognizes the match and loads the skill automatically. You never need to type a slash command.

Controlling automatic invocation

Not every skill should fire automatically. Deployment workflows, destructive operations, or anything with side effects should require explicit invocation.

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; full skill loads when invoked

Rule of thumb: If the skill has side effects (deploying, committing, sending messages), add disable-model-invocation: true. If the skill is background knowledge users should not invoke directly, add user-invocable: false.


Slash Command Invocation

You can always invoke a skill manually by typing /skill-name:

/explain-code src/auth/login.ts

Tab completion works in Claude Code — type / and start typing to see available skills and their argument-hint values.

Passing arguments

Arguments are available via the $ARGUMENTS placeholder:

YAML
---
name: fix-issue
description: Fix a GitHub issue
disable-model-invocation: true
---

Fix GitHub issue $ARGUMENTS following our coding standards.

1. Read the issue description
2. Understand the requirements
3. Implement the fix
4. Write tests
5. Create a commit

Running /fix-issue 123 gives Claude: "Fix GitHub issue 123 following our coding standards..."

If your skill does not include $ARGUMENTS, Claude Code appends ARGUMENTS: <your input> to the end automatically.

Positional arguments

Access individual arguments by position with $ARGUMENTS[N] or the shorthand $N:

YAML
---
name: migrate-component
description: Migrate a component from one framework to another
---

Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.

Running /migrate-component SearchBar React Vue replaces $0 with SearchBar, $1 with React, and $2 with Vue.

Other substitutions

Variable Description
$ARGUMENTS All arguments passed when invoking the skill
$ARGUMENTS[N] or $N Specific argument by 0-based index
${CLAUDE_SESSION_ID} Current session ID (useful for logging)

Built-in Skills

Claude Code ships with several built-in skills. These are available out of the box:

Command What It Does
/commit Create a git commit with a well-formatted message
/review-pr Review a pull request
/init Initialize Claude Code in a project (creates CLAUDE.md)

For other built-in commands like /help, /compact, /context, and /permissions, see the interactive mode documentation — those are built-in commands, not skills.


Creating Custom Skills

Step-by-step guide

1. Create the skill directory:

Bash
# Personal skill (available in all projects)
mkdir -p ~/.claude/skills/my-skill

# Project skill (available only in this project, can be committed to git)
mkdir -p .claude/skills/my-skill

2. Write the SKILL.md file:

YAML
---
name: my-skill
description: Clear description of what this does and when to use it
---

Your instructions here. Be specific about:
- What Claude should do
- What output format to use
- What quality criteria to follow
- How to handle edge cases

3. Test it:

# Automatic invocation — ask something that matches the description
How does the auth system work?

# Manual invocation
/my-skill src/auth/

4. Iterate. The first version will not be perfect. Use the skill a few times and refine the instructions based on what Claude gets right and wrong.


Practical Examples

Code Review Skill

YAML
---
name: review
description: Thorough code review of current branch changes against main. Use when reviewing code, checking for issues, or preparing a PR.
disable-model-invocation: true
allowed-tools: Bash(git *), Read, Grep, Glob
---

Review the changes in the current branch against main.

## Steps

1. Run `git diff main...HEAD` to see all changes
2. Run `git log main..HEAD --oneline` to understand the commit history
3. For each changed file, evaluate:
   - **Correctness**: Does the logic work? Are there edge cases?
   - **Security**: Any OWASP top-10 issues? Hardcoded secrets?
   - **Performance**: N+1 queries, unnecessary allocations, missing indexes?
   - **Style**: Does it follow the conventions in CLAUDE.md?
   - **Tests**: Are the changes adequately tested?

## Output format

Use this structure:
- **Summary**: 2-3 sentences on what changed and why
- **Issues**: Grouped as Critical / Major / Minor
- **Suggestions**: Improvements that are not blockers
- **Verdict**: Approve / Request Changes / Needs Discussion

Usage: /review after pushing your feature branch commits.

Deployment Checklist Skill

YAML
---
name: deploy
description: Run the deployment checklist for production releases
disable-model-invocation: true
---

Deploy $ARGUMENTS to production using this checklist:

## Pre-deploy

1. Run the full test suite — `npm test`
2. Check for lint errors — `npm run lint`
3. Verify the build — `npm run build`
4. Check for uncommitted changes — `git status`
5. Confirm we are on the correct branch

## Deploy

6. Tag the release: `git tag -a v$(date +%Y%m%d-%H%M) -m "Production release"`
7. Push the tag: `git push origin --tags`
8. Run the deploy command: `npm run deploy:production`

## Post-deploy

9. Verify the deployment succeeded (check health endpoint)
10. Run smoke tests against production
11. Report results with the tag name and deploy time

## Abort conditions

Stop immediately and report if:
- Any test fails
- There are uncommitted changes
- The build fails
- The health check fails after deploy

Usage: /deploy api-server to deploy a specific service.

Documentation Generator Skill

This example uses supporting files to keep the main skill focused:

.claude/skills/generate-docs/SKILL.md:

YAML
---
name: generate-docs
description: Generate API documentation for a module or file. Use when asked to document code or create API docs.
allowed-tools: Read, Grep, Glob, Bash(npx *)
---

Generate comprehensive documentation for $ARGUMENTS.

## Steps

1. Read the target file(s)
2. Identify all exported functions, classes, and types
3. For each export, document:
   - Purpose (one sentence)
   - Parameters with types and descriptions
   - Return value
   - Example usage
   - Edge cases or gotchas

## Format

Use the template in [template.md](template.md) for the output structure.

## Quality checks

- Every public function must have at least one example
- Parameter types must be accurate (read the source, do not guess)
- Examples must be syntactically valid

.claude/skills/generate-docs/template.md:

Markdown
# Module: {module_name}

{one-paragraph description}

## Functions

### `functionName(param1, param2)`

{description}

**Parameters:**
| Name | Type | Description |
|------|------|-------------|
| param1 | string | ... |

**Returns:** `ReturnType` — {description}

**Example:**
```js
const result = functionName('hello', 42);

Usage: `/generate-docs src/utils/validation.ts`

---

## Advanced Patterns

### Injecting dynamic context

The `` !`command` `` syntax runs shell commands *before* the skill content is sent to Claude. The command output replaces the placeholder:

```yaml
---
name: pr-summary
description: Summarize changes in a pull request
context: fork
agent: Explore
allowed-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 task
Summarize this pull request: what changed, why, and any concerns.

When this runs, each !`command` executes immediately and its output gets inserted into the prompt. Claude only sees the final rendered result.

Running skills in a subagent

Add context: fork to run a skill in an isolated context. The skill content becomes the prompt that drives a subagent, separate from your conversation history:

YAML
---
name: deep-research
description: Research a topic thoroughly in the codebase
context: fork
agent: Explore
---

Research $ARGUMENTS thoroughly:

1. Find relevant files using Glob and Grep
2. Read and analyze the code
3. Summarize findings with specific file references

The agent field determines the execution environment. Options include built-in agents (Explore, Plan, general-purpose) or any custom subagent you define in .claude/agents/. If omitted, it defaults to general-purpose.

Restricting tool access

Use allowed-tools to limit what Claude can do when a skill is active. This creates a read-only exploration mode:

YAML
---
name: safe-reader
description: Explore the codebase without making any changes
allowed-tools: Read, Grep, Glob
---

Explore and explain the code at $ARGUMENTS.
Do not modify any files.

Skills vs CLAUDE.md vs Hooks

These three systems complement each other. Here is when to use which:

Use Case Use This Why
Project conventions ("use tabs, not spaces") CLAUDE.md Always-on context, applies to everything
One-off knowledge ("our DB uses read replicas") CLAUDE.md Background context, not a task
Reusable task ("review this PR") Skill Structured instructions invoked on demand
Domain knowledge Claude should auto-apply Skill with user-invocable: false Auto-loads when relevant, but not a command
Automated validation (lint on every file write) Hook Runs on events, no manual invocation
Pre-commit checks Hook Fires on tool events automatically
Complex workflow with supporting files Skill Directory structure supports templates, scripts, examples

Quick test: If you are writing rules Claude should always follow, put them in CLAUDE.md. If you are writing instructions Claude should follow for a specific task, make it a skill. If you want something to happen automatically on an event, make it a hook.


Tips for Writing Great Skills

Start with the outcome. What should Claude have produced when the skill completes? State it clearly at the top.

Include quality criteria. "Write a good commit message" is vague. Specify the format, character limits, and what "good" means in your context.

Specify the output format. Should Claude produce a list? A table? Code changes? A report? Silence (just make the changes)?

Handle edge cases. What should happen if there is nothing staged? If the tests fail? If the file does not exist?

Write accurate descriptions. The description field is how Claude decides whether to load a skill automatically. Include the keywords and situations where the skill applies. Be specific enough that it does not trigger on unrelated requests.

Use disable-model-invocation for side effects. Any skill that deploys, commits, sends messages, or modifies external systems should require explicit invocation.


Sharing Skills

Skills can be distributed at different scopes:

  • Project skills: Commit .claude/skills/ to version control. Everyone on the team gets them.
  • Plugins: Create a skills/ directory in your plugin for distribution.
  • Managed settings: Deploy organization-wide through enterprise managed settings.

Troubleshooting

Skill not triggering automatically?

  • Check that the description includes keywords users would naturally say
  • Verify the skill shows up when you ask "What skills are available?"
  • Try invoking it directly with /skill-name to confirm it works
  • Make sure disable-model-invocation is not set to true

Skill triggering too often?

  • Make the description more specific
  • Add disable-model-invocation: true for manual-only invocation

Claude does not see all your skills?

  • Skill descriptions have a context budget (2% of the context window, ~16,000 characters fallback). If you have many skills, some may be excluded.
  • Run /context to check for a warning about excluded skills.
  • Set the SLASH_COMMAND_TOOL_CHAR_BUDGET environment variable to override the limit.

Practical Exercise

Build three skills for your actual workflow:

  1. A task skill — Something you do repeatedly (deploys, releases, migrations). Use disable-model-invocation: true so it only fires on your command.
  2. A reference skill — Domain knowledge Claude should apply automatically (API conventions, code style beyond what is in CLAUDE.md). Use user-invocable: false so Claude loads it when relevant.
  3. A skill with supporting files — A documentation generator or report builder that uses a template file in the skill directory.

Use each skill at least three times and refine the instructions based on the results.