分享用 AI 自动化编写技术规范的工作流,显著提升文档质量和编写效率。194k+ 浏览和高社区互动说明实用价值突出。
我在周三之前就用掉了每周 Claude 预算的 64%,为的是构建一个旨在减少 Claude 使用量的工具。这种讽刺程度,值得拥有一份专门的规范。
这个工具叫作 spec-writer:它是一个 Claude Code skill,可以在编写任何一行代码之前,将模糊的功能请求转化为结构化规范、技术方案和任务拆解。
它解决的问题,是大多数认真使用 AI 编程智能体的开发者在第一周内就会遇到的:智能体信心十足地朝错误方向编写代码,而你需要为此付出双重代价——一次是 token,一次是返工。
本教程将向你展示如何安装 spec-writer、如何针对一个真实功能调用它,以及如何解读输出结果,从而发现那些原本会浪费你时间的假设。
直接向智能体发出提示的问题
直接向智能体发出提示的问题
什么是规范驱动开发
什么是规范驱动开发
spec-writer 的工作原理
spec-writer 的工作原理
如何安装 spec-writer
如何安装 spec-writer
如何编写你的第一份规范
如何编写你的第一份规范
如何解读输出
如何解读输出
如何将规范交给你的智能体
如何将规范交给你的智能体
下面是跳过规范时会发生的事情。
你脑中有一个功能:“添加一种让用户导出其数据的方式。”你打开 Claude Code,描述这个功能。智能体生成了代码。代码看起来没问题。你运行它。大体上是对的——但它导出了所有数据,包括已软删除的记录;它没有分页;处理大型账户时会超时;而且导出端点没有任何身份验证检查。
这些内容都没有出现在你的提示中。智能体进行了猜测,而且猜得合情合理——这比明显猜错更糟糕。直到测试时,你才发现这些问题。
这就是针对任何非简单任务直接向智能体发出提示的根本问题:你的提示包含了你意识到的需求,但每项功能背后都隐藏着一些你没有想到要明确说明的需求。智能体则会用各种假设填补这片空白。
大多数时候,这些假设是合理的。有些时候,它们会以一种需要花费数小时才能理清的方式出错。
这种失败模式并不是幻觉,而是智能体提供的帮助恰好达到了提示所允许的程度——只不过这个程度还不够有用。
规范驱动开发直接解决了这个问题。Julián Deangelis 等实践者对此方法进行了广泛论述:书面规范并不是额外的文档负担,而是一种迫使你在智能体替你做决定之前,先自行做出决定的机制。
规范驱动开发是指在编写代码或向智能体发出提示之前,先编写一份结构化规范。该规范定义功能必须实现什么、当前采用了哪些假设,以及实现工作应当拆分成哪些任务。
关键在于理解规范的用途。规范并不是要取代代码,而是要呈现那些原本不可见的决定。无论如何,智能体都会做出这些决定:有规范时,由你先做决定;没有规范时,你会在测试阶段才发现这些决定。
对 SDD 最有力的反驳来自 Gabriella Gonzalez:一份足够详细的规范其实就是代码。她说得没错,有些规范会退化成极其具体的伪代码,具体到几乎等同于实现。
但那是因为规范写在了错误的抽象层级上。目标是明确有哪些决定,而不是预先实现它们。“只有通过身份验证的用户才能触发此次导出”是一项决定。“调用 verifyJWT(token),如果失败则返回 401”则属于实现。规范需要前者,后者交给智能体处理。
SDD 分为三个层级:
Spec-First:在开发每项功能之前编写规范,并将其作为上下文交给智能体。这是入门层级,也是本教程重点介绍的工作流。
Spec-First:在开发每项功能之前编写规范,并将其作为上下文交给智能体。这是入门层级,也是本教程重点介绍的工作流。
Spec-Anchored:规范保存在代码仓库中,与代码一同演进。当需求发生变化时,你更新规范,并再次向智能体发出提示,使其重新对齐。
Spec-Anchored:规范保存在代码仓库中,与代码一同演进。当需求发生变化时,你更新规范,并再次向智能体发出提示,使其重新对齐。
Spec-as-Source:规范是首要产物。代码由规范生成,并被视为可以丢弃的产物。这是最具雄心的层级,也是许多团队正在努力迈向的方向。
Spec-as-Source:规范是首要产物。代码由规范生成,并被视为可以丢弃的产物。这是最具雄心的层级,也是许多团队正在努力迈向的方向。
spec-writer 无需任何繁琐流程,就能让你立即进入 Spec-First 阶段。
spec-writer 是一个 Claude Code skill——它本质上是一个加载到智能体上下文中的 Markdown 文件,会在被调用时改变智能体的响应方式。
该 skill 遵循一条规则:先生成,再以内联方式标记假设。它不会在生成输出之前询问你澄清性问题,而是立即生成完整规范,并使用 [ASSUMPTION: ...] 标签标记在未获得你明确输入的情况下做出的每项决定。然后,由你纠正其中的错误。
这种方式比问答更快,因为它会以一种便于你作出回应的形式呈现所有决定,而不需要你提前预见它们。
输出包含三个固定顺序的部分:
SPEC:定义“做什么”。包括一句话目的、用户故事、需求、边界情况,以及采用 Given/When/Then 格式编写的验收标准。
SPEC:定义“做什么”。包括一句话目的、用户故事、需求、边界情况,以及采用 Given/When/Then 格式编写的验收标准。
PLAN:定义“怎么做”。包括技术栈和架构决策、数据模型变更、API 契约、测试策略以及安全约束。
PLAN:定义“怎么做”。包括技术栈和架构决策、数据模型变更、API 契约、测试策略以及安全约束。
TASKS:任务拆解。包含按顺序排列、彼此独立的任务,每项任务都能在一次智能体会话中完成,并且拥有各自的验收标准。
TASKS:任务拆解。包含按顺序排列、彼此独立的任务,每项任务都能在一次智能体会话中完成,并且拥有各自的验收标准。
在这三个部分之后,该 skill 会生成一份 Assumptions 摘要:收集输出中的每一条 [ASSUMPTION: ...],并按影响程度排序。这正是你在把任何内容交给智能体之前需要审查的部分。
该 skill 与 GitHub Spec Kit 和 OpenSpec 兼容。如果你使用其中任一框架,可以将规范输出保存到 .specify/ 或 openspec/changes/ 目录中,然后从那里继续操作。
spec-writer 使用 Agent Skills 标准,这意味着同一个 SKILL.md 文件可以在 Claude Code、Cursor、GitHub Copilot、Gemini CLI,以及任何其他支持该标准的智能体中使用。只需安装一次,就可以随处使用。
如果 skills 目录不存在,请创建该目录并克隆代码仓库:
mkdir -p ~/.claude/skills
git clone https://github.com/dannwaneri/spec-writer.git ~/.claude/skills/spec-writer
在 Windows PowerShell 中:
(注意:PowerShell 使用反引号(`)续行,而不是反斜杠。)
New-Item -ItemType Directory -Force -Path "$HOME\.claude\skills"
git clone https://github.com/dannwaneri/spec-writer.git "$HOME\.claude\skills\spec-writer"
安装过程到此结束。不需要安装软件包,不需要编辑配置文件,也不需要 API key。这个 skill 就是一个 Markdown 文件,由智能体读取。
打开 Claude Code 并输入:
/spec-writer test
如果该 skill 安装正确,智能体将读取 SKILL.md 并生成规范结构——即使输入内容只是“test”。你会看到三个部分和 Assumptions 摘要。如果没有任何反应,请确认 ~/.claude/skills/spec-writer/SKILL.md 文件是否存在。
调用格式如下:
/spec-writer [your feature description]
功能描述可以像你在 Slack 消息中写的那样粗略。这个 skill 的职责就是将其结构化。你不需要做到精确,因为让内容变得精确正是规范的作用。
下面是 Foundation 项目中的一次真实调用。Foundation 是一个构建在 Cloudflare Workers 之上的联邦式知识库:
/spec-writer Add CLI capture for Claude Code sessions stored in ~/.claude/projects/
只有十二个单词。没有提及技术栈,没有数据模型细节,没有身份验证要求,也没有错误处理规范。所有这些内容都会在规范中呈现出来。
下面是经过缩略的输出:
一句话目的:开发者可以在 Claude Code 会话日志于 30 天后被删除之前,将其从本地文件系统采集到 Foundation 中。
作为一名每天使用 Claude Code 的开发者,我希望自己的编程会话能够被自动采集,这样架构决策和调试模式就不会在 30 天后消失。
作为一名每天使用 Claude Code 的开发者,我希望自己的编程会话能够被自动采集,这样架构决策和调试模式就不会在 30 天后消失。
作为 Foundation 用户,我希望 CLI 会话和浏览器扩展捕获的内容位于同一个知识库中,以便可以在一个地方查询我的所有 AI 交互。
作为 Foundation 用户,我希望 CLI 会话和浏览器扩展捕获的内容位于同一个知识库中,以便可以在一个地方查询我的所有 AI 交互。
假设一名开发者的 Claude Code 会话位于 ~/.claude/projects/
当他们运行 Foundation CLI capture 命令时
那么系统会显示尚未捕获的会话列表,并按时间从新到旧排序
假设某个会话已存在于 Foundation 中
当开发者再次运行 capture 时
那么该会话不会出现在待检查列表中
假设存在一个格式错误的 .jsonl 文件
当 capture 命令处理该文件时
那么系统会记录该文件的错误,并继续处理其余会话
技术栈和架构:
CLI capture 在本地运行——它需要读取本地文件系统,而
Cloudflare Workers 无法做到这一点。[假设:CLI capture 是一个本地 Node.js
或 Bun 脚本,它通过调用 Foundation API 插入会话,而
不是 Worker 本身]
POST /api/sessions/import – 接受解析后的会话 JSON,返回会话 ID
POST /api/sessions/import – 接受解析后的会话 JSON,返回会话 ID
如果会话已存在,则返回 409
如果会话已存在,则返回 409
成功插入后触发评估器流水线
成功插入后触发评估器流水线
## 任务 1:.jsonl 解析器
**要构建的内容:** 一个解析器,用于读取 Claude Code 的 .jsonl 会话文件,
并输出 Foundation 的内部消息格式。
**可能受影响的文件:** cli/src/parsers/claudeCode.js(新建)
**验收标准:**
1. 将有效的 .jsonl 文件解析为正确的消息格式
2. 处理格式错误的行时不会崩溃——记录日志并跳过
3. 对空文件返回空数组
**依赖项:** 无
需要审查的假设:
1. CLI capture 是调用 Foundation API 的本地脚本,而不是 Worker
影响:高
如有以下需求,请修正此项:你希望采用纯 Serverless 方案
2. 捕获前需要手动筛选,而不是自动批量导入
影响:高
如有以下需求,请修正此项:你希望在后台自动捕获
3. 使用 .jsonl 文件名中的会话 ID 作为去重键
影响:中
如有以下情况,请修正此项:你的 schema 以其他方式存储会话 ID
4. v1 不进行敏感数据清理
影响:中
如有以下情况,请修正此项:你的会话中包含凭证或密钥
仅仅输入十二个单词,就立即暴露出了四项决策——其中三项会对架构产生实质影响。
第三项假设(“使用 .jsonl 文件名中的会话 ID 作为去重键”)最有可能引发难以察觉的 bug。AI 智能体会基于文件名实现去重,而且它会一直正常工作,直到某个会话文件被重命名。规格说明在编写任何代码之前就发现了这个问题。
这份输出的设计阅读顺序是:先快速查找 [ASSUMPTION: ...] 标签,再阅读任务。
每个 [ASSUMPTION: ...] 标签都标记了一个 AI 智能体自行补充了你未明确说明的信息的位置。你的工作是逐项查看“假设”摘要,并针对每一项作出决定:
正确:假设无误,保持不变
正确:假设无误,保持不变
覆盖:假设错误,重新说明需求并再次生成规格说明
覆盖:假设错误,重新说明需求并再次生成规格说明
推迟:该假设对本次迭代无关紧要,标记后继续
推迟:该假设对本次迭代无关紧要,标记后继续
影响评级可以告诉你,在开始编码之前需要修正哪些假设。高影响假设会影响架构或数据模型。如果它们有误,修正时就需要返工。低影响假设只影响行为细节,以后很容易修改。
以 Given/When/Then 格式编写的验收标准,是规格说明中最有助于发现范围错误的部分。阅读每一条并问自己:这真的是我想要的吗?
验收标准被刻意设计为二元判断。“未认证时返回 401”是一条验收标准。“正常工作”则不是。如果你读到某项标准时心想“嗯,这得视情况而定”,那就说明该标准隐藏了一项假设。请重新明确说明它。
任务已经排好顺序,并且彼此独立。每项任务都会产生一项可验证的变更。在把任何任务交给 AI 智能体之前,请检查两件事:
任务是否包含所需的全部上下文?如果某项任务写着“遵循现有的认证模式”,但你没有向 AI 智能体指出认证代码的位置,它就会自行猜测。
任务是否包含所需的全部上下文?如果某项任务写着“遵循现有的认证模式”,但你没有向 AI 智能体指出认证代码的位置,它就会自行猜测。
验收标准是否与你实际会执行的测试相符?如果标准含糊不清,请在 AI 智能体看到任务之前将其细化。
验收标准是否与你实际会执行的测试相符?如果标准含糊不清,请在 AI 智能体看到任务之前将其细化。
规格说明是上下文,而不是提示词。当你为某项任务启动 AI 智能体会话时,应将规格说明中的相关部分与任务描述一并提供。
对于上面示例中的任务 1,你的 AI 智能体会话可以这样开始:
上下文:
- 这是一个基于 Cloudflare Workers、D1 和 Vectorize 构建的联邦式知识库
- 会话以 .jsonl 文件形式存储在 ~/.claude/projects/
- API 运行在 https://<your-worker>.workers.dev
规格说明:
[粘贴 SPEC 和 PLAN 部分]
任务:
[粘贴任务 1]
这个上下文块只是一个示例。请将其替换为你自己项目的技术栈、文件位置和 API URL。重点是向 AI 智能体提供新团队成员入职第一天所需的同等上下文。
现在,AI 智能体拥有了需求、架构上下文,以及一项范围明确且具备二元验收标准的任务。它无法错误猜测去重键,因为规格说明已经解决了这个假设。它也无法跳过错误处理,因为验收标准明确要求这样做。
这就是这份规格说明所服务的工作流。规格说明不会取代 AI 智能体。相反,它会在工作开始之前,把决策权从 AI 智能体手中收回并交还给你。
如果你想转向“规格锚定开发”(即规格说明保存在代码仓库中),请将输出保存到项目的 specs/ 目录:
# 创建 specs 目录
mkdir -p specs
# 保存你的规格说明
# 将输出粘贴到 specs/cli-capture.md
当需求发生变化时,更新规格说明,并重新提示 AI 智能体,使实现与其重新对齐。规格说明将成为事实来源,而不是代码注释。
在编写任何代码之前,先在你的下一个功能上试用它。它标记出的假设会揭示一些你尚未有意识作出决定的功能细节——而在把任何内容交给 AI 智能体之前,先修正其中影响为“高”的假设,正是整个流程的意义所在。跳过这一步,就等同于直接向 AI 智能体输入提示词。
如果你的项目正在扩大,请逐步转向规格锚定开发。将规格说明保存在代码仓库的 specs/ 目录下。当新贡献者加入项目,或者 AI 智能体在没有上下文的情况下启动新会话时,规格说明可以直接向他们提供已经作出的决策,而无须他们通过逆向分析代码来推断。
这一工作流面临的最有力且持续存在的质疑,来自 Gabriella Gonzalez 的观点:详细的规格说明最终会变成代码。如果你的规格说明开始涉及具体实现,就说明你已经越界了。应退回到决策层面——例如“只有已认证用户才能触发此操作”——并将实现留给 AI 智能体。规格说明的职责,是明确指出 AI 智能体可能猜错的内容,而不是用散文来编写功能。
Agent Skills 标准目前已适用于 Claude Code、GitHub Copilot、Cursor 和 Gemini CLI。spec-writer 代码仓库位于 github.com/dannwaneri/spec-writer。
花费 64% 的 Claude 预算来构建一个提高 token 效率的工具,这种讽刺确实存在。但面对一个只有十二个单词的提示词,规格说明就揭示出了四项决策。第四项——关于去重键的假设——原本会产生一个始终表现完美的 bug,直到某个会话被重命名。
这不是幻觉。这只是 AI 智能体在提示词所允许的范围内,尽其所能地提供帮助。
规格说明正是你用来提高“有帮助”这一概念上限的方式。