You asked Claude Code for release notes for the third time this week and pasted the same four lines of instructions again. That is the moment to write a skill. A skill is a folder with one file, SKILL.md, that holds those instructions so you can type /release-notes instead, or just ask and let Claude pick the skill up on its own.
The file takes about ten minutes to write. Getting it to trigger reliably takes a bit longer, and that is where most first skills fail. This post covers both. I checked every field and behavior below against Anthropic's Claude Code docs on 2026-10-08. I parse-checked the example's frontmatter and ran its git log command, but I did not run the finished skill inside a live Claude Code session for this post, so treat the "what you should see" lines as what the docs describe, not a transcript.
What goes in a SKILL.md file?
Two parts: YAML frontmatter between --- lines, then Markdown instructions. Per the docs, every frontmatter field is optional, and only description is recommended. The ones you will use first:
| Field | What it does |
|---|---|
name | The slash command. Defaults to the folder name. Lowercase letters, numbers, hyphens. |
description | What the skill does and when to use it. Claude reads this to decide whether to load the skill. |
when_to_use | Extra trigger phrases. Appended to description. |
disable-model-invocation | true means only you can run it. |
allowed-tools | Tools Claude may use without asking, for that turn only. |
Two traps from the docs. Unrecognised fields are ignored silently, so a typo like descripton gives you a skill with no description and no error. And frontmatter is only read if the opening --- is the very first line of the file. If the YAML doesn't parse, the skill still loads, with no fields set, which means Claude has nothing to match against.
Where do you save it so Claude Code finds it?
Pick one:
~/.claude/skills/<name>/SKILL.mdfor every project you open.claude/skills/<name>/SKILL.mdinside a repo, for that project (commit it and your team gets it)
Claude Code watches these folders, so a new or edited skill works without a restart. If two skills share a name, personal beats project. A skill also beats an old .claude/commands/ file of the same name, because commands were merged into skills and both create the same slash command.
If you already keep notes in a CLAUDE.md, don't move them. That file loads every session. A skill loads on demand. The split is covered in the decision guide for skills, hooks and subagents.
A first skill that earns its keep: release notes
This is the example I built for the post. It uses the part of skills people skip: running a command before Claude sees the prompt.
mkdir -p ~/.claude/skills/release-notes
Save this as ~/.claude/skills/release-notes/SKILL.md:
---
name: release-notes
description: Drafts customer-facing release notes from recent git commits. Use when the user asks for release notes, a changelog entry, "what shipped", or an update to send to customers.
when_to_use: Also use for "write up this week's changes" or "summarise commits since the last tag".
---
## Recent commits
!`git log --oneline --no-merges -20`
## Instructions
Write release notes from the commits above for people who use the product, not people who build it.
1. Group into three headings: New, Improved, Fixed. Skip a heading if it has nothing.
2. One line per change, starting with a verb. No commit hashes, no file names.
3. Drop anything a customer would never notice: refactors, CI, dependency bumps, typo fixes in code.
4. If a commit message is too vague to describe, list it under "Needs a human" at the end instead of guessing.
5. Output Markdown only.
If the commit list above is empty, say there is nothing to release and stop.
I parsed that frontmatter with a YAML parser and got name, description and when_to_use back as expected. I also ran the git log line on this site's repo and it prints one line per commit.
Three choices in there are worth copying:
- The
!line. Claude Code runs the command and swaps in its output before Claude reads the skill. Claude works from your real commits, not from guesses about your repo. One catch from the docs: if that command fails, the whole invocation aborts. - A rule for the empty case. Without it, Claude invents release notes from nothing when the log is empty.
- A "needs a human" bucket. It stops the skill from fabricating a description for a commit called
fix stuff.
How do you test a skill?
Do these in order, because each one narrows down the failure.
- Open a git repo and run
claude. - Ask:
What skills are available?Your skill name should be in the list. If it isn't, the file is in the wrong place or the folder name is wrong. - Type
/release-notes. This bypasses matching entirely. If it works here, the instructions are fine and any later problem is about triggering. - Now ask in plain words:
write release notes for what we shipped this week. This tests whether the description gets matched.
Step 3 versus step 4 is the diagnostic that saves the most time. Direct invocation works, natural-language doesn't: fix the description. Neither works: fix the file.
Why won't my skill trigger, and how do you fix the description?
The docs' own checklist is short: put keywords people naturally say in the description, confirm the skill appears in the list, rephrase to match the description more closely, and invoke directly with /skill-name. In practice the causes I'd check, in order:
1. The description describes the skill instead of the request. Compare:
| Weak | Better |
|---|---|
Release notes helper | Drafts customer-facing release notes from recent git commits. Use when the user asks for release notes, a changelog entry, or "what shipped". |
The second contains the words someone types. Claude is matching your sentence against that text.
2. The key use case is buried. The combined description and when_to_use text is truncated at 1,536 characters in the skill listing, so lead with what matters.
3. You have a lot of skills. The docs say Claude Code loads a listing of names and descriptions within a budget (1% of the model's context window by default), and when it overflows, it drops descriptions starting with the skills you use least. The name stays, the keywords vanish, and the skill stops matching. Run /doctor to see the listing's context cost. The fix is fewer skills, shorter descriptions, or raising the skillListingBudgetFraction setting.
4. Broken frontmatter. No error, no fields. Run with --debug to see the parse error. The docs also point to claude plugin validate .claude/skills (v2.1.233 or later) to find SKILL.md files whose frontmatter doesn't parse.
5. Two descriptions overlap. If release-notes and changelog both claim "what shipped", Claude may pick the wrong one. Make each description say what it does that the other doesn't, or merge them.
The opposite problem, a skill firing when you didn't want it, has two fixes in the docs: make the description more specific, or set disable-model-invocation: true.
Why does Claude stop following my skill halfway through?
This one surprises people. When a skill is invoked, its rendered text enters the conversation once and stays there. Claude Code does not re-read the file on later turns. So write instructions that apply to the whole task ("Run the tests after every edit"), not one-time steps ("Run the tests").
After the conversation is compacted, Claude Code keeps only the first 5,000 tokens of each invoked skill, within a shared 25,000-token budget. Put the rules that matter most at the top of the file, and re-invoke the skill if Claude drifts after a long session.
If a rule must hold every single time, don't rely on a skill at all. The docs say to move it into a hook, which Claude Code runs whether or not Claude is following the skill. That trade-off is the core of the skills vs hooks vs subagents guide.
When should a skill be manual-only?
Anything that does something you'd regret by accident. The docs' example is a deploy skill:
---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---
With that flag, you can run /deploy staging and Claude can't decide on its own that now is a good time. The docs also note it keeps the description out of context, so it costs nothing until you call it. Arguments you type after the name arrive through $ARGUMENTS.
Does the same SKILL.md work in the Claude app?
Partly. The Claude apps support skills on Free, Pro, Max, Team and Enterprise plans, but they require code execution and file creation to be switched on (Settings > Capabilities on individual plans). Custom skills are uploaded as a ZIP under Customize > Skills, and they aren't visible to colleagues until shared. Anthropic's help page lists the usual upload failures: a missing skill file, a folder name that doesn't match the skill name, and invalid characters in the name or description.
Two cautions. The ! command injection is documented on the Claude Code skills page, and I found nothing saying the Claude apps run it, so don't count on it there. And the docs list personal skills in ~/.claude/skills as not loading in Cowork or cloud sessions. If you want one skill to work everywhere, keep it to plain instructions and test it in each place.
A short checklist before you call it done
- The first line of the file is
---. descriptionleads with the use case and includes the phrases you'd actually type./your-skillworks when typed directly.- A plain-English request also triggers it (try two different phrasings).
- Side-effect skills have
disable-model-invocation: true. - Critical rules sit near the top of the file, not the bottom.
- SKILL.md is under 500 lines; the docs recommend moving long reference material into separate files that SKILL.md links to.
If you want more worked examples, the Skills and reusable workflows lesson has longer multi-step examples. Its layout (a single review-pr.md file with no frontmatter) doesn't match the folder-plus-SKILL.md structure in Anthropic's current docs, so copy the ideas from it and the file format from this post. For where CLAUDE.md fits, see how to write a CLAUDE.md for any project.
Sources: Anthropic's Claude Code skills documentation and the help-center article on using skills in Claude, both read on 2026-10-08. Claude Code ships often, so if a field behaves differently on your version, the docs win over this post.



