What Are Claude Code Skills (and How to Write One)
If you use Claude Code, you've probably noticed that its behavior drifts. It writes a great commit message on Monday and a lazy one-liner on Thursday. It runs your tests when it feels like it. You end up re-typing the same instructions — "use conventional commits," "check the error path" — into every session.
Skills fix that. A skill is a small Markdown file that Claude Code loads on its own, only when it's relevant, so a procedure you care about gets applied consistently without you having to remember to ask. This article covers what a skill actually is, how the description field decides when it fires, where the files live, and a full walkthrough of writing one — including a real SKILL.md you can copy.
What a skill actually is
A skill is a folder with a Markdown file in it. That's the whole format. The file, SKILL.md, has two parts:
- YAML frontmatter — metadata at the top, most importantly a
nameand adescription. - The body — the actual instructions, written in plain Markdown.
When Claude Code starts, it reads the frontmatter of every skill it can find but not the bodies. It keeps a lightweight index of names and descriptions. Then, as you work, it watches for a task that matches one of those descriptions. When it finds a match, it pulls that skill's body into the current conversation and follows it.
The key idea is that a skill loads into your current context. It's not a separate agent or a background process — it's the same Claude, in the same thread, that just got handed a page of relevant instructions at the moment it needed them. That's why skills are cheap: they're text, added to the prompt only when they earn their place.
This lazy-loading is deliberate. If Claude Code stuffed every skill body into context up front, a dozen skills would bury your actual conversation in boilerplate. Instead it pays the cost of a skill only when that skill is in play. Some skills push this further by keeping SKILL.md short and pointing to other files in the same folder — a reference doc, a script, a template — that Claude reads only if the task goes deep enough to need them.
How the description drives triggering
Here is the single most important thing to understand: Claude decides whether to load a skill by reading its description and nothing else. The body is invisible until after the decision is made. So the description isn't documentation for humans — it's the trigger.
A vague description is a skill that never fires. Compare these two:
# Never triggers — too abstract to match anything
description: "Helps with database work."
# Triggers reliably — names the situations and keywords
description: >
Use when adding or changing a database migration. Enforces
backwards-compatible, reversible migrations with a rollback plan.
Trigger on "migration", "alter table", "schema change", or edits
under db/migrations/.
Write descriptions for the trigger. Name the concrete situations, the keywords a user would actually type, and the file paths involved. Think about what you'd say out loud right before you'd want this skill to kick in, and put that in the description.
You're not fully at the mercy of matching, either. You can force a skill to load by invoking it explicitly — typically /skill-name — which is useful both for skills you want on demand and for testing whether a new skill's body works before you tune its description. If /my-skill behaves correctly but auto-triggering doesn't happen, you've isolated the problem to the description, not the skill itself.
Where the files live
Claude Code discovers skills automatically from two locations:
.claude/skills/<name>/SKILL.mdin your project — checked into git, shared with your whole team. Everyone who clones the repo gets the same behavior.~/.claude/skills/<name>/SKILL.mdin your home directory — personal skills that follow you across every project.
There's nothing to register or install beyond putting the file in the right place. Project skills are the reason skills scale past you: commit them, and a house convention stops living in one person's muscle memory and starts applying to everyone's sessions.
Writing your first skill
Let's write one end to end. The goal: make Claude Code write disciplined commit messages every time, without being asked.
Create the folder and file:
mkdir -p .claude/skills/conventional-commits
$EDITOR .claude/skills/conventional-commits/SKILL.md
Then write the skill:
---
name: conventional-commits
description: >
Use when writing a git commit message or when the user asks to commit
changes. Enforces Conventional Commits format — type(scope): summary —
with a body that explains why. Trigger on "commit", "commit message",
"git commit", or right after staging changes.
---
# Conventional Commits
When you write a commit message, follow this exactly:
1. **Subject:** `<type>(<scope>): <summary>` — lowercase, imperative mood,
72 characters or fewer. Valid types: feat, fix, refactor, perf, docs,
test, chore, build, ci.
2. **Body:** one short paragraph on *why* the change was made — not a
restatement of the diff. Wrap at 72 columns. Omit it only for trivial
changes.
3. **Breaking changes:** add a `BREAKING CHANGE:` footer describing the
migration path.
4. Never invent a scope. Omit it when the change spans the repo.
Example:
feat(auth): add refresh-token rotation
Refresh tokens were single-use but never rotated, so a leaked token
stayed valid until expiry. Rotate on every use and revoke the prior
token so a stolen one dies on the next legitimate refresh.
That's a complete, working skill. Note what's doing the work:
- The description names the exact moments it should fire ("commit," "git commit," "after staging changes"), so Claude loads it precisely when you're about to commit and not otherwise.
- The body is imperative and numbered. Skills work best as rules Claude can execute, not prose it has to interpret. Keep it tight; a wall of paragraphs dilutes the instruction.
- The worked example shows the exact output shape you want. One good example is worth three paragraphs of description.
Now start Claude Code in the repo and ask it to commit a change. Instead of a generic message, you should see the format above — applied automatically, because the description matched.
Skills vs. just prompting
You might reasonably ask: why not just type these rules into the chat when I want them? Sometimes that's the right call — for a genuine one-off, prompting directly is less ceremony than authoring a file. But a skill wins the moment repetition enters the picture:
- It's automatic. You don't have to remember to invoke it. The description fires it at the right time, including times you'd have forgotten.
- It's reusable and shared. Write the rule once; it applies in every session and, if it's a project skill, for every teammate. Prompts evaporate when the conversation ends.
- It's versioned. A skill is a file in git. It gets reviewed, improved, and rolled back like any other code. Your team's conventions live somewhere durable instead of in scattered chat history.
- It stays out of the way. Because bodies load lazily, having twenty skills installed doesn't clutter your context. Only the relevant one shows up.
The mental split is simple: a skill is a way of working you want applied consistently and in place. It's not the tool for every job — when you want an independent, adversarial second opinion, reach for a subagent instead (a separate Claude with its own context). Both have their place; a skill is the cheaper of the two and the one you'll write most.
If you'd rather learn from working examples than a blank file, the open-source claude-code-starter repo ships a real ship skill (plus a subagent and a CLAUDE.md template) you can read, run, and adapt.
Wrapping up
A Claude Code skill is deceptively small: a Markdown file with a name, a description, and some rules. But that small file changes the economics of working with an agent. Instead of re-explaining your conventions every session, you encode them once and let the description decide when they apply. Get that description right — specific, situation-named, in the words a user would actually type — and the rest is just writing down what you already know good work looks like. Start with one skill for a task you keep correcting by hand, commit it, and let the consistency compound from there.
Related guides
- Doing Code Review With Claude Code
- Debugging Methodically With Claude Code
- Setting Up Claude Code for a Team
Set up Claude Code the right way
Start free with the open-source starter — a ship skill, an adversarial-reviewer subagent, a bug-hunt workflow, and a CLAUDE.md template. Want the full kit? The Pro Pack adds 6 skills, 3 subagents, 3 workflows, 4 templates and a handbook.