Writing a skill
A procedure the agent loads only when it is relevant — the unit of reusable expertise.
A skill is a teachable capability packaged as a unit: instructions, and often scripts or templates, that stay out of context until a pointer activates them. Harnesses implement this differently — a skills directory, custom commands, prompt files, reusable rules — but the shape is the same: a named procedure, loaded on demand.
When a procedure should be a skill
- It is more than three steps.
- You do it more than occasionally.
- Getting it wrong is annoying to unpick.
- It applies to some sessions, not most — that is the test that separates it from a brief line.
Typical candidates: adding a database migration, creating a new API endpoint end to end, the release checklist, adding a feature flag, onboarding a new integration, upgrading a framework major version.
The shape
# Add a database migration Use when: adding, altering, or removing any column, table, or index. ## Rules - Never edit an applied migration. Always add a new one. - Two-phase for destructive changes: deploy the code that stops using the column, then a later migration drops it. Never in one release. - Every migration needs a tested down-migration. ## Steps 1. npm run db:new <name> # creates a timestamped file 2. Write up and down. Both must be idempotent. 3. npm run db:migrate # apply locally 4. npm run db:rollback && npm run db:migrate # prove down works 5. Update src/db/schema.ts to match. Do not hand-edit generated types. 6. npm run check ## Done when Check passes, rollback was exercised, and the diff contains exactly one new file in db/migrations/ plus the schema.ts update.
Note what makes this work: an explicit use when, imperative steps with real commands, and a definition of done stated as something observable in the diff.
Activate it with a pointer
## Skills Before any schema change, read and follow .agents/skills/add-migration.md. Before cutting a release, read and follow .agents/skills/release.md.
Two lines always loaded; the procedures themselves only when relevant. That is progressive disclosure applied to know-how rather than to documentation.
Write skills from failures
The best source material is a session that went wrong. When you have just spent forty minutes unpicking a botched migration, that is the moment to write the skill — while you can still remember the specific step that was missed.
Watch out
Skills rot faster than briefs because they encode procedures, and procedures change with tooling. Put a command in every skill that would fail visibly if the skill were stale — a script name, a generated path — so drift surfaces as an error rather than as silently wrong work.
Try it
Write one skill for the most error-prone procedure in your project. Then run it: start a fresh session, give it a task that should trigger the skill, and see whether the agent follows it without being told. If not, your pointer is too vague.
Takeaways
- A skill is a named, on-demand procedure — for work that applies to some sessions, not most.
- Give every skill a "use when", real commands, and an observable definition of done.
- Write skills straight after the session that went wrong.
How do you decide between a brief line and a skill?
Frequency of relevance. If it applies to most sessions it belongs in the always-loaded brief; if it applies to a specific kind of task it belongs in a skill with a pointer, so the other sessions do not pay for it.
A course by Pieter Zandbergen