本文经原作者授权转载,版权归原作者所有。原作者:Xudong Han(@Xudong07452910)。查看原文 →
这一篇我只讲一件事。
Vibe Coding流程里投入产出比最高的一步,从来不是写代码,是先用对话把脑子里那句模糊的「我想让它能XX」逼成一份能直接对照写代码的spec。
spec是指一份把「我要做什么」写得非常清楚、详细、不模糊的文档。
Vibe Coding的「Vibe」是建立在spec上面的。spec越糊,AI跑得越快你死得越惨。
我搭EvoPaw (https://github.com/hxdflying/EvoPaw)这30天回头看,80%的返工源头都在第一句话没说清。花一两个小时把spec逼清楚,能省掉后面两周的乱改。
Vibe Coding跟传统写代码最大的区别,不是「写得快」,而是你不再逐行审代码。你说一句话,五分钟后AI给你交付20个文件500行代码,你扫一眼跑一下「能跑」就过了。模糊需求在这种流程里会被指数级放大,AI自己脑补的假设两周后才暴露,那时候它已经被10个文件、3层抽象绑死,改的成本比重写还高。
之前我在搭建个人agent方法篇里,简要介绍了拆解需求的步骤

文章链接如下:
https://x.com/Xudong07452910/status/2051891753821556976
下面我把这一步拆得很碎,今天看完就能照着跑一遍。结尾还会介绍一个偷懒党的捷径,叫obra/superpowers,让Claude Code或者Codex自动触发整套流程,不用记任何prompt。
接下来我用「让agent每天早上总结我3个工作群的待办」这个真实需求贯穿全文。
1.第一步,先用一张表逼自己说人话
很多人觉得「我脑子里很清楚要什么」,但你真让他写下来,能写出来的不超过两行。
这就是问题。
我自己每次开新需求前,会先花10分钟填这张表,手写或者丢在docs/raw_idea.md里都行。

以「飞书群待办总结」为例,我第一遍填出来是这样的。

这张表本身不重要,重要的是最后一行。
当你诚实地把「不知道的地方」写下来,你就知道下一步该让AI追问你什么了。
如果这一栏是空的,那说明你还没仔细想,回去再填一遍。
我观察过身边十几个朋友走这一步,80%的人会跳过这张表,直接去找Claude Code对话。结果就是对话开始之后,AI问什么他都答「都行」「随便」,整个brainstorm环节空转。
表的作用就是逼你在跟AI说话之前,自己先认真想10分钟。
2.第二步,开Plan mode,让Claude Code反着追问你
填完表,打开Claude Code,按一次Shift+Tab(或者输入/plan),状态栏会切到Plan mode(计划模式)。
这是Claude Code内置的一个模式,它在这个模式下不会写任何代码、不会改任何文件,只跟你聊。
如果你没用过这个模式,看一下底部状态栏写着plan mode on就对了。再按一次Shift+Tab会回到普通模式。
为什么一定要开plan mode?
因为Claude Code默认是「动手型选手」,你跟它说话它就想动手。哪怕你写「先别动手,我们聊聊」,它聊两轮也会忍不住开始建文件。plan mode是硬性约束,它在这个模式下连Write工具都用不了。
进入plan mode后,把你上一步填好的表整段贴进去,然后丢这一段prompt。
我要给我 fork 的 nanobot 加一个新功能,需求表如上。
请你扮演一个挑剔的产品经理,**一次只问我一个问题**,把我没想清楚的地方逐个挖出来。
追问的方向重点覆盖:
- 输入边界(什么算、什么不算)
- 输出格式(具体什么样的卡片、消息、文档)
- 触发条件(定时还是事件、失败怎么办)
- 失败处理(API 超时、空数据、解析失败各种情况)
- 与现有功能的边界(会不会跟已有 skill 打架)
- 性能与成本上限(一次最多处理多少、token 预算)
我每回答一个,你就抛下一个,直到你觉得这个需求边界完全清楚为止。**注意,你只问我,不要自己脑补答案**。最后再把整理结果写到 docs/spec.md。这段prompt里有几个细节是我反复调出来的,分别对应几个常见的坑。

把这段贴进去,回车。
接下来你会经历整个流程里最有价值的5到15分钟。
下面这段是我跑这个需求时的真实对话节选(简化了一部分),你感受一下。
**AI**:先确认范围。你说「3个工作群」,这3个群是固定的(你提前指定群名/群ID),还是动态的(agent 要自己判断哪些是工作群)?
**我**:固定的,我提前给你3个群名。
**AI**:明白。下一个,「@我」这个判定包含哪些情况?(a) 只算文本里有 @张三 的明确 at;(b) 也算「张三麻烦你处理一下」这种半显式提及;(c) 也算「这个需求谁来跟一下」这种潜在的求助。请选。
**我**:(a)+(b),(c) 太宽不要。
**AI**:好。那 (b) 怎么判?你给我几个关键词,还是让模型语义判断?关键词更可控成本低,语义更准但每天会多花几毛钱。
**我**:先关键词,给我列一份你建议的清单,我加减。
**AI**:建议清单(中文优先):「麻烦你」「请处理」「你跟一下」「你看下」「帮我」「@你确认」「需要你」「你来」。要不要加?
**我**:加「你这边」,去掉「你来」(太宽了)。
**AI**:收到。**下一个边界**,总结时间窗口怎么算?(a) 自然日,每天9点总结昨天0到24点;(b) 工作日,周一9点总结周五到周日全部;(c) 滚动24小时,每天9点总结过去24小时。
**我**:(b)。
**AI**:那节假日呢?比如清明、国庆。(a) 跟周末一样合并到下一个工作日;(b) 不管节假日按周一到周五正常推;(c) 你手动告诉 agent 今天是假期。
**我**:……这个我没想过。先 (b) 吧,简单。
(后续还有8到10轮,覆盖:消息体太长怎么截断、表情包/图片是否纳入、引用消息怎么算、机器人发的消息要不要排除、推送失败重试几次、模型超时 fallback 到哪个 provider、token 预算、是否生成总结日志)跑完之后,整个需求边界明显从「我每天看下昨天的群」清晰到了一份能拿去写代码的东西。
最有意思的是,整个过程里有30%的问题是我自己根本没意识到的。节假日、引用消息、机器人消息排除、token预算,全是它逼出来的。
这就是为什么这一步比你自己写需求文档值钱。
你自己写文档的时候你是在自我合理化,模型来追问的时候才是真正的对抗性思考。
聊到这个我突然想到苏格拉底那套「产婆术」。苏格拉底从来不直接告诉学生答案,他只问问题。一个问题接一个问题,直到学生自己说出答案。他说他不是在教知识,他只是在帮学生把本来就在他脑子里的东西「生」出来。
跟Claude Code的brainstorm一模一样。你脑子里其实早就有答案了,只是没有一个挑剔的对手把它逼出来而已。
3.第三步,让它把对话沉淀成一份你能审的spec.md
聊完之后,跟它说。
> 好了,把我们刚才聊到的所有结论整理成docs/spec.md,**用下面这个结构**,每一节都要具体到能直接对照写测试,**不要散文,只要列表和表格**。
>
> 1. 一句话目标(≤30字)
> 2. 用户故事(按「作为xxx我想xxx以便xxx」写3条)
> 3. In Scope / Out of Scope(两栏对照)
> 4. 触发与输入(时间、来源、过滤规则)
> 5. 处理流程(按步骤列)
> 6. 输出格式(贴一个真实样例消息)
> 7. 失败处理(每种失败一行,什么情况 → 怎么做)
> 8. 性能预算(每天最多多少消息、token上限、超时阈值)
> 9. 验收标准(5到8条,每条都能跑测试验证)
>
> 写完直接保存到docs/spec.md,不要确认。这里的关键是禁止它写散文。
让AI写文档它默认会输出一堆「该功能旨在……」「为了满足……」的话,看起来很正式,对你写代码毫无帮助。
spec不是给老板看的,是给Claude Code和你自己看的。越像列表、越像表格、越像合同,越好。
输出大概长这样,我贴一份节选版本。
# 飞书群待办总结 - spec
## 1. 一句话目标
每个工作日早上9:00,把指定3个群昨天的待办整理后私聊推给我。
## 2. 用户故事
- 作为EvoPaw用户,我希望9:00之前收到昨日待办,以便上班10分钟内确认工作量
- 作为EvoPaw用户,我希望节假日/周末后自动合并,以便周一不漏事
- 作为EvoPaw用户,我希望待办判定误报率<10%,以便不变成新的噪音
## 3. In Scope / Out of Scope
| In Scope | Out of Scope |
| :--- | :--- |
| 3个指定群的文本消息 | 家庭群、私聊 |
| 文本中的@我和关键词触发 | 图片/语音/视频内容识别 |
| 引用消息(追溯被引用原文) | 表情包独立消息 |
| 工作日推送、节假日合并 | 实时事件推送(独立功能) |
## 4. 触发与输入
- 触发:cron `0 9 * * 1-5`(周一至周五9:00)
- 时间窗口:上次推送时间 → 当前时间(节假日累计)
- 数据源:飞书 Open API `im/v1/messages`
- 过滤:排除 `msg_type=image|sticker|file|audio`,排除bot发的消息
## 5. 处理流程
1. 计算时间窗口(含节假日合并逻辑)
2. 拉取3个群在窗口内全部文本消息
3. 按消息逐条判定是否「待办」(规则见6)
4. 命中消息按群+时间聚合
5. 调用provider生成总结(prompt模板见 `prompts/group_summary.md`)
6. 渲染成飞书富文本卡片
7. 推送到私聊
8. 写入 `logs/daily_summary/YYYY-MM-DD.json`
## 6. 待办判定规则(按OR命中)
- 文本含 `@<my_user_id>`
- 文本含关键词列表(`config/todo_keywords.yaml` 维护):
麻烦你、请处理、你跟一下、你看下、帮我、@你确认、需要你、你这边
- 被引用消息已命中上面任一条 → 当前消息也算
## 7. 输出格式
(贴一个完整的示例飞书卡片JSON,省略)
## 8. 失败处理
| 情况 | 处理 |
| :--- | :--- |
| 飞书API限流(429) | 指数退避,最多重试3次;仍失败则发「今日总结失败,请手动检查」私聊 |
| 模型超时(>30s) | fallback到Kimi;仍超时则跳过摘要,直接列原始命中消息 |
| 群内0条消息 | 该群在输出中跳过,不发占位 |
| 全部3个群都0条 | 推送「昨日群内无动静」 |
## 9. 性能预算
- 每天总输入 ≤ 30万字(约15万token)
- 整个pipeline耗时 ≤ 90秒
- 单日token成本 ≤ ¥0.5
## 10. 验收标准
- [ ] 在2026-05-15 9:00准时收到推送
- [ ] 推送内容只来自3个指定群,无家庭群混入
- [ ] 含至少一个@我命中、一个关键词命中
- [ ] 引用消息能正确追溯到原文
- [ ] 在断网模拟下,pipeline报错信息符合上表
- [ ] logs目录下生成对应日期JSON
- [ ] 周一推送合并周末
- [ ] token成本日志 < ¥0.5你看,到这里整个需求不再有任何「模糊地带」了。
任何一个会写Python的人,哪怕不是你自己,照着这份spec都能开始干活。Claude Code拿着这份spec去拆任务、写代码、配测试,几乎不会再走偏。
4.第四步,让Codex给Claude Code当review(强烈建议加上)
到这里你已经有一份能用的spec了。但如果你有点追求,再花5分钟做一件事,会让spec质量上一个台阶,那就是找一个不同厂商的模型来挑刺。
具体做法在方法篇(https://x.com/Xudong07452910/status/2051891753821556976)里讲过装Codex MCP,这里直接用。prompt输入:
用codex review这份docs/spec.md,重点看,(1)有没有自相矛盾的地方(2)有没有看起来确定但其实没说清的措辞,比如「快速」、「及时」、「差不多」(3)我的失败处理表是不是漏了常见case(4)有哪些隐含假设我没写出来。它的修改建议你逐条评估,你同意的直接改spec.md,不同意的告诉我理由,最后让我拍板。
双模型互审最大的价值不是「更聪明」,而是不同训练分布带来的盲区互补。
我自己跑这一步,Codex经常会戳出Claude没问到的边界。比如「你说待办关键词是中文优先,那如果群里有英文消息呢?」「3个群是按群ID指定还是群名?群名会被人改」。这种问题Claude在自己review自己spec的时候是看不见的。
如果你没装Codex也别强求,跳过这一步不影响主流程。但装了的话,每次都做,几乎稳定能让spec再清晰20%。
5.第五步,把spec拆成prompt_plan和todo
spec清楚了,接下来这一步快得多。直接丢。
读 docs/spec.md,把它拆成 **5 到 10 个**可独立实现、可独立测试的小步骤。要求:
- 每个步骤都能独立跑通和验收(不依赖下一步)
- 每个步骤的输入和输出都是明确的文件或函数签名
- 每一步配一段我能直接复制丢给 Claude Code 的 prompt
- 写到 docs/prompt_plan.md
- 同时把粗粒度 checklist 维护到 docs/todo.md(每步一行)它输出的东西大概是这样。
# prompt_plan.md(节选)
## Step 1: 实现时间窗口计算函数
**目标**:给定当前时间,返回(开始时间,结束时间),含节假日合并。
**文件**:`custom_skills/group_summary/time_window.py`
**接口**:`compute_window(now: datetime, holidays: list[date]) -> tuple[datetime, datetime]`
**测试**:覆盖普通工作日、周一合并、节后第一天合并三种case
**Prompt**:
> 在 custom_skills/group_summary/ 下创建 time_window.py,实现 compute_window 函数(签名见上)。同时在 tests/custom_skills/test_time_window.py 写3个测试。先跑测试看红,再实现,再看绿。
## Step 2: 实现飞书消息拉取
(略)
## Step 3: 实现待办判定规则
(略)todo.md就是它的精简版。
Step 1: 时间窗口计算
Step 2: 飞书消息拉取
Step 3: 待办判定规则
Step 4: 总结生成 + provider fallback
Step 5: 飞书卡片渲染 + 推送
Step 6: cron 触发 + 日志写入
Step 7: 端到端集成测试为什么要拆这么细?
因为vibe coding最容易翻车的另一个点是,你让AI一口气实现一整个功能,它写到一半上下文炸了,或者中间某个假设错了,连带后面全错。
拆小之后,每一步独立验收,错了立刻知道在第几步。
每次开新会话第一句话固定写「读CLAUDE.md和docs/todo.md,告诉我下一步」,5秒进入状态。这一招是我30天里养成的最有用的习惯。
好,5步流程讲完了。下面这一段是我反复掉过的坑,列在这里你可以直接绕开。
(1)忘开Plan mode,AI直接动手
症状是你刚说完「我想加个功能」,AI已经在建文件了。每次开新需求第一件事先按Shift+Tab,养成肌肉记忆。
(2)嫌它问题烦,开始随口答
追问到第8、9个的时候你会很想回复「都行」「随便」「你看着办」。这一刻的偷懒会兑换成后面两周的返工。
规则是,只要它问你一个问题让你犹豫超过5秒,你的真实答案就是「我还没想好」。那就让它继续追问到你想好为止,或者明确告诉它「这一点我暂时不定,记成TBD写进spec」。
(3)spec里出现「快速」、「流畅」、「友好」这种词
这是spec里的甲烷,看着没毒其实致命。「快速」是1秒还是5秒?「流畅」是无延迟还是<100ms?
凡是出现这种词,都改成具体数字。
(4)把「怎么做」塞进spec
spec的本职是描述「做什么」,不是「怎么做」。
看到spec里出现「用Redis缓存」「用vector DB」「用GPT-4」这种实现细节,全删。这些放到docs/architecture.md或者prompt_plan里。spec只描述外部可观测的行为。
(5)一份spec装两个独立需求
有时候你会想「反正都是飞书相关,群总结和待办提醒一起做了吧」。
别。
两个独立可上线的功能就是两份独立的spec,分两轮brainstorm。一份spec装两个需求的结果是任何一个改动都牵动另一个的测试,迭代速度直接腰斩。
(6)spec写完就不更新
spec不是石碑。
功能上线两周你发现「哦原来用户还需要XX」,第一件事是回去改spec.md、commit,然后再让Claude Code基于新的spec改代码。
spec跟代码不一致的那一刻,整套工作流就开始崩了。
6.懒人版本
聊到这儿你可能在想,每加一个新功能都要跑这一整套,是不是太重了?
我懂。
所以这里要介绍一个偷懒党的捷径,叫obra/superpowers(https://github.com/obra/superpowers )。

简单说一句它是什么。
superpowers是给Claude Code、Codex、Cursor、Gemini CLI这些coding agent打的一套「工作流补丁包」,由Jesse Vincent(业内挺资深的一位独立开发者)维护,已经迭代到5.x。
它的核心思路跟我上面讲的这一整套几乎一模一样,先brainstorm把spec逼清楚、再写plan、再分小任务做、强制TDD。但它把整个流程做成了「会自动触发的skill」,你不用记prompt,说话就会触发。
举个最直观的例子。
装了superpowers之后,你跟Claude Code说「我想给nanobot加一个PDF解析能力」。
它不会动手,而是自动进入brainstorming skill,从头到尾跑一遍这套流程,探索项目上下文 → 一次一个问题地追问 → 给你2到3个备选方案 → 分章节展示设计 → 等你逐节approve → 写到docs/superpowers/specs/2026-05-11-pdf-parsing-design.md并commit → 自检spec里有没有placeholder、矛盾、模糊 → 让你最后审一遍 → 然后才允许进入下一步writing-plans。
整个过程跟我上面写的5步流程基本是一一对应的,但你不用打那一长串prompt,它内置了一份checklist硬约束自己照做。
装起来也简单,Claude Code里直接一行。
bash
/plugin install superpowers@claude-plugins-official如果这条没找到,也可以走它自己的marketplace。
bash
/plugin marketplace add obra/superpowers-marketplace
/plugin install superpowers@superpowers-marketplaceCodex CLI、Cursor、Gemini CLI、Copilot CLI都有对应安装命令,README里写得清楚(https://github.com/obra/superpowers#installation )。我自己实测下来Claude Code和Codex的体验最好,其他平台略弱一点。
装完之后几乎不用做什么,你正常使用Claude Code,它就会在合适的时机自动触发对应skill。

如果你想强制触发某个skill,直接说「用brainstorming skill帮我把这个需求逼成spec」,或者更省事,「我想加X功能」,只要触发词命中,它会自己跳进去。
我现在的实际配置是superpowers加我自己写的几条工程偏好。superpowers负责通用工作流,我的CLAUDE.md只保留项目特殊的规则,飞书相关的坑、provider切换偏好、commit前必问这种。两边互补。
效果上,新手装上少踩70%的坑,老手装上省70%的prompt打字时间。性价比很高。
但有一个前提需要说一下。它是一套别人定型的方法论。如果你的口味跟Jesse的工程哲学不太一样(他重TDD、重worktree隔离、重bite-sized task),你会觉得它在某些地方过于教条。
这种时候不是它不好,而是你需要更深入地定制,往superpowers的CLAUDE.md里加你的override规则,或者直接fork出来魔改某个skill。
我自己的建议是,第一周直接装上跟着跑一周,跑顺了再决定要不要自定义。
写到这里整篇文章其实就这一件事,vibe coding的速度优势,必须建立在spec清楚的基础上。spec越糊,AI跑得越快,你死得越惨。
把模糊需求逼成spec,要么自己手动跑5步流程(填表 → plan mode追问 → 写spec → 双模型互审 → 拆prompt_plan),要么装superpowers让它自动跑。两条路都行,但这一步绝对不能跳。
我自己30天的所有迭代回头看,80%的返工源头都在第一句话没说清。把这一步做扎实之后,后面的「写代码」反而成了流程里最轻松的环节。因为难的部分,在你跟AI聊那一两个小时里就已经做完了。
回头看苏格拉底两千多年前那句话,「我唯一知道的就是我什么都不知道」。其实他不是真不知道,他只是知道自己脑子里那些东西在被追问之前还不算「知道」。
vibe coding也一样。你以为你想清楚了,但在被一个挑剔的对手追问之前,你脑子里那东西其实还只是一团雾。
把雾捏成形状的那个过程,才是vibe coding真正的命门。
代码反而是最后一步而已。
---
下一篇预告,个人Agent实战篇02,「写完功能必须配测试,但99%的人写的测试根本守不住底线」。讲怎么让Claude Code或者Codex帮你写真的能拦住bug的测试,不是绿了就走人的那种。
评论区欢迎分享,你最近一次因为spec没写清楚被坑到的经历是什么?我会挑几个典型的在下一篇展开。