The to-spec Skill: What It Writes and When to Skip It
/to-spec is a skill in Matt Pocock's open-source skills collection for Claude Code, Codex, Copilot and other coding agents. You run it at the end of a planning conversation. It takes the decisions you already made, writes them into a spec with a fixed template, checks the test seams with you, and files the result as one issue in your tracker. It records decisions; it does not make them. This page covers what it writes, where it sits in the workflow, the gotchas its own documentation lists, and the one section we add before an agent builds from its output: numbered acceptance criteria.
This page is an independent explainer. Spec Coding is not affiliated with Matt Pocock or AI Hero. Facts were checked against mattpocock/skills v1.3.2.
What /to-spec does
The skill's description is short: "Turn the current conversation into a spec and publish it to the project issue tracker: no interview, just synthesis of what you've already discussed." Its SKILL.md breaks that into three steps:
- Read the codebase. The agent explores the repository if it has not already, uses the vocabulary from the project's domain glossary, and respects any ADRs in the area being changed.
- Sketch the test seams and check them with you. This is the only point where it asks you anything. More on seams below.
- Write and publish. It fills a seven-heading template and files the spec in your issue tracker with the
ready-for-agenttriage label.
The frontmatter sets disable-model-invocation: true, which in Claude Code means the model cannot load the skill on its own. It runs only when you type /to-spec. That fits the design: the project splits its skills into user-invoked ones that orchestrate a workflow and model-invoked ones that hold reusable discipline, and to-spec is one of the orchestrators.
If you knew it as /to-prd, it is the same skill. It was renamed in v1.1, when the project settled on "spec" and "tickets" as its two terms, and the old slug no longer works.
Installing it and the one-time setup
For Claude Code the README gives a plugin install that updates itself:
claude plugin install mattpocock-skills@claude-plugins-official
For other agents (Cursor, OpenCode, Windsurf and others) it uses the skills.sh installer, which copies editable files into your project that you update by hand:
npx skills@latest add mattpocock/skills -a <agent>
Pick one method per agent. Installing both gives you every skill twice. Then run /setup-matt-pocock-skills once per repository. It asks which issue tracker you use (GitHub, GitLab, local files, or something you describe), which labels you apply during triage, and where generated docs should live. /to-spec depends on this: without a configured tracker it tells you to run the setup first. The local option writes markdown files under .scratch/ and needs nothing else.
The template, section by section
The spec always has the same headings. The rules attached to each are where most of the skill's judgment lives:
| Section | What goes in | Rule worth knowing |
|---|---|---|
| Problem Statement | The problem, from the user's point of view | No solution language yet |
| Solution | The fix, also from the user's point of view | Behaviour, not modules |
| User Stories | A numbered list: "As an <actor>, I want a <feature>, so that <benefit>" | The template asks for a list that is "extremely extensive" and covers every aspect of the feature |
| Implementation Decisions | Modules built or changed, their interfaces, schema changes, API contracts, architectural decisions | No file paths or code snippets, because they go stale. The exception is a snippet from a prototype that states a decision more precisely than prose: a state machine, a schema, a type shape |
| Testing Decisions | What makes a good test, which modules get tests, prior art in the codebase | Test external behaviour, not implementation details |
| Out of Scope | What this spec deliberately leaves out | The docs call the refused items "usually the most useful lines on the page" |
| Further Notes | Anything else |
The "no file paths" rule is the one most teams would not think to write down. A spec that names src/billing/coupon.ts is wrong the day someone moves the file; a spec that says "coupon validation lives in the pricing module" survives the move.
Seams before prose
Before writing a single section, the skill sketches the seams where the feature will be tested and asks you to confirm them. The rules are strict: prefer seams that already exist, pick the highest one available, and keep the count low. In the SKILL.md's words, "the ideal number is one."
The seams matter later in the chain. The project's tdd skill only works at seams agreed in advance, and its code-review skill reviews the diff against the spec, so a seam nobody agreed to turns up as a review finding. That makes the seam check the part of /to-spec worth slowing down for. It is the same question this site asks in every spec packet: where will the evidence that this works come from?
When the spec earns its step
The docs are unusually direct about when not to use the skill. The trigger is a single condition: the build is too big for one agent session and has to be split across several.
| Where you are | What to run |
|---|---|
| Nothing is decided yet | grill-with-docs first |
| Decided, and the work fits one context window | implement, and skip the spec |
| Decided, and the work spans several sessions | /to-spec, then /to-tickets |
A wayfinder map has cleared | /to-spec #<map_issue> |
The full chain on the multi-session path is grill-with-docs → to-spec → to-tickets → implement → code-review → retro. The reasoning is that tickets are disposable and the spec is not. Each ticket from /to-tickets is a tracer bullet sized for one fresh context window, and it gets closed when done. The spec is the one place that keeps the reasoning behind all of them. On a single-session change there is nothing to keep, and you pay for an extra synthesis step where the model can drift.
Five gotchas from its own docs
The skill's documentation page answers the questions people actually hit. These five are the ones that change how you use it:
- The label invites the wrong agent.
ready-for-agentmeans "no further triage needed", not "build this". Autonomous agents that poll for the label cannot tell the difference and will try to build the whole spec in one run instead of the ticket slices. The docs call this the most-reported problem. Until it changes, exclude the parent spec in your autonomous agent's prompt, or remove the label after/to-ticketshas run. - It is a snapshot. Nothing keeps the spec in sync once implementation starts, and it goes out of date the first time the code teaches you something. Durable knowledge belongs in
GLOSSARY.mdand ADRs, not in an edited spec. - Refactors fit poorly. The template leans on user stories, which do not describe interface or module-boundary work. Use the implementation and testing sections, and record lasting architecture decisions as ADRs.
- It does not check for duplicates. It neither searches the tracker for overlapping issues nor links the ADRs it follows. In a busy area, search the tracker yourself first.
- Large specs can get truncated. A tracker may not return a very long issue in full when
/to-ticketsfetches it. Run both commands in the same window without clearing or compacting in between, so the spec never has to be fetched again.
How it compares with other spec formats
Most comparisons stop at tool names. The more useful difference is where the spec lives and how long it is meant to last:
| /to-spec | Spec Kit | OpenSpec | |
|---|---|---|---|
| Where it lives | One tracker issue (or a local .scratch/ file) | A spec.md per feature in the repository | A change folder: proposal.md, spec deltas, design.md, tasks.md |
| Who makes the decisions | You, before it runs; it only records | Drafted by the agent from your description, then clarified | Drafted by the agent as a proposal you review |
| Behaviour written as | User stories | Prioritised user stories, edge cases, functional requirements, measurable success criteria | Requirements with WHEN/THEN scenarios |
| Testing | Agreed seams and prior art | Success criteria | Scenarios |
| Lifespan | Disposable after the work ships | Stays with the feature | Merged into the source-of-truth specs when archived |
So /to-spec is the lightest of the three and the only one that deliberately lives outside the repository. That suits a team whose long-term knowledge already sits in a glossary and ADRs. If you want the spec itself to be the durable record, Spec Kit or OpenSpec fit better; OpenSpec vs Superpowers vs Spec Kit compares those in depth.
The section we add: numbered acceptance criteria
In the /to-spec template, behaviour is spread across user stories, which state intent ("so that…"), and testing decisions, which state where to test. Neither says what result counts as a pass. An agent picking up a ticket has to infer when it is done, and that inference is where runs drift. In our recorded agent runs, vague prompts mostly worked; the clearest effect of a written spec was that repeated runs stopped disagreeing with each other, down to how they handled a case the spec itself forgot.
The fix is one extra heading between Testing Decisions and Out of Scope:
- Number each criterion:
AC-1,AC-2, and so on, so tickets, tests and reviews can name them. - Make each one observable at an agreed seam: an input, an output or error, and a state you can check.
- Take them only from decisions you made while planning. If a criterion is new to you when you read the spec, the planning was too shallow, which is the same test the skill's docs apply to the whole spec.
How you add it depends on how you installed the skills. The skills.sh install gives you editable copies, so you can add the heading to the template in SKILL.md. The Claude Code plugin updates itself and would overwrite edits, so put the instruction in your project's CLAUDE.md or AGENTS.md instead: "Specs include an Acceptance Criteria section, numbered AC-n, each testable at an agreed seam." The acceptance criteria guide has more examples of the format.
Example: a to-spec spec with acceptance criteria
This is a trimmed illustration we wrote by hand following the template, not output captured from the skill. It uses the coupon feature from our checkout example:
## Problem Statement Customers with a valid coupon cannot apply it at checkout, so support applies discounts by hand after the order. ## Solution Customers enter a code at checkout and see the discounted total before they pay. ## User Stories 1. As a customer, I want to enter a coupon code at checkout, so that I pay the discounted price 2. As a customer, I want a clear message when a code has expired, so that I know why the price did not change 3. As a support agent, I want to see which coupon an order used, so that I can answer refund questions ## Implementation Decisions - Coupon validation lives in the pricing module; checkout calls price(cart, code) and never computes discounts itself - One coupon per order; codes are case-insensitive - The order record stores coupon_code and discount_cents ## Testing Decisions - One seam: price(cart, code) in the pricing module - No UI tests for discount maths; prior art: the tax tests ## Acceptance Criteria (added) - AC-1: a valid code lowers the total by its discount, never below 0 - AC-2: an expired code returns COUPON_EXPIRED; the total is unchanged - AC-3: a second code on the same order returns COUPON_LIMIT - AC-4: a paid order stores coupon_code and discount_cents ## Out of Scope - Stacking coupons, per-customer usage limits, an admin UI for codes ## Further Notes - Marketing creates codes; existing codes are all uppercase
Two details are worth noticing. Every criterion is checkable at the single seam named under Testing Decisions, and the Out of Scope line names three things someone will ask for during review. When /to-tickets later slices this spec, each ticket can list the criteria it closes, and code-review has a pass/fail list to check the diff against.
FAQ
Does /to-spec work outside Claude Code?
Yes. The same skills install into Codex and Copilot as plugins, into Gemini CLI with gemini skills install, and into Cursor, OpenCode, Windsurf and others through skills.sh. The /to-spec behaviour comes from the same SKILL.md in each case.
Should I use /to-spec or write the spec myself?
If the decisions are already in a long planning conversation, /to-spec saves you transcribing them, and the seam check is worth having either way. If you plan in a document rather than a chat, you already have the spec. Either way, read the seams and the out-of-scope section before an agent builds from it.
How is this different from Claude Code's built-in skills?
It is an ordinary skill: a SKILL.md with frontmatter and instructions, distributed as a plugin. Our Claude Code Skills guide covers the file format, where skills load from, and how to write your own spec-writing skill.
References
- mattpocock/skills on GitHub (README: installation, setup, skill list)
- to-spec SKILL.md
- to-spec documentation (when to use it, common questions)
- to-tickets documentation
- Claude Code docs: Skills
- Spec Kit spec template
- OpenSpec spec-driven templates
Checked on 2026-11-06 against mattpocock/skills v1.3.2 (released 2026-10-29), Spec Kit v1.3.1 and OpenSpec v1.16.0. Quotes are from the linked files.