
Claude Code Skills: What They Are, Where They Live, and How to Write One
Claude Code skills explained: what a SKILL.md is, where skills live, how to write one, and the skills I actually run. Checked against the docs on 09/29/2026.
Why this matters
A Claude Code skill is a folder with a SKILL.md file inside it. The file has short YAML frontmatter and a markdown body of instructions. Claude reads only the name and description at the start of a session, then loads the full body when the task matches or when you type /skill-name. Personal skills live in ~/.claude/skills/ and project skills live in .claude/skills/ inside the repository. To write one, make the folder, write a description that says what the skill does and when to use it, and keep the body short. Most skills that do not trigger have a vague description.
A Claude Code skill is a folder containing a SKILL.md file: a few lines of frontmatter and a body of instructions. Claude adds it to its toolkit, uses it when your task matches the description, or runs it when you type /skill-name. This page covers where skills live, how Claude decides to load one, how to write one you can copy, and the skills I run myself.
Everything about product behavior here comes from the Claude Code docs as of 09/29/2026. Where I describe my own setup, I say so.
What a Claude Code skill is
The docs put it in one sentence: create a SKILL.md file with instructions, and Claude adds it to its toolkit. Claude uses skills when relevant, or you invoke one directly with /skill-name.
The docs give two signals for when a skill is worth writing. You keep pasting the same instructions, checklist or multi-step procedure into chat. Or a section of your CLAUDE.md has grown into a procedure instead of a fact. A skill body loads only when it is used, so long reference material costs almost nothing until you need it.
Skills follow the Agent Skills open standard, which works across multiple AI tools. Claude Code extends that standard with invocation control, subagent execution and dynamic context injection. So a skill written for Claude Code may use fields that other tools do not read.
Claude Code also ships bundled skills. The docs name /doctor, /code-review, /batch, /debug, /loop and /claude-api, and a trio for running your app: /run, /verify and /run-skill-generator. Bundled skills are prompt-based. They give Claude detailed instructions and let it orchestrate the work with its own tools.
Where skills live
Where you save a skill decides which sessions load it. The docs list these locations:
| 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 so your team gets it too |
| Nested | <subdir>/.claude/skills/<skill-name>/SKILL.md | Sessions started in or below that subdirectory |
| Plugin | <plugin>/skills/<skill-name>/SKILL.md | Wherever the plugin is enabled, as /plugin-name:skill-name |
| Enterprise | .claude/skills/<skill-name>/SKILL.md in the managed settings directory | All users where the organization deploys it |
| claude.ai account | Skills enabled for your claude.ai account | Cowork sessions, cloud sessions, and terminal sessions signed in with that account |
Three details that catch people. First, if the same name exists in two places, enterprise wins over personal and personal wins over project. Second, personal skills in ~/.claude/skills/ are not read by Cowork or cloud sessions, so a routine that calls a personal-only skill will report that it was not found. Third, project skills in a subdirectory below where you started do not load at startup. They load the first time Claude reads or edits a file in that subdirectory.
Claude Code watches these folders for changes, so adding or editing a skill takes effect within the session. The one exception is a top-level skills folder that did not exist when the session started. For that, run /reload-skills.
How Claude decides to load a skill
Claude loads a listing of every skill name and description into context so it knows what is available. It matches your task against those descriptions. The full body loads only when you invoke the skill or Claude picks it.
That gives you three modes, controlled by two frontmatter fields:
| Frontmatter | You can invoke | Claude can invoke | Context behavior |
|---|---|---|---|
| (default) | Yes | Yes | Description always in context, full skill loads when invoked |
disable-model-invocation: true | Yes | No | Description not in context, full skill loads when you invoke |
user-invocable: false | No | Yes | Description always in context, full skill loads when invoked |
Use disable-model-invocation: true for anything with side effects, like a deploy or a commit. The docs say you do not want Claude deciding to deploy because your code looks ready. Use user-invocable: false for background knowledge that is not a meaningful command.
Two costs are worth knowing before you write your fiftieth skill.
The listing has a budget. It scales at 1% of the model’s context window. When you have many skills, Claude Code drops descriptions to fit, starting with the skills you invoke least. The docs say the dropped text is exactly the keywords Claude needs to match your request. Each entry is also capped at 1,536 characters for description and when_to_use combined, so put the key use case first.
A loaded body stays. Once a skill runs, its rendered content enters the conversation as one message and stays across later turns. Claude Code does not re-read the file. After auto-compaction, it re-attaches the most recent invocation of each skill, keeping the first 5,000 tokens of each, within a combined budget of 25,000 tokens. Older skills can be dropped entirely if you invoked many in one session.
If you worry about what all of this costs against your plan, see Claude usage limits, explained. The short version is that descriptions are the always-on cost and bodies are the pay-as-you-go cost.
How to write a Claude Code skill
Every skill needs a SKILL.md. It has two parts: YAML frontmatter between --- markers that tells Claude when to use the skill, and markdown with the instructions Claude follows when it runs.
All frontmatter fields are optional. Only description is recommended. The fields I use most, from the docs’ reference table:
name: the command name. It defaults to the directory name.description: what the skill does and when to use it. Claude uses this to decide.disable-model-invocation:truemeans only you can invoke it.allowed-tools: tools Claude can use without asking during the turn that invokes the skill. The grant clears when you send your next message.argument-hint: a hint shown in autocomplete, such as[issue-number].
Field names must match the table exactly. Claude Code ignores a field it does not recognize and does not report an error. Also, the frontmatter is read only when the opening --- is the first line of the file.
Here is a small skill you can copy. It writes a changelog entry from recent commits. Save it as ~/.claude/skills/changelog-entry/SKILL.md:
---
name: changelog-entry
description: Drafts a changelog entry from recent git commits. Use when the user asks for release notes, a changelog entry, or a summary of what shipped.
argument-hint: "[version]"
allowed-tools: Bash(git log *)
---
## Recent commits
!`git log --oneline -30`
## Instructions
Write a changelog entry for version $ARGUMENTS from the commits above.
- Group changes under Added, Changed and Fixed.
- One line per change, in plain language, starting with a verb.
- Skip merge commits and commits that only touch tests.
- If no version was given, use the heading "Unreleased". Four things in that file are doing real work.
The description names both the job and the phrases a person would say: release notes, changelog entry, what shipped. That is what Claude matches against.
The !`git log --oneline -30` line is dynamic context injection. Claude Code runs the command and replaces the line with its output before Claude sees the skill, so the instructions arrive with the commits already inlined.
The allowed-tools line is not decoration. The docs say injected commands never prompt for permission while a skill renders, and outside auto mode a command whose permission check does not return allow aborts the whole invocation. Pre-approving git log here keeps the skill from failing.
$ARGUMENTS receives whatever you type after the skill name. Run /changelog-entry 2.4.0 and the body reads “for version 2.4.0”.
To test it, open a git project and ask “write release notes for the last few commits”. Then invoke it directly with /changelog-entry 2.4.0. If the first works, the description is doing its job. If only the second works, the description is the problem.
Supporting files
A skill can be more than one file. The docs show a SKILL.md for overview and navigation, plus optional reference files and a scripts/ folder. Reference the extra files from SKILL.md so Claude knows what each contains and when to load it. The docs recommend keeping SKILL.md under 500 lines and moving detailed reference material to separate files.
The skills I actually run
I keep my personal skills in ~/.claude/skills/. I counted 152 folders there with ls -d */ on 09/29/2026. One of them is synced, the folder Claude Code manages for skills downloaded from claude.ai, so the number I wrote myself is smaller. That is far more skills than I need loaded at once, and the listing budget above is the reason I care about description length.
Here are four, all technical, read from their SKILL.md files on 09/29/2026. I picked them because each teaches a different lesson.
codex-search, at ~/.claude/skills/codex-search/SKILL.md. It runs a ranked local search over my own notes. The description is one sentence of what it does, then a “Skip when” clause: “Skip when the exact node id is already known.” It is one file, 80 lines. The body has sections for when to fire, when to skip, how to run it, known limits, and anti-patterns. The lesson is that a small skill with a clear skip condition is easy for Claude to route.
blog-seo-gate, at ~/.claude/skills/blog-seo-gate/SKILL.md. It checks a blog post title and metadata before I publish. It is one file of 237 lines. Its frontmatter carries version and a triggers list of phrases like “new blog post” and “check title”. Neither field is in the docs’ frontmatter table. Since the docs say unrecognized fields are ignored, I read that list as decoration, and the description is what routes the skill. I would not copy it.
conductor, at ~/.claude/skills/conductor/SKILL.md. It classifies a goal and hands it to other skills in order. It is one file of 383 lines, with a “When this skill applies” section and a “Do NOT trigger when” list in the body. My reading, which is an inference and not something the docs state: the body loads only after Claude has already chosen the skill, so a “do not trigger” list in the body cannot stop a wrong trigger. That work belongs in the description.
hallmark, at ~/.claude/skills/hallmark/SKILL.md. It is a design builder and critic. The description is one short line. The SKILL.md is 549 lines, over the docs’ 500-line guidance, and the folder has references, docs and site subfolders, with 221 files by my find count. The lesson runs both ways. Supporting folders are the right home for bulk. A 549-line entry file is a recurring context cost every time it loads.
None of these are clever. Each replaces a procedure I would otherwise retype or forget.
Skills vs slash commands vs subagents vs CLAUDE.md
These four get confused, and the docs draw the lines like this.
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. Old command files keep working. If a skill and a command file share a name, the skill wins. Prefer a skill for new work, since skills also support supporting files.
CLAUDE.md. It loads every session. The docs say to put “always do X” rules there, and to put reference material Claude needs only sometimes, or a workflow you trigger with /name, in a skill. Their rule of thumb is to keep CLAUDE.md under 200 lines. For how project instructions work, see Claude Code AGENTS.md and CLAUDE.md.
Subagents. A subagent is an isolated worker with its own context window. Only a summary returns to your main conversation. A skill adds to your main window. They combine: a skill with context: fork runs in a subagent, and a subagent can preload skills through its skills field. If you are deciding between them, the full comparison is in Claude Code skills vs subagents.
Hooks. The docs draw this line clearly: a hook always fires on its event, while a skill is interpreted by Claude and the outcome can vary. An instruction like “never edit .env” inside a skill is a request, not a guarantee. If a rule must hold every time, use a hook. I cover that in the Claude Code hooks tutorial.
For the whole picture of how these pieces fit into one setup, start at the Claude Code complete guide.
Common mistakes, and when a skill does not trigger
The docs give a short debugging path for a skill that does not fire. Work through it in order.
- Check the description. It should include keywords a person would naturally say. This is the most common cause.
- Check the skill is listed. Ask “What skills are available?” If it is missing, the file is in the wrong place or the folder name is wrong.
- Rephrase your request to match the description more closely.
- Invoke it directly with
/skill-name. If that works, the body is fine and the description is the problem.
If the YAML is malformed, Claude Code loads the skill body with empty metadata. /skill-name still works, but Claude cannot match against the description. Run with --debug to see the parse error. The docs also say claude plugin validate ~/.claude/skills finds files whose frontmatter does not parse, and it needs Claude Code v2.1.233 or later.
A few other mistakes I see, each grounded in the docs:
- A vague description for a skill that fires too often. Make it more specific, or add
disable-model-invocation: trueif you only want it by hand. - Guidelines with no task under
context: fork. The docs warn that a forked subagent given only guidelines returns without meaningful output. The subagent does not see your conversation, so the instructions must stand alone. - Expecting a skill to stick after compaction. If a skill seems to stop influencing behavior, the docs suggest strengthening the description and instructions, or re-invoking it after compaction.
- Never checking what your skills cost. Run
/doctorfor an estimate of the listing’s context cost. Run/skill-doctorto see what each skill costs and how often it gets used. The docs say/skill-doctorrequires v2.1.252 or later. - Never testing against a baseline. Seeing a skill trigger tells you Claude found it, not that it did what you meant. The docs recommend running a few realistic prompts in a fresh session with the skill and again with it disabled, then comparing.
Skills are the right tool for procedures Claude should apply with judgment. When you catch yourself pasting the same checklist for the third time, that is the moment to write one.
· Frequently asked
FAQ
What are Claude Code skills, and do they work in Claude Code?
Yes, skills are a built-in part of Claude Code. A skill is a folder with a SKILL.md file of instructions. Claude uses the skill when your task matches its description, or you invoke it directly with /skill-name. Skills follow the Agent Skills open standard, and Claude Code adds features on top of it. Source: code.claude.com/docs/en/skills, read 09/29/2026.
Where do Claude Code skills live?
Personal skills live in ~/.claude/skills/<skill-name>/SKILL.md and load in all your projects on that machine. Project skills live in .claude/skills/<skill-name>/SKILL.md and load in sessions in that repository. Plugins, an enterprise managed directory, and skills synced from your claude.ai account are the other locations.
How do I give Claude Code a skill, or create one?
Create a folder such as ~/.claude/skills/my-skill/, add a SKILL.md with a description in the frontmatter and instructions below it, and start a session. Claude Code watches the skills folders and picks up new skills without a restart. If the top-level skills folder did not exist when the session started, run /reload-skills.
What is the difference between Claude Code 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, frontmatter to control who can invoke them, and automatic loading by Claude. Built-in commands such as /help and /compact are separate.
What are the top skills for Claude Code?
Start with the bundled ones. The docs list /doctor, /code-review, /batch, /debug, /loop and /claude-api, plus /run and /verify for launching and checking your app. After that, the best skill is the one that replaces a procedure you keep pasting into chat, such as a release checklist or a commit message format.
Why is my Claude Code skill not triggering?
Usually the description is too vague or does not contain words you would naturally say. Check that the skill appears when you ask "What skills are available?", rephrase your request closer to the description, and invoke it with /skill-name to confirm the body works. Also check that the opening --- is the first line of the file, because the frontmatter is ignored otherwise.
· Sources & further reading
Sources & Further Reading
Further reading
- Claude Code Skills vs Subagents vs Hooks vs CLAUDE.md: Which One Fits Which Job /blog/claude-code-skills-vs-subagents Claude Code skills vs subagents vs hooks vs CLAUDE.md as of 09/29/2026: when each loads, whose context it uses, and a simple decision sequence for picking one.
- Claude Code AGENTS.md Support: When CLAUDE.md Still Wins /blog/claude-code-agents-md Claude Code reads AGENTS.md since 2.1.277, but only when the project has no CLAUDE.md. If both exist, CLAUDE.md wins. The four modes, the one-line fix and the limits.
- SvelteKit MCP: The Official Svelte Server, and What Its Autofixer Found in 134 Components /blog/sveltekit-mcp-server-claude-code The official Svelte MCP server gives Claude Code current Svelte 5 docs and an autofixer. I ran it on 134 components: 70 missing keys, 34 files it could not read.
- Fable 5.1 vs Opus 5 in Production: A Whole Day on Fable Used 19% of a Max Weekly Window /blog/claude-fable-5-vs-opus-5 Same harness, same day: 2,443 Fable 5.1 turns and 1,120 Opus 5 turns after a weekly reset consumed 19% of the Max weekly window, and the 5-hour window peaked at 59% without capping. Fable errored less per tool call, hit more permission gates, and would have cost 1.4x per turn on the API, not 2x.
- Claude Code 'Compaction Failed': Causes and 3 Fixes /blog/claude-context-management-dev-docs 'Compaction failed: conversation could not be reduced below the context limit' means state lived in the chat. Three files fix it: plan, context, tasks.
Built from these systems
Claude Code Project Memory Kit $29
Four Claude Code skills, an install script and a CLAUDE.md template that keep a knowledge base inside your repo, so the next session starts from what the last one learned.
Want more of this in your Google results?
What do you think?
I post about this stuff on LinkedIn every day and the conversations there are great. If this post sparked a thought, I'd love to hear it.
Discuss on LinkedIn