Spec-Driven Dev
Coding Agents·Module 1 · The Brief·L2·50 minBrief

Skills: Packaging Repeatable Work

Turn a procedure you keep re-explaining into a skill the agent loads on demand, give it arguments and supporting files, hand isolated jobs to a subagent, and write a task brief that starts each piece of work.

Before this: L1 CLAUDE.md: the standing brief

What you'll learn
  • Explain the difference between the standing brief (always loaded) and a skill (loaded when invoked or relevant).
  • Write a SKILL.md with a name, a description that says when to use it, and a procedure with numbered steps.
  • Decide whether something belongs in CLAUDE.md, a skill, or a subagent.
  • Write a task brief for one change request: goal, definition of done, constraints, and what not to touch.
  • Invoke a skill with arguments and know what the agent sees.

Why this matters

Every Friday Omar asks Quill to write the release notes for Shelf. Every Friday he types the same explanation: group the merged pull requests under Features, Fixes, and Internal, one line each, no PR numbers in the headings, do not commit. Every Friday it comes out a little different. One week the headings have numbers. One week Quill commits the file. One week Omar forgets to say "since the previous tag" and gets the whole history. Jun watches this for a month, then moves the explanation into .claude/skills/release-notes/SKILL.md. The next Friday Omar types /release-notes v2.4 and reads the result. Same format every time, and the explanation lives in a file that Jun can review like any other code.

1. Standing brief vs skill

In L1 you wrote the standing brief, the CLAUDE.md that Quill reads at the start of every session. It holds what is true all the time: how to run the tests, where the tests live, which folders need a person's approval. A skill is different. A skill is a procedure, a set of numbered steps for one kind of job, stored in its own file and loaded only when that job comes up.

The two differ in one way that matters: when they are read. The standing brief is read every session, whether or not it is relevant. A skill is read when you invoke it, or when the agent decides its description matches the task.

Why does the release-notes procedure not belong in CLAUDE.md? Because the procedure is 20 lines that matter on Friday and never on Monday. Put it in the brief and every session on CR-110, CR-111, and CR-112 pays to carry it.

2. Anatomy of a skill

Quill runs on Claude Code, so a skill uses the Claude Code shape: a folder under .claude/skills/ named after the skill, holding a SKILL.md. The file starts with frontmatter, a small block of YAML between two --- lines, with two fields. The name is what you type after a slash to invoke it. The description says what the skill does and when to use it. After the frontmatter comes the procedure.

Here is the whole release-notes skill, the one Jun wrote.

---
name: release-notes
description: Write the release notes for a tag from the merged PRs since the previous tag. Use when asked for release notes or a changelog.
---

1. Run `git log <previous-tag>..$ARGUMENTS --merges --oneline`.
2. Group the PRs under Features, Fixes, Internal.
3. Fill `template.md` in this folder; one line per PR, no PR numbers in the headings.
4. Print the result; do not commit.

The description does two jobs. For a person browsing the folder, it says what the skill is. For the agent, it is the matching rule. When Omar types "can you put together a changelog for the new tag?" without invoking anything, Quill compares the request against every skill's description, sees "changelog," and loads this one on its own.

3. Writing the procedure

A procedure is the body of the skill. It has four parts: numbered steps, exact commands, the output format, and a done check. Numbered steps, so you can refer to "step 3" when something goes wrong. Exact commands, because "run the tests" becomes npm test in one session and make test in another, and only one of those runs the lint. The output format, because "write it up" produces a different write-up every time. A done check, so the agent knows when it has finished.

Here is a second Shelf skill, new-endpoint, which scaffolds a route, its test, and a line of docs.

---
name: new-endpoint
description: Scaffold a new HTTP route in Shelf with its test and a docs line. Use when asked to add an endpoint, route, or API path.
---

Arguments: the route path, for example `/inventory/low-stock`.

1. Create `src/<area>/<name>.ts` exporting a handler. Pick `<area>` from the first path segment.
2. Create `tests/<area>/<name>.test.ts` with one Vitest case that calls the handler and asserts the status code. Run `make test` and confirm the new test fails before step 3.
3. Implement the handler so the test passes. Run `make test` again.
4. Add one line to `docs/api.md`: method, path, one-sentence purpose.
5. Done when `make test` is green, the docs line exists, and no file outside `src/<area>/`, `tests/<area>/`, and `docs/api.md` changed. Print `git status --short` as proof.

