Guide · updated 2026-10-12 · 8 min read
Claude Code Skills: How to Build and Use Them
Claude Code skills are reusable instructions packaged as a folder with a SKILL.md file: YAML frontmatter that says what the skill does and when to use it, followed by Markdown instructions. Put one in .claude/skills/<name>/SKILL.md (project) or ~/.claude/skills/<name>/SKILL.md (personal), and Claude loads it when your request matches its description, or you run it yourself with /name.
The skills docs give the clearest rule for when to write one: when you keep pasting the same instructions, checklist or procedure into chat, or when a section of CLAUDE.md "has grown into a procedure rather than a fact." Unlike CLAUDE.md, a skill's body only loads when it's used.
Skills, commands, CLAUDE.md and subagents
Some quick orientation, because these overlap:
- Custom commands are now skills.
.claude/commands/deploy.mdand.claude/skills/deploy/SKILL.mdboth create/deploy. Old command files keep working. If both exist with the same name, the skill wins. - CLAUDE.md holds facts Claude needs every session. Skills hold procedures and reference material Claude needs sometimes. See how to write a CLAUDE.md file.
- Subagents run in their own context. A skill runs in your current conversation unless you set
context: fork. See the subagents guide.
Skills also follow the Agent Skills open standard, which is why the same folder can work in other tools. Cursor's docs, for example, say it reads .claude/skills/ too.
Build your first skill
This is the docs' starter example, and it's a genuinely useful one. It summarizes your uncommitted changes and flags risks.
mkdir -p ~/.claude/skills/summarize-changes
Save this as ~/.claude/skills/summarize-changes/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.
Now ask "what did I change?" and Claude picks it up, or type /summarize-changes. The !`git diff HEAD` line is dynamic context injection: Claude Code runs the command and swaps in its output before Claude sees the skill, so Claude works from your real diff.
Claude Code watches skill directories, so edits apply in the current session without a restart. If you created a brand-new top-level skills directory mid-session, run /reload-skills.
Where skills live
| Location | Path | Loads in |
|---|---|---|
| Personal | ~/.claude/skills/<name>/SKILL.md |
All your projects on this machine |
| Project | .claude/skills/<name>/SKILL.md |
This repo. Commit it for your team. |
| Nested | <subdir>/.claude/skills/<name>/SKILL.md |
Sessions in or below that folder, or once Claude works on files there |
| Plugin | <plugin>/skills/<name>/SKILL.md |
Wherever the plugin is enabled, as /plugin-name:skill-name |
| Enterprise | Managed settings directory | Everyone your org deploys it to |
One gotcha that bites people: cloud sessions, routines and Cowork don't read ~/.claude/skills/ from your machine. For those, either commit the skill to the repo's .claude/skills/ or enable it on your claude.ai account.
When names collide, enterprise beats personal and personal beats project. A project skill with the same name as a bundled skill replaces it.
The frontmatter fields that matter
Every field is optional. description is the one you should always write, because it's how Claude decides when to use the skill. The frontmatter reference has the full list; these are the ones worth knowing:
| Field | What it does |
|---|---|
name |
Command name. Defaults to the folder name. |
description |
What it does and when to use it. Put the key use case first. |
when_to_use |
Extra trigger phrases, appended to the description. |
disable-model-invocation |
true means only you can run it, with /name. |
user-invocable |
false hides it from the / menu so only Claude uses it. |
allowed-tools |
Tools Claude can use without asking, during the turn that invokes the skill. |
argument-hint |
Autocomplete hint, such as [issue-number]. |
context |
fork runs the skill in a subagent. |
agent |
Which subagent type to use with context: fork. |
model / effort |
Override model or effort while the skill is active. |
paths |
Globs that limit when Claude auto-loads the skill. |
hooks |
Hooks registered when the skill is invoked. |
Field names use hyphens (except when_to_use) and must match exactly. Claude Code ignores a field it doesn't recognize, without an error. The combined description and when_to_use text is truncated at 1,536 characters in the skill listing.
Control who runs it
This is the single most important decision for each skill.
---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---
Deploy $ARGUMENTS to production:
1. Run the test suite
2. Build the application
3. Push to the deployment target
4. Verify the deployment succeeded
With disable-model-invocation: true, Claude can't decide to deploy because your code "looks ready." You type /deploy staging. The description also stays out of context until you invoke it.
The opposite, user-invocable: false, suits background knowledge such as a legacy-system-context skill that Claude should consult when relevant but that isn't a meaningful command for you to type.
A small detail from the docs: /deploy staging at the start of a message runs the skill. Typing "go ahead and /deploy to staging" mid-sentence only gives Claude permission to run it.
Arguments
Skills take arguments through substitutions:
$ARGUMENTSis everything you typed after the skill name.$0,$1(or$ARGUMENTS[0]) are individual arguments, with shell-style quoting.- Named arguments: declare
arguments: [issue, branch]and use$issueand$branch. ${CLAUDE_SKILL_DIR}points at the skill's folder, handy for bundled scripts.
The docs' issue-fixing skill from the best practices page is a good template:
---
name: fix-issue
description: Fix a GitHub issue
disable-model-invocation: true
---
Analyze and fix the GitHub issue: $ARGUMENTS.
1. Use `gh issue view` to get the issue details
2. Understand the problem described in the issue
3. Search the codebase for relevant files
4. Implement the necessary changes to fix the issue
5. Write and run tests to verify the fix
6. Ensure code passes linting and type checking
7. Create a descriptive commit message
8. Push and create a PR
Run it with /fix-issue 1234.
Bundle scripts without permission prompts
Combine ${CLAUDE_SKILL_DIR} with allowed-tools and a skill can run its own script without prompting you:
---
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.
The allowed-tools grant only lasts for the turn that invoked the skill. It doesn't restrict other tools, and it doesn't carry into your next message. For session-wide approvals, use permission rules in settings.
Supporting files work the same way. Keep SKILL.md under 500 lines, put long reference material in reference.md or examples.md next to it, and link them from SKILL.md so Claude knows when to open them.
Run a skill in a subagent
Add context: fork and the skill runs in an isolated subagent, which doesn't see your conversation history:
---
name: deep-research
description: Research a topic thoroughly
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
Forked skills run in the background by default. Set background: false to wait for the result in the same turn. Two cautions from the docs: context: fork only makes sense for skills with an actual task, not guidelines, and edits made by a backgrounded fork aren't covered by /rewind, so use git to revert them.
Bundled skills you already have
Claude Code ships with bundled skills including /code-review, /debug, /loop, /batch, /claude-api and /doctor. A few worth knowing:
/runand/verifylaunch your app and check a change against the running app./run-skill-generatorrecords how to build and launch your project as a project skill so they stop guessing.- If your project has a skill named
verifyorsimplify, Claude Code (v2.1.286 or later) tells Claude to run it before each commit, except for docs or test changes. /doctorchecks your setup, including unused skills and their context cost.
When skills don't behave
Not triggering. Make sure the description uses words you'd actually say. Ask "What skills are available?" to check it loaded. If the YAML is malformed the body still loads but with empty metadata, so /name works and auto-matching doesn't. Run claude plugin validate .claude/skills to find bad frontmatter.
Triggering too often. Make the description more specific, or add disable-model-invocation: true.
Followed at first, then ignored. Claude Code doesn't re-read the skill file on later turns, so word rules as standing instructions ("run the tests after every edit"). After compaction, only the first 5,000 tokens of each recent skill are re-attached, so put the important parts at the top. Rules that must hold every time belong in a hook, which you can define in the skill's own hooks frontmatter.
Descriptions cut short. With many skills, Claude Code drops descriptions of your least-used ones to fit a budget of 1% of the context window. Raise it with skillListingBudgetFraction, or prune.
Bottom line
Write your first skill for the procedure you explain most often: a release checklist, a PR summary, a migration recipe. Give it a specific description, set disable-model-invocation: true on anything with side effects, keep SKILL.md short with reference files beside it, and commit project skills so your team gets them. When a CLAUDE.md section starts reading like a how-to, it's a skill. More on how skills fit into a full setup in Claude Code best practices.
Subscribe to Agent Shipped for a copy-paste skill, hook or subagent in every issue, twice a week.
FAQ
What is a skill in Claude Code?
A skill is a folder with a SKILL.md file containing YAML frontmatter and Markdown instructions. Claude loads it automatically when your request matches its description, or you run it directly by typing /skill-name.
What is the difference between skills and slash commands?
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 and frontmatter to control who can invoke them.
How do I stop Claude from running a skill on its own?
Add disable-model-invocation true to the frontmatter. Claude can then only run it when you type /skill-name, which is what you want for deploys, commits and anything with side effects.
Do skills cost context when they are not used?
Only a little. Skill names and descriptions are listed in context so Claude knows what exists, but the full body loads only when the skill is invoked. Skills with disable-model-invocation true keep even the description out of context.