Writing Skills
Writes and revises Agent Skills so they are discovered and followed — frontmatter that validates, descriptions that match real requests, progressive disclosure, and the right degree of freedom. Use when creating a SKILL.md, editing an existing skill, packaging one for distribution, or working out why a skill never triggers.
- Skill name
writing-skills- Category
- meta
- Price
- Free
- Install
~/.claude/skills/writing-skills/SKILL.md- Tags
- skills, authoring, prompting, documentation, meta
Writing Skills
A skill has two jobs, and they fail independently. It has to be found — which is entirely the description's work — and then followed, which is the body's. Most broken skills are well-written bodies attached to a description nothing matches.
The contract
SKILL.md opens with YAML frontmatter. Two fields are required:
---
name: processing-invoices
description: Extracts totals, dates and line items from PDF and scanned invoices, and writes them to CSV. Use when the user mentions invoices, receipts, accounts payable, or bulk data entry from documents.
---
name— 1-64 characters, lowercase letters, digits and hyphens only. No
leading, trailing or doubled hyphens. It must match the directory name.
description— 1-1024 characters. Both required fields reject angle brackets,
because the frontmatter is injected into a system prompt verbatim.
Optional and rarely needed: license, compatibility (up to 500 characters,
only when the skill has real environment requirements), metadata (a flat map
of strings), and allowed-tools (a single space-separated string).
The description is the whole discovery surface
Only name and description are loaded at startup, for every installed skill
at once. Nothing else about the skill is visible until it triggers. So the
description must carry both halves — what it does, and when to reach for it —
in the third person, using the words a person would actually type.
| Instead of | Write |
|---|---|
Helps with documents | Extracts text and tables from PDF files, fills forms, merges documents. Use when working with PDFs or when the user mentions forms or document extraction. |
I can review your code | Reviews changed code for correctness bugs and unclear naming. Use when the user asks for a code review or mentions a pull request. |
Data tool | Cleans messy CSV exports: fixes headers, normalises dates, removes duplicate rows. Use when a spreadsheet or CSV will not parse cleanly. |
Write the description last, then test it: list five ways someone might ask for this help, and check each phrasing against the words actually in the field.
What belongs in the body
The body loads in full every time the skill fires, so its length is a cost paid by every task that touches it. Keep it under 500 lines and roughly 5000 tokens.
Assume a capable reader. Explaining what a PDF is, or how imports work, spends context on something already known. Write the parts that are specific to this job: the conventions, the constraints, the sequence, the thing that goes wrong the first time.
Push detail outward. A skill can bundle as much as it likes, because nothing costs anything until it is read:
processing-invoices/
├── SKILL.md loaded when the skill triggers
├── references/
│ └── field-mapping.md read only when the mapping is needed
└── scripts/
└── extract.py executed; its source never enters context
Two rules make that work. Link every reference directly from SKILL.md — a file reached through another file gets partially read, so a chain quietly loses information. And give any reference over about 100 lines a contents list at the top, so a partial read still shows what is in it.
Degrees of freedom
Match how specific the instructions are to how fragile the task is.
- Open field — many routes reach a good result, and context decides which.
Give direction and stop. "Check for edge cases and unclear naming" beats a twelve-point rubric that will be applied mechanically to code it does not fit.
- Narrow bridge — the operation is destructive, ordered, or easy to get
subtly wrong. Give the exact command and say plainly not to deviate.
Both failures are common, and they look the same from the outside: the skill is ignored. Over-specified instructions get skipped because they do not fit; under- specified ones get improvised around.
Things that reliably work
- One default with an escape hatch, never four alternatives to choose between.
- Concrete input/output pairs. Showing the wanted output teaches more than
describing it.
- Numbered steps for anything sequential, plus a copyable checklist once there
are more than about five.
- A verification loop wherever correctness matters: produce, check, fix, check
again, and an explicit "only continue when it passes".
- One name per thing, used throughout.
- No dated claims. Describe the current method, and put anything superseded
under an "Old patterns" heading.
- Forward slashes in every path.
The authoring loop
- [ ] 1. Do the task once by hand, noting what context you had to supply
- [ ] 2. Write the smallest SKILL.md that captures it
- [ ] 3. Write three test requests, phrased as a user would phrase them
- [ ] 4. Run them in a fresh session with the skill installed
- [ ] 5. Watch where it goes wrong: not triggered, wrong file read, step skipped
- [ ] 6. Fix the specific cause, not the general vibe, and run the three again
Step 5 is the one people skip, and it is the only step that produces evidence. Not triggering is a description problem. Reading the wrong file is a structure problem. Skipping a step is usually a prominence problem — the instruction was present but buried.
The full pre-publication checklist is in references/checklist.md.
Common failures
| Symptom | Cause | Fix |
|---|---|---|
| Never triggers | Description says what, not when | Add the triggering situation and the user's own vocabulary |
| Triggers on the wrong things | Description too broad | Name the boundary explicitly |
| Instructions ignored | Body too long, key rule buried | Cut, then promote the rule to its own section |
| Bundled file never read | Not linked from SKILL.md | Link it directly, and say what it is for |
| Works for you, not for others | Assumed local context | State the assumption or remove the dependency |
Distributing it
The directory is the unit. Zip it with the directory name matching the name
field, and it unzips into ~/.claude/skills/ for personal use or
.claude/skills/ inside a project. Treat a skill from anyone else as you would
any other code you are about to run: read the scripts, and look at what any
external address it contacts is for.