SDD × Claude Code:先写清楚,再让 AI 写代码
用 AI 写代码的人,大多走过这样一个循环:一句话丢给 AI,它几秒钟就写出一大堆代码,看着能跑,细看全是坑。让它改,它改好这里又弄坏那里。再改几轮,前面说好的约定它也忘了。最后你开始怀疑:到底是 AI 不行,还是我不会用?
问题往往不在 AI 不够聪明,而在于我们没把需求说清楚。人和人协作,含糊的地方可以靠默契补;AI 没有默契,只能靠猜。猜对了是运气,猜错了就是返工。
今天聊一个专门解决这个问题的方法:SDD(Spec-Driven Development,规格驱动开发) 。前半篇讲清楚理论,后半篇用 Claude Code 带你从零跑通一个真实功能,配置文件都能直接抄。
一、SDD 是什么
一句话:先写规格,再写代码。
“规格”就是一份功能说明书,回答三个问题:要做什么、不做什么、怎样算做完。以前规格是写给人看的,常常写完就压箱底。到了 AI 编程时代,规格多了一个读者,就是 AI。它不嫌文档长,看得认真,也严格照着做。
打个比方:你请装修队装房子,只说“装得好看点”,结果全凭师傅发挥;给一张标好尺寸、材料、插座位置的图纸,结果就可控多了。AI 就是那个手很快的师傅,规格就是图纸。师傅手越快,图纸越重要,因为错的方向上跑得越快,返工越多。
和“凭感觉写”(Vibe Coding)相比,SDD 要多花十几分钟写文档,省下的却是几个小时的反复沟通。更重要的是,每一行代码都有了“为什么这么写”的依据,评审、交接、排查问题都轻松很多。
为什么 AI 时代更需要它
有三个原因:
- AI 的记忆有限。对话一长,早期的约定会被压缩甚至遗忘,写在文件里的规格却随时能重新读取。
- AI 倾向于“补全” 。你没说的地方它不会停下来问,而是按最常见的做法自己填上,往往和你的业务不符。
- AI 的产出量太大。一次生成几百行代码,人很难逐行审,但对照一份清单检查“验收标准是否都满足”就容易得多。
二、SDD 的四个步骤
GitHub 开源的 Spec Kit、亚马逊的 Kiro 等工具都在推这套思路,细节各有不同,主干都可以归纳成四步:
- Specify 写规格:只谈业务,不谈技术。写用户故事、验收标准,并明确“不做什么”。
- Plan 做方案:这时才谈技术。用什么框架、数据怎么存、接口怎么设计、有哪些风险。
- Tasks 拆任务:把方案拆成一个个小任务,每个都能单独完成、单独验证。
- Implement 实现:AI 按任务清单逐项写代码、跑测试、打勾。
为什么要把“业务”和“技术”分成两步?因为两者混在一起时,人很容易被技术细节带跑,忘了最初要解决什么问题。先把“要什么”定死,再讨论“怎么做”,方案选错了也只需要重写 plan,不用推翻需求。
另外两点要记住。第一,每一步都留下一份文档,它既是人和 AI 之间的“合同”,也是下一步的输入。第二,每一步结束都要人工确认。AI 负责干活,人负责拍板,这是 SDD 最核心的分工。
三、为什么用 Claude Code 来做
很多人以为做 SDD 必须装一套专门的框架。其实 Claude Code 自带的五个功能,刚好能一一对应 SDD 的需要:
| SDD 的需要 | Claude Code 功能 | 作用 |
|---|---|---|
| 项目宪法 | CLAUDE.md | 每次会话自动加载,不用重复交代规矩 |
| 先想后做 | Plan Mode | 只读不改,先出方案再动手 |
| 固定流程 | 自定义斜杠命令 | 每一步固化成模板,团队用法一致 |
| 独立评审 | Subagents 子代理 | 独立上下文,适合当“审查员” |
| 自动把关 | Hooks 钩子 | 改完文件自动跑测试,失败即反馈 |
五样东西组合起来,就是一套不依赖第三方框架的轻量 SDD 工作流。下面动手搭一遍。
四、实战:给待办 API 加“标签”功能
假设我们有一个待办清单 API(Node.js + PostgreSQL),现在要加一个功能:给待办打标签,并能按标签筛选。
第 1 步:搭好目录
规格文档放在 specs/ 目录,每个功能一个带编号的文件夹,跟代码一起提交到 Git。半年后有人问“这个功能当初为什么这样设计”,翻文档就知道,不用去考古聊天记录。
第 2 步:写 CLAUDE.md
在项目根目录写上工作约定。不用长,关键是规则明确、可执行:
# 工作约定
- 新功能必须先有 specs/xxx/spec.md
- spec 未经我确认,不写 plan
- 按 tasks.md 顺序实现,完成一项勾选一项
- 需求有歧义时标记 [待确认],不要自己猜
# 技术栈
- Node.js 20 + Express + PostgreSQL
- 测试:Vitest,提交前必须全部通过
“不要自己猜”这一条最管用。加上之后,AI 遇到模糊的地方会主动列问题,而不是悄悄替你做决定。
第 3 步:做三个斜杠命令
在 .claude/commands/spec.md 写入模板,$ARGUMENTS 会被替换成你输入的需求:
根据需求「$ARGUMENTS」,在 specs/ 下新建
编号文件夹,生成 spec.md,包含:
1. 背景与目标
2. 用户故事(作为…我想要…以便…)
3. 验收标准(必须可测试)
4. 不做什么
5. 待确认问题
只写业务,不涉及任何技术实现。
plan.md 和 tasks.md 两个命令同理:前者要求读取 spec.md 后输出技术方案,后者要求把方案拆成带编号、按依赖排序、每项都能单独测试的任务。
第 4 步:跑一遍完整流程
输入 /spec 后,AI 生成的规格大致是这样(节选):
## 验收标准
- 创建待办时可附带 0~5 个标签
- 标签名 1~20 个字符,统一存为小写
- GET /todos?tag=work 只返回带该标签的待办
- 超过 5 个标签时返回 400 和明确提示
## 不做什么
- 不做标签颜色、标签管理页面
- 不做多标签组合筛选(留到下一期)
注意“不做什么”这一节。没有它,AI 很可能顺手给你加上标签颜色、批量编辑,代码量翻倍,测试却没跟上。
整个流程里,你只做了三件事:描述需求、回答 AI 提出的问题、确认方案。最有价值的是那些“待确认”问题,比如“最多几个标签”“是否区分大小写”。这些细节不问,AI 就会默默替你定,等上线后才发现不对。
小技巧:每个阶段结束后输入
/clear清空对话,下一步只让 AI 读文档。如果 AI 读完文档还要追问,说明文档有漏洞,正好补上。
第 5 步:自动验收
最后做两道关卡。第一道是审查子代理,放在 .claude/agents/spec-reviewer.md:
---
name: spec-reviewer
description: 对照 spec.md 审查实现是否完整
tools: Read, Grep, Glob
---
逐条读取 spec.md 的验收标准,检查每一条
是否有对应的实现和测试。输出:已覆盖、
未覆盖、超出范围的改动。只报告,不修改。
它只有只读权限,并且在独立上下文里工作,不会因为“代码是自己写的”而手下留情。
第二道是 Hook,写在 .claude/settings.json,每次 AI 改完文件就自动跑测试:
{
"hooks": {
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "npx vitest run || exit 2"
}]
}]
}
}
这里的 exit 2 是关键:测试失败时,错误信息会直接回传给 AI,让它当场修复,不用你复制粘贴报错。
五、避坑经验
最容易踩的坑是规格写得太虚。“界面友好”“性能好”这种话 AI 没法验证。判断标准很简单:一条验收标准,能不能写成一个测试?能,就是好标准。
第二个坑是改需求只改代码。实现过程中发现规格有问题很正常,但一定要先改 spec.md,再让 AI 按新规格调整。否则文档和代码很快对不上,下次 AI 读到过时的规格,又会把代码改回去。
还要提醒一句:SDD 不是越重越好。改个文案、修个拼写,直接让 AI 改就行。功能越大、协作的人越多、维护时间越长,SDD 的回报越高。
写在最后
AI 让“写代码”变得越来越便宜,但“想清楚要什么”依然昂贵。SDD 做的事情很朴素:把想清楚这一步,从脑子里搬到纸面上。AI 有据可依,人也有据可查。
你不需要一次把整套流程都搭起来。可以先从一个 CLAUDE.md 和一个 /spec 命令开始,下一个小功能先花 10 分钟写 spec.md,再交给 Claude Code。多试几次你会发现,AI 写的东西越来越贴近你想要的结果。