Step 2 makes the agent see the test fail before the code exists. That is the same discipline the Spec-Driven Development for Dummies course teaches for specs, applied inside a skill. Step 5 is the done check, and it ends with evidence, not a claim.

4. Arguments

Most procedures need one piece of input: a tag, a route, a ticket number. Arguments are the text you type after the skill name. Omar types /release-notes v2.4, and inside the skill body every $ARGUMENTS is replaced by v2.4 before the agent reads it. This is the Claude Code shape; other agents have equivalents.

Look back at step 1 of release-notes: git log <previous-tag>..$ARGUMENTS --merges --oneline. When Omar invokes it with v2.4, Quill sees git log <previous-tag>..v2.4 --merges --oneline, works out that the previous tag is v2.3 from git tag, and runs the command. The tag is the one thing that changes week to week, so it is the one thing that comes from outside the file.

5. Supporting files

A skill folder can hold more than SKILL.md. A template, a checklist, or an example output can sit next to it, and the procedure refers to the file by name. This keeps the procedure short and keeps the shape of the output in one place that a person can edit without touching the steps.

Step 3 of release-notes says "Fill template.md in this folder." Here is that file.

# Shelf $ARGUMENTS

## Features
- 

## Fixes
- 

## Internal
- 

Released <date>. Full log: `git log <previous-tag>..$ARGUMENTS`.

When Nadia asks for a "Known issues" heading, Jun adds it to template.md. The procedure does not change. When Omar wants the date in a different format, he edits one line in one file.

6. Subagents for isolated jobs

Some jobs should not run inside your main session at all. A long exploration of the codebase fills the context window with files that the main task does not need. A review against a fixed checklist works best when the reviewer has not seen the conversation that produced the code. For these, Claude Code offers a subagent: a separate agent with its own instructions and its own tools, defined in .claude/agents/<name>.md, that runs with a fresh context and reports back to the main session.

The file has frontmatter with name, description, and tools, then the instructions.

---
name: test-reviewer
description: Reviews a diff and checks that every changed function has a meaningful test. Use after a feature is implemented, before opening the PR.
tools: Read, Grep, Glob, Bash
---

You review diffs for test coverage. For every changed exported function, find its test. Report: function, test file, whether the test would fail if the function's body were replaced with `return undefined`. Do not edit files.

Two things to notice. The tools line leaves out Edit and Write, so this subagent cannot change a file. And the instruction asks a sharp question: would the test fail if the function did nothing? That catches a test that asserts nothing, which the main session, having written both, is unlikely to notice.

When does a subagent fit? A skill is steps the main session follows with everything it already knows. A subagent is a job that benefits from knowing nothing: a fresh look, a bounded tool set, and a report instead of a diff.

7. The task brief

Everything so far lives in a file. The task brief does not. A task brief is the message that starts one piece of work: the goal, the definition of done, the constraints, what not to touch, and how the agent should verify. It is written once per task and thrown away when the task ends. The standing brief says what is always true; the skill says how to do a recurring job; the task brief says what to do today.

Here is the CR-110 task brief, eight lines.

Goal: show a "low stock" badge on the inventory list when a title has fewer than 5 copies.
Done: the badge renders for a title with 4 copies and not for one with 5; a Vitest test proves both.
Constraint: read the threshold from src/inventory/config.ts; do not hard-code 5.
Constraint: stock is counted per store, not across stores.
Do not touch: src/orders/, src/giftcards/, migrations/.
Do not touch: any existing test.
Verify: make test green; paste the output.
Then stop. Do not open a PR.

Compare it with "add a low stock badge." That version leaves Quill to decide the threshold, whether stock is per store, and whether to open a PR. Each decision is a chance to be wrong, and L0 showed what a literal agent does with a missing sentence. The eight-line version closes every gap that matters and says where the edges are.

8. Which layer

You now have four places to put a piece of knowledge: the standing brief, a skill, a subagent, and the task brief. The question for each candidate line is when it is needed.

Needed whenLayerExample from Shelf
Every sessionCLAUDE.md (standing brief)"Run make test, not npm test." Stock is counted per store.
On demand, same steps each timeSkill in .claude/skills/<name>/SKILL.mdrelease-notes, new-endpoint
Fresh context and a fixed jobSubagent in .claude/agents/<name>.mdtest-reviewer
This task onlyTask brief (a message)"Read the threshold from config.ts." Do not open a PR.

Two tests resolve most cases. Would this line be wasted on an unrelated task? Then it is not brief material. Could a stranger do this job from a written description, and would a fresh view help? Then it is a subagent. Steps for a recurring job are a skill, and anything left is the task brief.

