
How to Create a Claude Skill: Write SKILL.md in 10 Minutes
We test Claude skills for a living, hundreds of them so far, and the pattern is depressing: most skills that fail our review didn’t fail because the author couldn’t write instructions. They failed because the skill never loaded, or loaded when it shouldn’t have, or was three skills wearing a trenchcoat. All fixable at authoring time, none fixable after the fact by writing a nicer README.
This is the tutorial we wish every submitter had read first. By the end you’ll have a working skill: a code review checklist that pushes Claude past “looks good, maybe rename this variable” into checking boundary conditions, error paths, and dead code. It’s a real example on purpose. The best community skill in our coding category, Code Review Checklist, does exactly this and scores 8/10 on output. Yours won’t beat it on day one, but you’ll understand every decision that skill’s author made.
The 10-minute promise is honest with one asterisk. Writing the first working version takes about 10 minutes. Testing it properly takes another 30. Skip the second part and you’ll join the half of published skills that don’t survive contact with a fresh session. We wrote up the autopsy in why half of Claude skills don’t work, and we’d rather not add yours to the dataset.
If you’ve never installed a skill and don’t know what one is, read what Claude skills are and how to install them first. This post assumes you’ve used at least one.
Step 1: scope it to one job
Before you write a line, decide what your skill does. Then cut that in half.
The single biggest failure we see in testing is skills that try to do everything. “Helps with code quality” sounds like a reasonable scope. It isn’t. A skill like that wants to trigger on reviews, refactors, test writing, linting questions, and architecture debates, which in practice means Claude can’t tell when to load it, so it loads unpredictably or not at all. Trigger problems are the number one reason a skill scores low in our methodology, ahead of bad instructions and broken installs. Not because triggering is the hardest part of skill authoring, but because scope creep upstream makes it unsolvable downstream.
One skill, one job. Here’s the test: can you finish the sentence “use this skill when the user asks to ___” with a single concrete verb phrase? “Review a pull request or diff” passes. “Improve their code” fails. If your sentence has “and” or “or” joining unrelated activities, you’re writing two skills. Write two skills. Folders are free.
For our example, the scope is: review a diff or PR for correctness bugs, using a fixed checklist, suppressing style nitpicks. Not “help with reviews.” Not “review and fix.” Review, report, stop.
Step 2: the SKILL.md template
A skill is a folder with one required file. Ours goes in ~/.claude/skills/ for personal use, or .claude/skills/ inside a repo if the whole team should get it:
review-checklist/
SKILL.md ← required, and often all you need
reference/ ← optional, loaded only when Claude decides to read it
templates/ ← optional, files your instructions point to
Here’s the full SKILL.md we’ll build, annotated. Copy it, then read the annotations, because two of these lines matter far more than the rest:
---
# 'name' is an identifier: lowercase, hyphens, no spaces.
# Claude sees it, but it does NOT drive triggering.
name: review-checklist
# 'description' is the ONLY thing Claude reads when deciding
# whether to load this skill. Everything below the frontmatter
# is invisible until after that decision. Write it like a
# trigger condition, not marketing copy.
description: Use when the user asks to review code, review a
PR, review a diff, or check a branch before merging. Runs a
correctness-focused review checklist. Do NOT use for writing
new code, fixing bugs the user already identified, or
general refactoring requests.
---
# Code review checklist
When reviewing a diff or PR, work through this checklist in
order. Report only findings; do not fix anything unless asked.
## Procedure
1. Read the full diff before commenting on any line.
2. For each changed function, check:
- Off-by-one risks at loop bounds and slice indices
- Null/undefined paths: what happens when inputs are empty?
- Error handling: are failures swallowed or logged and re-raised?
3. Check for dead code the change creates: unused imports,
unreachable branches, orphaned helpers.
4. Check concurrency only if the diff touches shared state.
5. Verify new logic has test coverage. Missing tests are a
finding, not a blocker.
## Reporting rules
- Max 10 findings, ordered by severity. If you found 30,
report the 10 worst.
- Every finding needs a file, a line reference, and a one-line
fix suggestion.
- Do NOT report: naming preferences, formatting, comment
style, or anything a linter would catch.
- If the diff is clean, say so in one sentence. Do not invent
findings to seem thorough.
That’s the whole skill. No build step, no manifest, no registration. Restart your Claude session and it’s live.
The frontmatter has exactly two fields that matter. name is bookkeeping. description decides everything, and here’s why: Claude keeps only the name and description of every installed skill in context. The body of your SKILL.md doesn’t exist as far as the model is concerned until it reads your description, decides “this matches what the user wants,” and loads the rest. A brilliant 200-line checklist behind a vague description is a brilliant 200-line checklist nobody will ever execute. In our scoring rubric, triggering is weighted as heavily as output quality for exactly this reason. A skill that fires 40% of the time is a coin flip with extra steps.
Step 3: write the trigger description
Since the description is a trigger condition, write it like one. Name the phrasings a real user would type. Include the negative space, meaning the nearby requests where the skill should stay quiet.
Side by side, from real submissions we’ve tested (lightly anonymized):
Bad:
description: A powerful skill that helps improve code quality
and catch issues early in the development process.
Good:
description: Use when the user asks to review code, review a
PR, review a diff, or check a branch before merging. Do NOT
use for writing new code or fixing already-identified bugs.
The bad one describes the benefit. The good one describes the moment. Claude isn’t reading your description to be persuaded; it’s pattern-matching against the user’s actual words. “Review this PR” shares zero vocabulary with “helps improve code quality,” so the skill sleeps through its own use case. We tested a submission almost identical to that bad example: it fired on 1 of 8 review-shaped prompts. After rewriting the description to name phrasings, same body, it fired on 8 of 8.
Another pair, this one about the negative space:
Bad:
description: Use for anything related to testing.
Good:
description: Use when the user asks to write tests for
existing code or asks what to test. Do NOT use when the
user is doing TDD (writing tests before implementation) or
debugging a failing test.
“Anything related to testing” is how you end up hijacking a debugging session. Over-triggering is quieter than under-triggering and just as damaging: the user gets checklist-flavored answers to questions that needed something else, blames the model, uninstalls the skill.
Mechanical rules that hold up across everything we’ve tested: name three to five concrete user phrasings, include at least one “do NOT use” clause, stay under roughly 500 characters, and never use the words “powerful,” “comprehensive,” or “helps with.” Those words correlate with failing trigger scores in our data so consistently that we now flinch on sight.
Step 4: write a body Claude actually follows
Once the skill loads, the body is the instruction set. The failure mode here is subtler than triggering but just as common: instructions that inspire instead of constrain. “Write a thorough, thoughtful review” is a motivational poster. Claude already wants to be thorough and thoughtful; that’s the default behavior you’re trying to shape, not the shape.
The skills that top our rankings are lists of constraints. Test-Driven Development forbids implementation before a failing test exists, full stop. Our example skill caps findings at 10 and bans style nitpicks outright. Notice how many of its lines start with “do not.” That’s deliberate. Models over-generate by default, so the highest-value instructions are usually subtractive.
Rules of thumb for the body:
- Numbered procedures beat prose. “Work through this in order” gives Claude a spine; paragraphs give it vibes.
- State the stopping condition. Our skill says report findings, don’t fix. Without that line, Claude will helpfully start rewriting the code, which nobody asked for.
- Legislate the output format. Max counts, required fields, what a clean result looks like. “If the diff is clean, say so” prevents invented findings, a failure we catch constantly in review-type skills.
- Put rarely needed detail in
reference/files. If your skill has a 300-line style guide that applies once a month, don’t paste it in SKILL.md where it burns context on every activation. Save it asreference/style-guide.mdand write “when the user asks about X, read reference/style-guide.md first.” Claude loads it on demand.
When do you add scripts and templates? Only when instructions can’t do the job. A skill that generates a specific config file should ship a templates/config.yaml and say “copy this, then modify.” A skill that needs deterministic behavior, say parsing a lockfile format, should ship a script and instruct Claude to run it rather than reimplement it from memory each time. But most skills need neither. Our example needs neither. Every file in the folder is something you now maintain, so earn each one.
FREE STARTER PACK
The fastest way to internalize these rules is reading skills that already pass them. We'll email you our 3 top-scored skills plus the install checklist we test with. Free.
Get the free starter packStep 5: test it locally
You are not done when it works once. “It worked when I tried it” is the testing standard of every broken skill we’ve ever failed. Here’s the minimum battery, and it maps closely to what our methodology runs on submissions:
- Fresh session. Restart Claude Code entirely. Skills load at session start; testing in the session where you wrote it proves nothing.
- Trigger test, positive. Try three different phrasings a real user would type: “review this PR,” “can you check this diff before I merge,” “look over my changes.” All three should activate the skill. You can tell it fired because the output follows your rules (a capped, severity-ordered finding list looks nothing like a default review). If you’re unsure, ask Claude directly whether it used the skill.
- Trigger test, negative. Try three adjacent requests that should NOT fire it: “fix this bug,” “write a function that parses dates,” “why is this test failing?” If your review checklist shows up in a debugging session, your description needs a “do NOT use” clause.
- Baseline comparison. Run the same review prompt in a session with the skill and one without. If you can’t tell the outputs apart, the skill isn’t earning its context and you should sharpen the constraints. This is our favorite test because it’s brutal. About a third of the skills we review fail it.
- Clean-install test. If you plan to publish: copy the folder to another machine (or delete and re-clone), follow your own README verbatim, and see if it works. Missing dependency notes die here.
Whole battery takes 30 minutes. It filters out roughly 80% of the failures we see, which is a strong return on half an hour.
Step 6: run it through the validator
Before you publish, paste your SKILL.md into our free skill validator. It scores against the same rubric we use in reviews: description length and specificity, presence of concrete trigger phrasings, negative-space clauses, constraint density in the body, format legislation, obvious anti-patterns like “powerful” and “anything related to.”
It’s static analysis, so treat it accordingly. It catches the mistakes that are visible in the text, which in our experience is most of them, but it can’t run your skill against live prompts. A validator pass plus the Step 5 battery is the real bar. A validator pass alone is a linted skill that might still not fire.
If you’d rather have interactive help than a checker, Anthropic’s Skill Creator is the tool we recommend. It scored 9.6 in our testing, scaffolds the folder, and its description-optimization step measurably improved triggering on our own internal skills. Using a skill to write skills sounds like a joke and works anyway.
Step 7: publish and submit
Publishing is a normal GitHub repo. Layout convention:
your-repo/
README.md ← what it does, install command, one example
review-checklist/
SKILL.md
reference/
Put the install command in the README as a copy-paste block, the standard pattern being git clone plus cp -r review-checklist ~/.claude/skills/. Then add the claude-skills topic tag to the repo. This isn’t decoration: the topic tag is how our crawler and every other directory discover new skills. An untagged skill repo is invisible in practice.
A README worth writing has four things: one sentence on what the skill does, the install block, one before/after example, and any dependencies. The before/after example does more for adoption than everything else combined, because it’s the only part that shows rather than claims.
Then submit it to SkillProof. Testing and listing are free. We run the submission through the same process as everything else in the catalog: fresh install from your README, trigger battery, baseline comparison, output scoring. If it passes, it gets listed with a score, and you can embed a “SkillProof tested” badge in your README. For an unknown author with a two-day-old repo, an independent test verdict is the difference between “random SKILL.md from the internet” and something a stranger will actually install. If it doesn’t pass, you get the failure notes, fix it, and resubmit. Plenty of listed skills went through two rounds.
Common mistakes we see in submissions
After a few hundred reviews, the same five keep showing up.
Vague descriptions. Still first place by a wide margin. If your description could describe three other skills, it describes none of them.
The kitchen-sink skill. One SKILL.md handling reviews, commits, refactors, and documentation. Every job dilutes the trigger for the others. Split it.
Restating model defaults. A body that says “be clear, be accurate, think step by step” adds nothing. Claude does that anyway. If deleting a line wouldn’t change the output, delete the line.
No negative constraints. Skills that only say what to do, never what to stop doing. The “do NOT” lines are where most of the behavior change lives.
Untested install instructions. The README says copy one folder; the skill silently depends on a second skill or a Python package. Dies on our clean-install step every time, and it’s the most avoidable failure on this list.
SKILLPROOF PACK
Every skill in the Writer Pack passed the review these mistakes fail. If you want worked examples of trigger descriptions and constraint-heavy bodies before you publish, study how the pros structured theirs.
Study the Writer Pack — $10FAQ
Do I need to know how to code to create a Claude skill? No. A SKILL.md is markdown with a YAML header. If your skill ships helper scripts you’ll need to write those, but instruction-only skills, which is most of them, are plain writing. The skill in this post contains zero code.
How long should a SKILL.md be?
As short as it can be while still constraining behavior, typically 30 to 150 lines. Under about 20 lines it usually isn’t adding anything beyond defaults; past a few hundred you should be moving detail into reference/ files. Length is a cost you pay per activation, not a quality signal.
Why isn’t my skill triggering? The description, almost always. Check that it names phrasings a user would actually type rather than describing benefits, and confirm you restarted the session after installing, since skills load at session start. If it triggers on some phrasings and not others, add the missing ones to the description explicitly.
What’s the difference between a skill and an MCP server? A skill is instructions: markdown that shapes how Claude behaves, no code running anywhere. An MCP server is a program that gives Claude new capabilities, like querying your database. If your idea is “Claude should approach X differently,” it’s a skill. If it’s “Claude needs access to Y,” it’s MCP. Longer version in Claude skills vs MCP.
Can I charge for a Claude skill? There’s no built-in payment mechanism; skills are files, and the public ecosystem runs on open repos. Some authors sell private skill packs to teams as consulting deliverables, which works because the value is the encoded expertise, not the file. Anything meant for the public catalog should be openly licensed, since nobody installs a skill they can’t read.
Scope one job, write the trigger like a regex in prose, constrain instead of inspire, and test in a fresh session before you tell anyone. That’s the whole craft. The rest is iteration, and the submission queue is open.
For more, see the full frontmatter field reference.
★ 9.6/10 × 3
The free starter pack
3 skills with our highest test scores plus the install checklist — the setup we'd put on a fresh machine. Free, by email.