# Writing Skills

> Use when authoring, editing, or reviewing a skill in this library — a new SKILL.md, one that under-triggers, or hardening an existing one. Covers description and listing-budget rules, frontmatter, progressive disclosure, the 3-eval rule, and pressure-testing against rationalizations.

- Skill: `swestash/writing-skills` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add swestash/writing-skills`
- Raw SKILL.md: https://api.skillmd.com/api/skills/swestash/writing-skills/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Finance & Business
- Author: SWEStash (https://skillmd.com/u/swestash)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/swestash/writing-skills

---


# Writing Skills

Author and maintain skills for this library. The canonical rule set lives in
**docs/AUTHORING.md** — read it for descriptions, listing budget, frontmatter,
dynamic context injection, and common mistakes. This skill adds the parts that
must be *applied*, not just read: how to reproduce a skill's failure before
fixing it, how to write a description that actually triggers, and how to
pressure-test.

## ⛔ The Iron Law

**Don't write a skill from imagination — reproduce the failure first, then write the minimum that fixes it.**

Writing a skill is TDD applied to process documentation. If you're fixing a
skill that under-triggers or that an agent rationalizes past, first reproduce
that exact failure (the RED). A skill written to a problem you only *imagined*
tends to over-explain things Claude already knows and miss the real failure mode.

## The authoring loop (RED → GREEN → REFACTOR)

1. **RED — reproduce the failure.** Run the target scenario against a fresh agent
   *without* the skill (or without the new section). Watch what goes wrong and
   capture the *verbatim* excuses it uses ("it's too simple to test", "I'll
   verify after"). See [references/pressure-testing.md](references/pressure-testing.md).
2. **GREEN — write the minimum that addresses those failures.** Don't pad. Match
   the form of the fix to the form of the failure (table below).
3. **REFACTOR — re-test, capture *new* rationalizations, add counters.** Repeat
   until the behavior holds under pressure. Stop when two consecutive runs pass.

**When it doesn't pass, stop by rule, not by patience.** Before each rewrite, name
the cause you believe is responsible and change *only* that. If the number doesn't
move, the hypothesis is dead — do not reword the same section a third time. Either
the assertion is unsatisfiable in this harness (see EVALS.md limitations 3 and 4:
reference-dependent and tool-dependent), or the behavior is a real cost of the
skill and belongs in the test's `expected_behavior` as an accepted trade with its
mechanism recorded. Both endings are results. Endless rewording is how a skill
grows to satisfy an instrument instead of a user.

### Match the form to the failure

| Baseline failure | Right form in the skill |
|---|---|
| Skips or violates a rule under pressure | An Iron Law + a rationalization table + red flags |
| Output has the wrong shape | A positive recipe / template stating what the output *is* |
| Omits a required element | A structural requirement (named field or slot) |
| Behavior should depend on a condition | A conditional rule ("if X, do Y"), not a blanket rule + exceptions |
| Skill defers instead of delivering | The grounding instruction needs a **delivery clause** (below) |
| Behavior is documented but never appears | It is filed where the question doesn't reach — **move it, don't restate it** (below) |
| Behavior appears only as a handoff to another skill | The cross-skill reference is **ceding** it — say what stays in this skill's answer (below) |

### Grounding instructions need a delivery clause

Any instruction of the form *"read/inventory/verify X before you answer"* degrades
into *"ask permission to read X, deliver later"* unless you say otherwise. This is
the most-repeated authoring failure in this library — **eight occurrences across
three cycles**, in `architecture-design`/`data-modeling` (Step 0's first draft),
`project-documentation` (twice), `verification-before-completion`,
`git-workflow`, `tdd-workflow`, `api-design`, and `test-suite-design` — and the
base model, having no such instruction, often scores *better* because it just
answers. The `architecture-design` Step 0 fix shape has now been applied eight
times and has never failed.

It also hides behind other diagnoses. `test-suite-design` looked like a *naming*
problem — an assertion about specification-style test names was failing — but the
judges recorded "no test names appear anywhere": the skill stopped at a behavior
map and an `it.each` table shape, so there was nothing to name. **When an assertion
about the quality of some output fails, first check that the output exists at all.**

Every grounding step must carry three things, and they are cheap:

1. **"This is not a gate on delivering."** Say it in those words.
2. **An exit condition** — the literal one-line sentence that closes the step, so
   the model has something concrete to emit instead of a question.
3. **"…in the same response."** Plus the fallback: when the artifact can't be read,
   state the assumption and deliver anyway. A draft the user corrects beats a
   question they must answer.

`architecture-design` Step 0 is the reference implementation — copy its shape rather
than reinventing it. The tell in an eval is a GREEN reply that contains no artifact:
no message, no document, no recommendation, just a plan to produce one.

**The library's stated position, so this stops being argued case by case: ask
alongside, never instead.** A skill may always ask — questions are often the most
valuable thing it produces — but it must not make the answer conditional on a
reply it cannot get. Deliver under stated assumptions in the same response, and
put the open questions next to the draft rather than in place of it.

Two things follow. **A skill that asks first is not thereby wrong** — the failure
is withholding the artifact, not seeking context, and a skill whose whole job is
opening up a question (`brainstorming`) is behaving correctly when it converges
last. And **an eval score partly measures this posture rather than knowledge**: a
control arm that chooses to ask instead of produce scores as ignorant, so two
cases with the same margin can measure different things. Before reading a margin
as skill quality, check *why* the control failed.

### Before adding content, check whether it is already there

A behavior can be documented and still never appear, because it is filed where the
question never reaches. Adding it a second time makes the skill longer without
making it reachable — **move it, or file it where the prompt lands.**

Three confirmed cases: `accessibility-design` documented submit-time focus in a
general focus table, but the Form Accessibility reference — the material a forms
prompt actually opens — omitted it, so the unaided model produced the behavior and
the skill did not; `test-suite-design` had its `refactoring` handoff buried inside a
step about untestable code, framed as "later", so a "where do I start" question never
hit it; `api-design`'s YAGNI bullet licensed omitting the very pagination its own
step specified. Each was fixed by relocating, not by restating.

The check is cheap: grep the skill directory for the behavior first. If it is there,
the bug is placement. **But confirm before assuming** — this pattern does not explain
every miss. Two of three assertions investigated in one later pass turned out to be
genuine content gaps where the behavior appeared nowhere in the skill at all, and the
material an author would "relocate" did not exist.

### A cross-skill reference can suppress the behavior it delegates

The mirror image of the above. When a handoff covers something **this skill's own
output is judged on**, naming the other skill gives the model permission to hand the
topic over instead of doing it.

Measured: `cicd-pipeline` gained a Step 3 bullet requiring a multi-stage cached
Docker build *and* a `containerization` reference that ceded "the Dockerfile itself
(multi-stage layout…)". Multi-stage went from 0 of 6 generations to 5 of 6 — but
almost never together with caching, because the reply pushed the build out of scope:
*"the pipeline assumes a good one exists."*

The delegation that worked, in `test-suite-design`, has four ingredients:

1. A **dedicated Cross-Skill References entry**, not only a sentence inside a step.
2. The delegation **leads the list** rather than sitting among peers.
3. A bold imperative naming the **trigger condition** ("name this handoff whenever
   the goal of the coverage is a refactor").
4. It says **what to say**, and **cedes nothing** — the skill still does its own work
   and names the successor for what comes after.

So: state explicitly what stays in this skill's answer. A reference that transfers
the topic will transfer the behavior with it.

## Description discipline (the highest-leverage line)

The `description` decides whether the skill ever runs. Agents follow the
description over the body, so get it right.

- **Write WHEN to use, not WHAT it does.** A description that summarizes the
  internal workflow ("reviews code in two passes") triggers worse than one that
  lists situations ("review this PR, check my code before commit").
- **The listing is `description` + `when_to_use`.** The `Triggers:` list *is* the
  when-to-use expressed as the phrases a user actually types — keep casting that
  net wide. **New skills put it in `when_to_use`; existing skills migrate lazily**
  (whenever next touched). A migration must be a **pure move**: triggers go to
  `when_to_use`, the **boundary/delegation instructions STAY in `description`**
  (they're what steers haiku routing — EVALS.md). The catalog builder concatenates
  both fields — check with `node scripts/build-plugins.mjs` + `git diff
  catalog.json` that content is unchanged (a trailing boundary reorders ahead of
  the triggers; that's fine). No re-baseline needed.
- **~350 chars** combined listing target (hard caps: `description` 1024, combined
  1536 — the builder errors above either). Over the listing budget, the
  *least-invoked* skills' descriptions drop silently — `/doctor` reports it. See
  AUTHORING.md "Listing Budget".
- **Anti-pattern:** describing mechanics/steps instead of triggering situations.

## Structure and budget (brief — see AUTHORING.md for detail)

- Frontmatter: `name`, `description`, `when_to_use`, `allowed-tools` — do NOT
  set `model` (inline pins are ignored at runtime; on forked skills they
  override the user's model choice and quota bucket — see AUTHORING.md
  "Frontmatter Fields"). Newer fields where they fit:
  `context: fork` + `agent` (heavy report-producing skills — must write the full
  report to a file and put anything needing user input in an "Open questions"
  section, since a fork returns only a summary and can't ask the user),
  `paths` (file-scoped), `disable-model-invocation` (deliberate-only workflows),
  `effort`. Dynamic injection (bang-prefixed backtick commands, inline or
  fenced): cheap `--stat`-style commands only, `|| true` failure-tolerant — see
  AUTHORING.md's injection rules. Note the syntax executes even inside markdown
  code spans, so never write a runnable example of it in a SKILL.md — describe
  it, or the skill runs the command every time it loads.
- Progressive disclosure: keep SKILL.md tight (aim < 300 lines); push deep
  domain knowledge to `references/`, output formats to `templates/`. On
  compaction only a skill's first ~5k tokens are re-attached — front-load the
  Iron Law and workflow; write standing instructions, not one-time steps.
- Exactly **3 evals** (happy path / edge case / scope boundary) with specific,
  verifiable assertions. For hardened skills, add an optional `pressure` eval
  (see `verification-before-completion` and the safety-critical skills for the
  pattern).
- Register new skills in `skill-router` so they're discoverable.

## When to harden vs. keep open-field

Apply rigor where mistakes are expensive; keep freedom where judgment matters.

- **Harden** (Iron Law + rationalization table + red flags): fragile, safety-
  critical workflows — tests, migrations, deploys, security, incidents.
- **Keep open-field** (explanatory, flexible): creative/advisory work —
  architecture exploration, UX, estimation, proposals. Rigidity there produces
  worse outcomes, not better ones.

## Retiring skills (obsolescence review)

As base models improve, a skill can become pure overhead. Once per release cycle
— or on a major base-model update — re-run the skill's 3 evals RED on shipping
models via `evals/workflow-runner.mjs`; re-sample ×3 on borderline scores and
read the judge journal before calling a result variance (a "flaky" case is often
a real content gap the skill causes). The GREEN arm reads the skill's
`references/` and `templates/`, so reference-heavy skills are judged against
their full depth — the old carve-out for them is retired. If RED ≈ GREEN across
all 3 evals (0/0 assertion pairs needing a real repo, a write, or an executed
command don't count — the harness can't provide those), **slim first** — cut what the model
does unaided; keep the Iron Law, boundaries, and cross-skill references — then
re-run GREEN (gate: GREEN ≥ RED per case). Retire only after a slimmed skill
stays RED ≈ GREEN a full cycle later, with a deprecation notice in
CHANGELOG/ROLES.md first (removal is user-visible to role and plugin consumers).
Full policy: docs/AUTHORING.md § Obsolescence review.

## See also

- docs/AUTHORING.md — the canonical rules and common mistakes.
- [references/pressure-testing.md](references/pressure-testing.md) — running baseline scenarios and the pressure levers.
- `docs/EVALS.md` — the automated RED/GREEN harness that replays evals through subagents and gates regressions in CI.
- `verification-before-completion` — the discipline that proves a skill change works (run the eval, read the result).

