to-spec Skill 详解:它写什么,什么时候该跳过
/to-spec 是 Matt Pocock 开源 skills 合集里的一个 skill,支持 Claude Code、Codex、Copilot 等编码 agent。它在一段规划对话的末尾使用:把你已经做出的决定按固定模板写成 spec,先和你确认测试接缝,再以一个 issue 的形式发到任务跟踪系统。它负责记录决定,不负责做决定。本文讲清楚它写什么、在工作流里处于哪一步、它自己的文档里列出的坑,以及我们在把它的产出交给 agent 之前会补上的一节:编号的验收标准。
本文是独立的解读文章,Spec Coding 与 Matt Pocock 及 AI Hero 没有任何关联。内容已对照 mattpocock/skills v1.3.2 核对。
/to-spec 做了什么
它的描述只有一句:把当前对话变成 spec 并发布到项目的任务跟踪系统,不做访谈,只综合已经讨论过的内容。SKILL.md 把这件事拆成三步:
- 读代码库。如果还没读过,agent 会先浏览仓库,沿用项目领域词汇表(glossary)里的用词,并遵守要改动区域内的 ADR。
- 画出测试接缝,并和你确认。这是它唯一会问你的地方,下文细说。
- 写好并发布。按七个小节的模板填写,发到任务跟踪系统,打上
ready-for-agent分诊标签。
它的 frontmatter 设置了 disable-model-invocation: true。在 Claude Code 里,这表示模型不能自己加载这个 skill,只有你输入 /to-spec 才会运行。这和项目的设计一致:skills 分成两类,一类由用户手动调用、负责编排流程,另一类可以由模型自动调用、承载可复用的做法,to-spec 属于前一类。
如果你以前用的是 /to-prd,那就是同一个 skill。它在 1.1 版本改了名,项目从此只用“spec”和“tickets”两个词,旧名称已经不能用了。
安装和一次性配置
Claude Code 用插件安装,会自动更新:
claude plugin install mattpocock-skills@claude-plugins-official
其他 agent(Cursor、OpenCode、Windsurf 等)用 skills.sh 安装,它会把可编辑的文件复制进你的项目,之后需要手动更新:
npx skills@latest add mattpocock/skills -a <agent>
每个 agent 只选一种方式,两种都装会让每个 skill 出现两次。装好后在每个仓库里运行一次 /setup-matt-pocock-skills:它会问你用哪个任务跟踪系统(GitHub、GitLab、本地文件,或你描述的其他系统)、分诊时用哪些标签、生成的文档放在哪里。/to-spec 依赖这一步,没配置跟踪系统时它会提示你先运行配置。选本地文件的话,spec 会写成 .scratch/ 下的 markdown 文件,不需要任何其他配置。
模板逐节看
spec 的小节是固定的,这个 skill 的主要判断力都藏在每一节附带的规则里:
| 小节 | 写什么 | 值得注意的规则 |
|---|---|---|
| Problem Statement(问题) | 从用户视角描述的问题 | 这里还不写方案 |
| Solution(方案) | 同样从用户视角描述的解决方式 | 写行为,不写模块 |
| User Stories(用户故事) | 编号列表,格式为“作为某角色,我想要某功能,以便获得某好处” | 模板要求列表“极其详尽”,覆盖功能的每个方面 |
| Implementation Decisions(实现决定) | 新建或修改的模块、它们的接口、schema 变更、API 契约、架构决定 | 不写文件路径和代码片段,因为它们很快会过时。例外是原型里那种比文字更精确地表达决定的片段:状态机、schema、类型结构 |
| Testing Decisions(测试决定) | 什么算好测试、哪些模块要测、代码库里可以参考的已有测试 | 只测外部行为,不测实现细节 |
| Out of Scope(不在范围内) | 这份 spec 刻意不做的事 | 官方文档说,被拒绝的那些事“通常是整页最有用的几行” |
| Further Notes(补充说明) | 其他内容 |
“不写文件路径”这条规则,大多数团队想不到要写下来。写着 src/billing/coupon.ts 的 spec,在有人挪动文件的那天就错了;写着“优惠券校验放在定价模块里”的 spec,文件挪了也仍然成立。
先定接缝,再写正文
在写任何一节之前,这个 skill 会先画出功能将在哪些“接缝”(seam)上被测试,并请你确认。规则很严格:优先用已有的接缝,选能选到的最高层,数量越少越好。SKILL.md 的原话是:理想数量是一个。
接缝在后续环节里很关键。这个项目的 tdd skill 只在事先约定好的接缝上工作,code-review skill 会对照 spec 审查 diff,所以一个没人同意过的接缝会变成审查意见。这让接缝确认成为 /to-spec 里最值得放慢的一步。它和本站每个 spec packet 都在问的问题是同一个:证明它能用的证据从哪里来?
什么时候值得写 spec
官方文档对“什么时候不该用”说得很直接。触发条件只有一个:工作量大到一个 agent 会话放不下,必须拆到多个会话里做。
| 你所处的阶段 | 该运行什么 |
|---|---|
| 还什么都没决定 | 先运行 grill-with-docs |
| 已经决定,且一个上下文窗口装得下 | 直接 implement,跳过 spec |
| 已经决定,且需要跨多个会话 | 先 /to-spec,再 /to-tickets |
一张 wayfinder 地图已经理清 | /to-spec #<map_issue> |
多会话路径上的完整链条是 grill-with-docs → to-spec → to-tickets → implement → code-review → retro。背后的逻辑是:tickets 用完即弃,spec 不是。/to-tickets 拆出的每个 ticket 都是一颗“曳光弹”,大小正好能在一个全新的上下文窗口里完成,做完就关掉;spec 则是唯一保存所有 ticket 背后理由的地方。单会话的改动没有什么需要保存,多出来的这一步综合反而给了模型偏离的机会。
官方文档里的五个坑
这个 skill 的文档页回答了大家真正会遇到的问题,下面五条会直接改变你的用法:
- 标签会招来不该来的 agent。
ready-for-agent的意思是“无需再分诊”,不是“请来实现它”。轮询这个标签的自主 agent 分不清两者,会试图一次性实现整份 spec,而不是按 ticket 分片做。文档说这是被反馈最多的问题。在它修改之前,要么在自主 agent 的提示词里明确排除这份父 spec,要么在/to-tickets运行后去掉这个标签。 - 它只是一张快照。实现开始后没有任何机制让 spec 保持同步,代码第一次教会你新东西时它就过时了。需要长期保留的知识应该写进
GLOSSARY.md和 ADR,而不是去改 spec。 - 重构类工作不太合适。模板高度依赖用户故事,而用户故事描述不了接口或模块边界的工作。这时用实现决定和测试决定两节,把长期有效的架构决定记成 ADR。
- 它不查重。它不会先在跟踪系统里搜索重复的 issue,也不会链接它遵守的 ADR。改动区域很热闹时,先自己搜一遍。
- 长 spec 可能被截断。
/to-tickets去读取时,跟踪系统不一定会完整返回很长的 issue。把两个命令放在同一个窗口里连续运行,中间不要清空或压缩上下文,这样就不用再去读取 spec。
和其他 spec 格式的对比
大多数对比停在工具名字上。更有用的区别是 spec 放在哪里、打算保留多久:
| /to-spec | Spec Kit | OpenSpec | |
|---|---|---|---|
| 放在哪里 | 一个跟踪系统 issue(或本地 .scratch/ 文件) | 仓库里每个功能一份 spec.md | 一个变更目录:proposal.md、spec delta、design.md、tasks.md |
| 谁做决定 | 你,在运行之前;它只负责记录 | agent 根据你的描述起草,再澄清 | agent 起草成提案,由你审阅 |
| 行为的写法 | 用户故事 | 带优先级的用户故事、边界情况、功能需求、可量化的成功标准 | 带 WHEN/THEN 场景的需求 |
| 测试 | 约定的接缝和已有测试 | 成功标准 | 场景 |
| 保留多久 | 上线后即可丢弃 | 随功能长期保留 | 归档时合并进作为事实来源的 specs |
所以 /to-spec 是三者里最轻的,也是唯一刻意放在仓库之外的。它适合长期知识已经沉淀在词汇表和 ADR 里的团队。如果你希望 spec 本身就是长期记录,Spec Kit 或 OpenSpec 更合适,OpenSpec vs Superpowers vs Spec Kit 对它们做了详细对比。
我们会补上的一节:编号的验收标准
在 /to-spec 的模板里,行为分散在用户故事(说明意图,“以便……”)和测试决定(说明在哪里测)两处,但都没有说明什么结果算通过。接手某个 ticket 的 agent 只能自己推断什么时候算做完,而运行结果正是在这种推断里出现偏差的。在我们记录的 agent 运行里,模糊的提示词大多也能跑通;书面 spec 最明显的作用,是让多次运行不再互相矛盾,连 spec 自己漏掉的那个情况都处理得一致。
办法是在测试决定和不在范围内之间加一个小节:
- 给每条标准编号:
AC-1、AC-2……这样 ticket、测试和审查都能引用它。 - 每一条都要能在约定的接缝上观察到:一个输入、一个输出或错误、一个可检查的状态。
- 只从规划时做出的决定里提炼。如果读 spec 时发现某条标准对你来说是新的,说明规划不够深入,这和官方文档检验整份 spec 的标准一样。
怎么加取决于安装方式。skills.sh 安装的是可编辑的副本,可以直接在 SKILL.md 的模板里加这一节。Claude Code 插件会自动更新,改动会被覆盖,所以要把要求写进项目的 CLAUDE.md 或 AGENTS.md:“spec 需包含 Acceptance Criteria 一节,按 AC-n 编号,每条都能在约定的接缝上测试。”更多写法示例见验收标准指南。
示例:带验收标准的 to-spec spec
下面是我们按模板手写并删减过的示意,不是这个 skill 的实际输出。用的是结账优惠券示例里的功能(spec 正文保留英文,方便直接复制给 agent):
## 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
有两点值得注意。每条验收标准都能在测试决定里写的那一个接缝上检查;不在范围内那一行,列出了审查时一定会有人问起的三件事。之后 /to-tickets 拆分这份 spec 时,每个 ticket 都能写明自己完成哪几条标准,code-review 也有了一份可以逐条对照 diff 的通过/不通过清单。
常见问题
/to-spec 能在 Claude Code 以外用吗?
可以。同一套 skills 能以插件形式装进 Codex 和 Copilot,用 gemini skills install 装进 Gemini CLI,也能通过 skills.sh 装进 Cursor、OpenCode、Windsurf 等。各个平台上 /to-spec 的行为都来自同一份 SKILL.md。
用 /to-spec 还是自己写 spec?
如果决定已经散落在一段很长的规划对话里,/to-spec 能省去你手动整理的功夫,而且接缝确认这一步本身就很有价值。如果你习惯在文档里而不是聊天里做规划,那份文档已经是 spec 了。无论哪种,在 agent 动手之前,都要读一遍接缝和不在范围内两部分。
它和 Claude Code 内置的 skills 有什么不同?
它就是一个普通的 skill:一份带 frontmatter 和说明的 SKILL.md,以插件形式分发。我们的 Claude Code Skills 指南介绍了文件格式、skill 从哪里加载,以及怎么写自己的 spec skill。
参考资料
- GitHub 上的 mattpocock/skills(README:安装、配置、skill 列表)
- to-spec 的 SKILL.md
- to-spec 文档(适用场景、常见问题)
- to-tickets 文档
- Claude Code 文档:Skills
- Spec Kit 的 spec 模板
- OpenSpec 的 spec-driven 模板
已于 2026-11-06 对照 mattpocock/skills v1.3.2(2026-10-29 发布)、Spec Kit v1.3.1 和 OpenSpec v1.16.0 核对。引文出自上述链接中的文件。