注意我使用的语言:“深入地(deeply)”、“非常详细地(in great details)”、“复杂细节(intricacies)”、“梳理所有细节(go through everything)”。这不只是废话。如果没有这些词,Claude 就会走马观花。它会读一个文件,在函数签名层面看一眼功能,然后就跳过了。你需要发出信号:表面层的阅读是不可接受的。
书面产物(research.md)至关重要。这不仅仅是让 Claude 做功课,它是我的评审界面。我可以阅读它,验证 Claude 是否真的理解了系统,并在任何规划开始前纠正误解。如果调研错了,计划就会错,实施也会跟着错。垃圾进,垃圾出(Garbage in, garbage out)。
这是 AI 辅助编程中最昂贵的失败模式,而且这通常不是因为语法错误或逻辑不通,而是因为实现方案在孤立环境下可行,却破坏了周围的系统。比如:一个忽略了现有缓存层的函数;一个不符合 ORM 约定的迁移脚本;或者一个重复了现有逻辑的 API 端点。调研阶段可以防止这一切发生。
我坚持使用自己的 .md 计划文件,而不是 Claude Code 内置的计划模式。内置的计划模式很鸡肋。我的 Markdown 文件让我拥有完全的控制权:我可以在编辑器里编辑它,添加行内注释,而且它作为项目中的真实产物是可以持久保存的。
我经常使用的一个技巧是:对于一些封装良好的功能,如果我在某个开源仓库里见过优秀的实现,我会把那段代码作为参考资料和计划请求一起发给它。例如,如果我想添加可排序的 ID,我会粘贴一个做得很好的项目的 ID 生成代码,并说:“这是他们实现可排序 ID 的方式,写一份 plan.md 说明我们如何借鉴类似的方法。” 当 Claude 有具体的参考实现而不是从零开始设计时,它的表现会戏剧性地变好。
但计划文档本身并不是最有趣的部分,有趣的是接下来发生的事。
标注循环(The Annotation Cycle)
这是我工作流中最独特的部分,也是我贡献价值最多的环节。
流程图:
Claude 编写 plan.md
我在编辑器中审阅
我添加行内注释
将 Claude 发回文档
Claude 更新计划
是否满意?(不满意回到第 2 步,满意则进入下一步)
请求待办事项清单(Todo list)
Claude 写完计划后,我会在编辑器中打开它,直接在文档中添加行内注释。这些注释用于纠正假设、拒绝某种方案、添加约束条件,或者提供 Claude 所不具备的领域知识。
注释的长度差异很大。有时只是两个单词:在 Claude 标记为可选的参数旁边写上“不是可选”;有时则是一个段落,解释业务约束或粘贴一段我期望的数据结构代码片段。
第一阶段:调研 每一个有意义的任务都始于一个“深度阅读”指令。
原文地址
我如何使用 Claude Code
我已经将 Claude Code 作为我的主要开发工具使用了大约 9 个月。我摸索出的这套工作流与大多数人使用 AI 编程工具的方式截然不同。
大多数开发者只是输入一个提示词(Prompt),有时会用一下“计划模式”(plan mode),修复错误,然后不断重复。更有甚者,整天在网上折腾什么 Ralph Loops、MCPs(模型上下文协议)、Gas Towns 之类的。在这些情况下,结果往往一团糟,一旦面对非琐碎的任务就会完全崩盘。
我要介绍的这套工作流核心原则只有一个:在审阅并批准一份书面计划之前,绝不让 Claude 编写任何代码。
这种将“规划”与“执行”分离的做法,是我所做的最重要的事情。它能防止浪费精力,让我始终掌控架构决策,并且相比直接跳到编码阶段,它能以最少的 Token 消耗产生显著更好的结果。
第一阶段:调研
每一个有意义的任务都始于一个“深度阅读”指令。在进行任何操作之前,我要求 Claude 彻底理解代码库的相关部分。而且我始终要求将研究结果写入一个持久的 Markdown 文件,而不仅仅是聊天记录里的口头总结。
注意我使用的语言:“深入地(deeply)”、“非常详细地(in great details)”、“复杂细节(intricacies)”、“梳理所有细节(go through everything)”。这不只是废话。如果没有这些词,Claude 就会走马观花。它会读一个文件,在函数签名层面看一眼功能,然后就跳过了。你需要发出信号:表面层的阅读是不可接受的。
书面产物(
research.md)至关重要。这不仅仅是让 Claude 做功课,它是我的评审界面。我可以阅读它,验证 Claude 是否真的理解了系统,并在任何规划开始前纠正误解。如果调研错了,计划就会错,实施也会跟着错。垃圾进,垃圾出(Garbage in, garbage out)。这是 AI 辅助编程中最昂贵的失败模式,而且这通常不是因为语法错误或逻辑不通,而是因为实现方案在孤立环境下可行,却破坏了周围的系统。比如:一个忽略了现有缓存层的函数;一个不符合 ORM 约定的迁移脚本;或者一个重复了现有逻辑的 API 端点。调研阶段可以防止这一切发生。
第二阶段:规划
一旦我审阅完调研报告,我会要求在另一个单独的 Markdown 文件中制定详细的实施计划。
生成的计划通常包含:对方法的详细解释、显示实际更改的代码片段、将被修改的文件路径,以及相关考量和权衡。
我坚持使用自己的
.md计划文件,而不是 Claude Code 内置的计划模式。内置的计划模式很鸡肋。我的 Markdown 文件让我拥有完全的控制权:我可以在编辑器里编辑它,添加行内注释,而且它作为项目中的真实产物是可以持久保存的。我经常使用的一个技巧是:对于一些封装良好的功能,如果我在某个开源仓库里见过优秀的实现,我会把那段代码作为参考资料和计划请求一起发给它。例如,如果我想添加可排序的 ID,我会粘贴一个做得很好的项目的 ID 生成代码,并说:“这是他们实现可排序 ID 的方式,写一份
plan.md说明我们如何借鉴类似的方法。” 当 Claude 有具体的参考实现而不是从零开始设计时,它的表现会戏剧性地变好。但计划文档本身并不是最有趣的部分,有趣的是接下来发生的事。
标注循环(The Annotation Cycle)
这是我工作流中最独特的部分,也是我贡献价值最多的环节。
Claude 写完计划后,我会在编辑器中打开它,直接在文档中添加行内注释。这些注释用于纠正假设、拒绝某种方案、添加约束条件,或者提供 Claude 所不具备的领域知识。
注释的长度差异很大。有时只是两个单词:在 Claude 标记为可选的参数旁边写上“不是可选”;有时则是一个段落,解释业务约束或粘贴一段我期望的数据结构代码片段。
我添加的一些真实注释示例:
drizzle:generate生成迁移,不要用原始 SQL。” ——(Claude 不知道的领域知识)PATCH,而不是PUT。” ——(纠正错误假设)然后我把 Claude 发回文档:
这个循环会重复 1 到 6 次。明确的 “先不要实施” 禁令至关重要。如果没有它,Claude 一旦觉得计划足够好,就会立刻跳到代码环节。但在我说好之前,它都不够好。
为什么这行之有效
Markdown 文件充当了我和 Claude 之间的共享可变状态。我可以按自己的节奏思考,精确地标注错误的地方,并在不丢失上下文的情况下重新介入。我不需要在聊天信息里解释一切,我直接指着文档中具体的位置,把修正写在那里。
这与通过聊天信息引导实施有着本质区别。计划是一个结构化的、完整的规范,我可以进行全局审查。而聊天对话则需要翻阅历史记录来重组决策。计划文档在任何时候都更胜一筹。
三轮“我加了注释,更新计划”的操作,可以将一个平庸的实施方案转化为一个完美契合现有系统的方案。Claude 非常擅长理解代码、提议方案和编写实现,但它不了解我的产品优先级、用户的痛点,或者我愿意在工程上做出的权衡。标注循环就是我注入这些判断力的方式。
待办事项清单(The Todo List)
在开始实施之前,我总是要求一个细粒度的任务拆解:
这会创建一个检查清单,在实施过程中作为进度追踪器。Claude 会随做随记,将已完成的项打勾,这样我随时看一眼计划就能知道进度。在持续数小时的会话中,这非常有用。
第三阶段:实施
当计划就绪后,我会发布实施命令。我将其精炼成了一个在不同会话中重复使用的标准 Prompt:
这一个 Prompt 包含了所有核心要点:
在几乎每一个实施会话中,我都使用这段话(稍作改动)。到我说出“全部实施”时,所有的决策都已经做完并验证过了。实施过程变成了机械性的,而不是创造性的。 这是故意的。我希望实施阶段是枯燥的。创造性的工作发生在标注循环中。一旦计划正确,执行就应该是水到渠成的。
如果没有规划阶段,通常会发生的情况是:Claude 在早期做出了一个合理但错误的假设,并在此基础上构建了 15 分钟,然后我不得不回溯并撤销一连串的更改。“先不要实施”这道防线彻底消灭了这种可能性。
实施过程中的反馈
一旦 Claude 开始执行计划,我的角色就从架构师转变为监督者。我的 Prompt 会变得非常简短。
在规划阶段,一个注释可能是一个段落;而在实施阶段,一个纠正通常只有一句话:
deduplicateByTitle函数。”由于 Claude 拥有计划和当前会话的完整上下文,这种简短的纠正就足够了。
前端工作是迭代最频繁的部分。我在浏览器中测试并快速发出修正指令:
对于视觉问题,我有时会附上截图。一张对齐错误的表格截图比文字描述更能快速传达问题。
我也经常参考现有代码:
这比从头描述设计要精确得多。在成熟的代码库中,大多数功能都是现有模式的变体。一个新的设置页面应该看起来像现有的设置页面。指向参考文件可以传达所有隐含的要求,而无需费力解释。Claude 通常会在修正前阅读参考文件。
当事情走向错误的方向时,我不尝试修补。我会通过撤销 Git 更改来重置并重新调整范围:
在撤销后缩小范围,几乎总是比试图增量修复一个错误的方案效果更好。
保持主导性
尽管我将执行委托给了 Claude,但我从不给它决定“构建什么”的完全自主权。我在
plan.md文档中完成了绝大部分的主动引导。这很重要,因为 Claude 有时会提出技术上正确但对项目来说是错误的方案。也许该方法过度设计了,或者它改变了一个其他系统依赖的公共 API 签名,又或者它在有更简单的选择时选了一个复杂的。我拥有关于整个系统、产品方向和工程文化的上下文,而 Claude 没有。
我会从提案中“精挑细选”: 当 Claude 发现多个问题时,我会逐一过一遍:“对于第一个,直接用
Promise.all,别搞太复杂;对于第三个,提取成独立函数以提高可读性;忽略第四和第五个,不值得为此增加复杂度。” 我是基于对当前重点的了解来做出单项决策的。削减范围: 当计划中包含了一些“有了更好(nice-to-haves)”的功能时,我会主动砍掉它们:“从计划中删除下载功能,我现在不想实现这个。” 这防止了范围蔓延(scope creep)。
保护现有接口: 当我确信某些东西不应改变时,我会设定硬约束:“这三个函数的签名不能变,调用方应该去适配,而不是库去适配。”
覆盖技术选择: 有时我有特定的偏好,而 Claude 无法预知:“使用这个模型而不是那个模型”,或者“使用这个库的内置方法,而不是手写一个自定义方法”。这些是快速、直接的指令覆盖。
Claude 处理机械性的执行,而我负责做判断决策。计划在前期捕捉大决策,而选择性的引导则处理实施过程中出现的细小决策。
单一长会话
我会在一个单一的长会话中完成调研、规划和实施,而不是将它们拆分到不同的会话中。一个会话可能始于深度阅读一个文件夹,经历三轮计划标注,然后运行完整实施,这一切都在一段连续的对话中完成。
我并没有察觉到大家常说的“上下文窗口超过 50% 后性能下降”的问题。实际上,到我说出“全部实施”时,Claude 已经用整个会话建立了深刻的理解:在调研期间阅读文件,在标注循环中完善思维模型,吸收我对领域知识的修正。
当上下文窗口填满时,Claude 的自动压缩功能(auto-compaction)能保留足够的上下文以维持运行。而且计划文档作为持久产物,在压缩过程中能保持完整的保真度。我可以在任何时间点让 Claude 参考它。
一句话总结工作流
深入阅读,编写计划,标注计划直到它完美,然后让 Claude 不停顿地执行全部内容,并沿途检查类型。
就是这样。没有神奇的提示词,没有复杂的系统指令,没有投机取巧的黑科技。只有一个严谨的流水线,将“思考”与“打字”分离开来。
试一下我的工作流吧,你会惊讶于在没有一份标注过的计划文档介入的情况下,你以前是怎么敢用编程 Agent 发布代码的。