Claude Code Skills Guide: How to Write a SKILL.md
Learn what Claude Code skills are, where SKILL.md files live, the key frontmatter fields, and how to write, test and share skills, with copy-paste examples.
By Claudekit Team Published 12 min read
Skills are the single most useful way to customise Claude Code. A skill is a folder containing a SKILL.md file: instructions Claude adds to its toolkit and uses when relevant, or that you run directly with /skill-name. This guide covers what skills are, where they live, how to write one well, and patterns worth copying. All behaviour described here is checked against the official Claude Code docs as of October 2026.
What a skill is (and when to make one)
Anthropic’s docs put it simply: create a skill when you keep pasting the same instructions, checklist or multi-step procedure into chat, or when a section of CLAUDE.md has grown into a procedure rather than a fact.
The key property is progressive loading. CLAUDE.md loads in full every session. A skill’s description sits in context so Claude knows it exists, but the body loads only when the skill is invoked. Long reference material in a skill costs almost nothing until you need it.
Two more things to know:
- Commands merged into skills. A file at
.claude/commands/deploy.mdand a skill at.claude/skills/deploy/SKILL.mdboth create/deploy. Old command files keep working, but skills support extra features, so prefer them for new work. - Open standard. Claude Code skills follow the Agent Skills standard, so the core format is portable across tools. Claude Code adds extensions such as invocation control, subagent execution and dynamic context injection; our Agent Skills standard explainer shows which fields travel.
Claude Code also ships bundled skills, such as /doctor, /code-review, /debug, /loop and /claude-api. You invoke them the same way as your own. For community skills worth installing, see the best Claude Code skills.
Where skills live
Where you save a skill decides which sessions load it:
| Location | Path | Loads in |
|---|---|---|
| Personal | ~/.claude/skills/<skill-name>/SKILL.md | All your projects on this machine |
| Project | .claude/skills/<skill-name>/SKILL.md | Sessions in this repository (commit it for your team) |
| Nested | <subdir>/.claude/skills/<skill-name>/SKILL.md | Sessions started in or below that subdirectory, or once Claude works on files there |
| Plugin | <plugin>/skills/<skill-name>/SKILL.md | Wherever the plugin is enabled, as /plugin-name:skill-name |
| Enterprise | Managed settings directory | All users where your organisation deploys it |
A few rules worth remembering: don’t name a skill folder synced (reserved for skills synced from your claude.ai account), and skill folders can be symlinks to a shared directory.
Your first skill in three minutes
This example, adapted from the official docs, summarises uncommitted changes and flags risks.
1. Create the folder
mkdir -p ~/.claude/skills/summarize-changes
2. Write SKILL.md
---
description: Summarizes uncommitted changes and flags anything risky. Use when the user asks what changed, wants a commit message, or asks to review their diff.
---
## Current changes
!`git diff HEAD`
## Instructions
Summarize the changes above in two or three bullet points, then list any risks
you notice such as missing error handling, hardcoded values, or tests that need
updating. If the diff is empty, say there are no uncommitted changes.
The !`git diff HEAD` line is dynamic context injection: Claude Code runs the command and replaces the line with its output before Claude reads the skill.
3. Test it
Start claude in a git repo with a small edit, then either ask a matching question (“What did I change?”) or run it directly:
/summarize-changes
The folder name (or the name field, if set) becomes the command.
Frontmatter reference: the fields that matter
All frontmatter fields are optional, but description is strongly recommended. Field names must match exactly; unknown fields are silently ignored.
| Field | What it does |
|---|---|
name | Command name shown in the / menu. Defaults to the directory name. |
description | What the skill does and when to use it. Claude uses it to decide when to load the skill. Put the key use case first. |
when_to_use | Extra trigger phrases or example requests, appended to description. The combined text is truncated at 1,536 characters in the skill listing. |
argument-hint | Autocomplete hint, for example [issue-number]. |
arguments | Named positional arguments for $name substitution. |
disable-model-invocation | true stops Claude from invoking it on its own. Use for side effects like deploys. |
user-invocable | false hides it from the / menu; only Claude can use it (background knowledge). |
allowed-tools | Tools Claude may use without a permission prompt during the turn that invokes the skill. |
disallowed-tools | Tools removed while the skill is active. |
model / effort | Override model or effort level while the skill is active. |
context + agent | context: fork runs the skill in a subagent of the type named in agent. |
paths | Glob patterns; Claude auto-loads the skill only when working with matching files. |
hooks | Hooks registered when the skill is invoked. |
Who can invoke a skill
| Frontmatter | You can invoke | Claude can invoke | Description in context? |
|---|---|---|---|
| (default) | Yes | Yes | Yes |
disable-model-invocation: true | Yes | No | No |
user-invocable: false | No | Yes | Yes |
Use disable-model-invocation: true for anything with side effects (/deploy, /commit, /send-slack-message). You don’t want Claude deciding to deploy because the code “looks ready”.
Arguments and substitutions
Arguments typed after the skill name are available as $ARGUMENTS. Individual positions are $ARGUMENTS[0] or the shorthand $0, $1 and so on.
---
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 sends “Fix GitHub issue 123 following our coding standards…”. If no placeholder exists, Claude Code appends ARGUMENTS: <your input> so nothing is lost.
Other useful variables:
${CLAUDE_SKILL_DIR}: the skill’s own folder, for referencing bundled scripts.${CLAUDE_PROJECT_DIR}: the project root.${CLAUDE_SESSION_ID}: the current session ID, handy for logs.
Combine ${CLAUDE_SKILL_DIR} with allowed-tools so a bundled script runs without a prompt:
---
name: render-chart
description: Render a chart from a CSV file
allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *)
---
Run `${CLAUDE_SKILL_DIR}/scripts/render.sh <csv-file>` to render the chart.
Supporting files: keep SKILL.md lean
A skill folder can hold more than one file:
my-skill/
├── SKILL.md (required: overview and navigation)
├── reference.md (detailed docs, loaded when needed)
├── examples.md (examples, loaded when needed)
└── scripts/
└── helper.py (executed, not loaded)
Reference the extra files from SKILL.md so Claude knows when to open them. The official guidance is to keep SKILL.md under 500 lines and move detail into separate files. Once loaded, skill content stays in context across turns, so every line is a recurring token cost.
Running a skill in a subagent
Add context: fork to run the skill in an isolated subagent. The skill content becomes the subagent’s task; it does not see your conversation history.
---
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 analyse the code
3. Summarise findings with specific file references
Only use context: fork for skills with an explicit task. A skill that is just guidelines (“use these API conventions”) gives the subagent nothing actionable. For the inverse pattern, preloading skills into a custom subagent, see the subagents guide.
Patterns worth copying
Reference skill (conventions). Knowledge Claude applies while working:
---
name: api-conventions
description: API design patterns for this codebase. Use when writing or reviewing HTTP endpoints.
---
When writing API endpoints:
- Use RESTful naming conventions
- Return consistent error formats
- Include request validation
Task skill (procedure with side effects). Pair it with disable-model-invocation: true and a narrow allowed-tools:
---
name: commit
description: Stage and commit the current changes
disable-model-invocation: true
allowed-tools: Bash(git add *) Bash(git commit *) Bash(git status *)
---
Stage the relevant changes and write a conventional commit message.
Path-scoped skill. Use paths: ["src/db/**"] so a migrations skill only loads when Claude touches database code.
Writing descriptions that trigger reliably
The description is the whole routing signal, so treat it like a search snippet:
- Lead with the use case. “Generates Alembic migrations…” beats “This skill helps with…”.
- Name the triggers. Include the words users actually type: “migration”, “schema change”, “add a column”.
- Say when not to use it if it overlaps another skill.
- Stay well under the 1,536-character cap. Long descriptions get truncated, and many skills share a listing budget.
Anthropic’s skill-creator skill can draft a skill, run evals and tune the description for triggering accuracy.
Sharing skills
- Project: commit
.claude/skills/to version control. - Plugin: put skills in a plugin’s
skills/directory and distribute through a marketplace. See the plugins guide. - Organisation: deploy through managed settings.
To install community skills, browse our skills directory. For example, Anthropic’s public repository can be added as a marketplace:
/plugin marketplace add anthropics/skills
/plugin install document-skills@anthropic-agent-skills
That installs the pdf, docx, xlsx and pptx skills.
Security note: a skill’s allowed-tools can grant itself tool access, and workspace trust doesn’t gate that field. Review skills checked into a repository before running Claude Code there.
Troubleshooting
- Skill not triggering: check that
---is the very first line, the YAML parses, and the description matches how you phrase requests. - Triggers too often: narrow the description, add
paths, or setdisable-model-invocation: true. - Claude stops following it mid-session: after auto-compaction, Claude Code re-attaches recent skills within a token budget (the first 5,000 tokens of each, 25,000 combined), so older skills can drop out. Re-invoke the skill.
- Find unused skills: run
/doctor, which reports unused skills against their context cost.
Where skills fit in your kit
Skills are one layer of a broader setup. CLAUDE.md holds facts, skills hold procedures, hooks enforce rules deterministically, MCP servers connect external tools, and plugins package everything. Read What is a Claude kit? for how the layers combine, or skills vs subagents vs hooks for when to use which.
Frequently asked questions
What is the difference between a skill and a slash command?
Custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy. Skills add a folder for supporting files, frontmatter to control who invokes them, and automatic loading when relevant.
Do skills cost context when I'm not using them?
Only a little. By default a skill's name and description sit in context so Claude knows it exists; the full body loads only when the skill is invoked. Skills with disable-model-invocation: true don't put their description in context at all.
Can I use the same SKILL.md outside Claude Code?
Yes, for the core format. Claude Code skills follow the Agent Skills open standard (agentskills.io). Claude Code-specific fields such as context: fork or allowed-tools may be ignored by other tools.
Why isn't my skill triggering?
Usually the description doesn't match how you phrase requests, or the frontmatter doesn't start on the first line of the file. Put the key use case and trigger phrases first in description or when_to_use, and check the YAML parses.