Most skills are written in the first hour of enthusiasm and deleted in the second week. They read like a job description: be thorough, think step by step, act like a senior reviewer. The agent follows them for a day, drifts, and the author concludes that skills do not work.
They work when they describe a procedure that can end. This guide is the authoring routine: start from a task you have done twice, write the trigger first, keep the instruction file short, and test both the trigger and the output. It assumes the packaging described in how to choose an agent skill, and it applies whether you publish the result or keep it in your own repository.
Start with a task you did twice
A skill earns its place when the same job, done by hand, produces the same steps. Pick a task you have completed at least twice and can describe without looking at notes. "Prepare a release note from the commits since the last tag" is a candidate. "Improve the codebase" is not, because there is no point at which the job is done.
Write down the steps you actually took, including the boring ones: which command you ran first, which file you opened to check a name, what you did when a test failed. The boring steps are the skill. The interesting judgment is what you leave to the model, with a rule for when to stop and ask.
The description is the product
The agent decides whether to load your skill by reading its description. If the description says "helps with documents," it will fire on every document task and annoy everyone. If it says "extract line-item totals from supplier invoices and flag missing tax fields," it will fire on invoices and stay quiet elsewhere.
Write the description with both halves: what the skill does, and when to use it. Name the file types, the tools, and the phrases a user might actually say. In the common Claude-style format, name is lowercase letters, numbers, and hyphens, up to 64 characters, and description is capped at 1024 characters and cannot contain XML tags. Those limits are a feature: they force you to choose.
A description is not a summary of the body. It is the matching key. Test it by asking: if I pasted this description into a chat with no other context, would I know when to invoke it and when not to?
Keep the instruction file short
Skills load in stages. The metadata is always in context; the instruction body is read when the skill triggers; bundled files and scripts are read only when the instructions reference them. That means a long body is not free. It occupies context on every triggered request, and it competes with the user's actual task.
A good target is a body you can read in two minutes. If the skill needs a table of API fields, put it in a separate reference file and link to it. If it needs a deterministic transformation, put it in a script and let the script print the result. The script's code never enters context; only its output does. This is the same progressive-disclosure idea the major agent platforms use, and it is the difference between a skill that scales and a skill that bloats.
A structure that works
The exact headings are yours, but the parts are not optional:
- Trigger. One sentence restating when the skill applies, in the user's words.
- Inputs. What must be present before starting, and what to do if it is missing.
- Procedure. Numbered steps in the order you actually run them. Name commands and file paths.
- Output. The artifact and its shape: a diff, a table with named columns, a file at a path.
- Checks. What the agent must verify before declaring success, and how.
- Stop conditions. When to refuse, ask, or hand back. Include at least one.
Here is a compact example. It is a real procedure, not a persona:
---
name: release-note-from-commits
description: Draft a release note from the commits between two git tags. Use when the user asks for release notes, a changelog, or "what changed since vX".
---
# Release note from commits
## When to use
The repository has at least two tags and the user names a range.
## Inputs
- Previous tag and target tag. If either is missing, ask; do not guess.
## Procedure
1. Run `git log --oneline <previous>..<target>`.
2. Group commits into Features, Fixes, and Internal.
3. For each user-visible change, write one sentence in the present tense.
4. Omit merge commits and version bumps unless they change behavior.
## Output
A Markdown section titled `## <target>` with three subsections.
Leave a subsection out when it has no entries.
## Checks
- Every bullet traces to a commit in the range.
- No issue numbers or author names are invented.
- The note contains no commit hashes.
## Stop
If the range contains more than 200 commits, report the count and ask
whether to summarize by directory instead.
Notice what is absent: adjectives about quality, instructions to "think deeply," and any claim that the model should be an expert. The procedure carries the quality.
Put the check in the skill
The most useful line in a skill is the one that tells the agent how to know it is done. "The JSON parses and every required key is present" is checkable. "The answer is high quality" is not. If you can write a script for the check, do that and have the skill run it.
A skill without a check will pass its own work. That is not malice; it is what a model does when the only definition of success is the model's confidence. Give it an external signal: a test, a schema, a diff, a count, a file that must exist.
Test the trigger, not only the output
Two tests matter, and most authors run only the second.
The trigger test. Open a fresh session with the skill installed. Ask for the job in ordinary language, without naming the skill. It should fire. Then ask for three nearby jobs that should not use it. It should stay quiet. If it fires on everything, the description is too broad. If it never fires, the description is too clever or the host is not loading the folder.
The output test. Run the skill on two real inputs, one clean and one broken. The clean one should produce the artifact. The broken one should trigger the stop condition rather than a confident invention. Compare the output to what you would have written by hand; if the difference is cosmetic, the skill is saving you time. If you have to rewrite it, the procedure is missing a step.
Keep both inputs next to the skill in your repository. When you edit the instructions, rerun them. A skill is a small program whose interpreter is stochastic; the only defense against silent regression is a test you can repeat.
Version it like code
Put the skill in version control with a short changelog. Record which host and model version you tested it on, because a prompt that works in one host can fail in another. When you change the description, treat it as a behavior change: the trigger surface moved. When you change the procedure, rerun the two inputs.
Delete skills you no longer use. Every installed skill adds a description to the context and a chance to fire on the wrong task. The directory on this site is full of skills that were fun to install; your own folder should be smaller. If you want a second opinion on someone else's prompt before you adapt it, the audit guide is the checklist, and when not to install is the reason to leave it alone.