Summary

  • The standing brief is loaded every session; a skill is loaded only when invoked or when its description matches the task, so recurring procedures belong in skills, not in CLAUDE.md.
  • A skill is .claude/skills/<name>/SKILL.md: frontmatter with name and a description that says what it does and when to use it, then a procedure of numbered steps, exact commands, an output format, and a done check.
  • $ARGUMENTS carries the one thing that changes per run, such as /release-notes v2.4; supporting files such as template.md hold shapes so the steps stay short.
  • A subagent in .claude/agents/<name>.md runs a fixed job with a fresh context and a bounded tool set, and reports back; use it for review and exploration, not for building.
  • A task brief is the message that starts one piece of work: goal, definition of done, constraints, do-not-touch, and how to verify. Pick the layer by asking when the knowledge is needed.

Key terms in this lesson

Check your understanding

Pick an answer to see why it is right or wrong. These are graded in code, instantly.

1.When does Quill read a skill stored in .claude/skills/release-notes/SKILL.md?
2.What is the description field in a SKILL.md's frontmatter for?
3.Omar types /release-notes v2.4. Where does v2.4 appear, and what does Quill see?
4.Which job is the best fit for a subagent in .claude/agents/ rather than a skill?
5."Do not open a PR for this one; I want to see the diff first." Which layer does this line belong in?
6.Why did Jun add a fifth step to the new-endpoint skill that says "no file outside src/<area>/, tests/<area>/, and docs/api.md changed; print git status --short as proof"?

Apply it

Write your answer in your own words. Eve grades it against a rubric and gives you feedback, the same way an LLM judge works in Lesson 5.

Short answerGraded by Eve · 5 criteriaup to ~150 words

Pick one thing you re-explain to a tool or a colleague every week. Write the skill's name and its description line, in the SKILL.md frontmatter shape.

0 words
Free responseGraded by Eve · 6 criteria

Write the task brief for CR-112, the nightly job that emails each store manager a sales summary. Include the goal, the definition of done, three constraints, a do-not-touch list, and how Quill should verify.

0 words
Instructor notes(for whoever is teaching this lesson)

Talking points

  • Open with the Friday release notes. Ask who re-explains the same procedure every week. That is the skill they will write.
  • The distinction that carries the lesson: the brief is read every session, a skill is read when invoked or matched. Load cost decides the layer.
  • The description is a search key, not a comment. The "Use when" sentence should hold the words a person actually types.
  • A procedure instructs; it does not describe. "Make sure it is well tested" is a wish, not a step.
  • The done check ends with evidence, not a claim. git status --short is the habit the review lessons build on.
  • A subagent is for a job a stranger could do well: fresh context, bounded tools, a report back. It is not a way to build faster.
  • The task brief is the only layer that is not a file: goal, done, constraints, do-not-touch, verify.

Live demo idea

Start with a repository that has a CLAUDE.md and no skills. Ask for release notes in plain words and watch the format wander. Create .claude/skills/release-notes/SKILL.md and template.md live, following the lesson's file exactly, and run /release-notes v2.4. Show the substituted step 1. Then ask for a changelog without the slash command and show the agent picking the skill from its description. Finish with .claude/agents/test-reviewer.md on a diff with a weak test; point at the tools line that keeps it read-only.

Common misconceptions

  • "A skill is a shorter CLAUDE.md." The brief is always loaded; a skill is loaded on demand. A procedure in the brief costs context on every unrelated task.
  • "The description is documentation." It is the matching rule. A vague description means the skill is only ever reached by the slash command.
  • "Subagents make the work faster." A subagent starts from zero and cannot see the conversation. It suits review and exploration, not implementation.
  • "The task brief goes in a file." It is the message that starts the work. What proves always true migrates to CLAUDE.md later.
  • "$ARGUMENTS is filled in by the agent." It is replaced by the text typed after the skill name, before the agent reads the body. An empty argument is a case the procedure must handle.

Timing

Fifty minutes: story and section 1, six; anatomy and the description, seven; the procedure, seven; arguments, four; supporting files, four; subagents, eight; the task brief, eight; the decision table, six.

If you only have 20 minutes

Write release-notes/SKILL.md live and invoke it with a tag (eight minutes). Compare the CR-110 task brief with "add a low stock badge" and ask which decisions the short version leaves open (seven minutes). Close on the decision table and the question "when is this needed?" (five minutes). Assign sections 5 and 6 as reading.