分享使用Claude Code的核心最佳实践——将规划和执行分离,直接改进开发者的AI编程工作效率,引发976分热议。
我来完整翻译这篇文章:
我已经使用 Claude Code 作为我的主要开发工具大约 9 个月了,我所形成的工作流程与大多数人使用 AI 编码工具的方式截然不同。大多数开发者会输入一个 prompt,有时候使用规划模式,修复错误,然后重复。那些更加活跃的开发者在拼凑 ralph loops、mcps、gas towns(还记得那些东西吗?)等等。两种情况的结果都是一团糟,对任何非平凡的工作都完全崩溃。
我将要描述的工作流程有一个核心原则:在 Claude 写代码前,你必须审查并批准一个书面计划。这种规划和执行的分离是我所做的最重要的单一事情。它防止了浪费的努力,让我保持对架构决策的控制,并且相比直接跳到代码,能以最少的 token 使用产生显著更好的结果。
flowchart LR
R[Research] --> P[Plan]
P --> A[Annotate]
A -->|repeat 1-6x| A
A --> T[Todo List]
T --> I[Implement]
I --> F[Feedback & Iterate]
每一项有意义的任务都从一个深度阅读指令开始。我要求 Claude 在做任何其他事情之前,彻底理解代码库中相关的部分。而且我总是要求将发现内容写入一个持久的 markdown 文件,永远不只是在聊天中做口头总结。
read this folder in depth, understand how it works deeply, what it does and all its specificities. when that's done, write a detailed report of your learnings and findings in research.md
study the notification system in great details, understand the intricacies of it and write a detailed research.md document with everything there is to know about how notifications work
go through the task scheduling flow, understand it deeply and look for potential bugs. there definitely are bugs in the system as it sometimes runs tasks that should have been cancelled. keep researching the flow until you find all the bugs, don't stop until all the bugs are found. when you're done, write a detailed report of your findings in research.md
注意措辞:"deeply"、"in great details"、"intricacies"、"go through everything"。这不是填充语。没有这些词,Claude 会跳读。它会读一个文件,看一下函数在签名级别做什么,然后继续。你需要表明表面级的阅读是不可接受的。
这个书面产物(research.md)很关键。这不是为了让 Claude 做家庭作业。这是我的审查界面。我可以读它,验证 Claude 是否真的理解了系统,以及在任何规划发生前纠正误解。如果研究是错误的,计划将是错误的,实现也将是错误的。垃圾进,垃圾出。
这是 AI 辅助编码中最昂贵的失败模式,它不是语法错误或不良逻辑。这是在隔离环境下工作的实现,但破坏了周围的系统。忽略现有缓存层的函数。不考虑 ORM 约定的迁移。复制已经存在其他地方的逻辑的 API 端点。研究阶段防止了所有这些。
一旦我审查了研究内容,我会要求一个详细的实现计划放在一个单独的 markdown 文件中。
I want to build a new feature <name and description> that extends the system to perform <business outcome>. write a detailed plan.md document outlining how to implement this. include code snippets
the list endpoint should support cursor-based pagination instead of offset. write a detailed plan.md for how to achieve this. read source files before suggesting changes, base the plan on the actual codebase
生成的计划总是包括对方法的详细解释、展示实际更改的代码片段、将被修改的文件路径,以及考虑因素和权衡。
我使用我自己的 .md 规划文件,而不是 Claude Code 的内置规划模式。内置规划模式很糟糕。我的 markdown 文件让我完全控制。我可以在编辑器中编辑它,添加内联注释,它作为项目中的真实产物而存在。
我经常使用的一个技巧是:对于那些我在开源仓库中看到过好的实现的自包含特性,我会在规划请求旁边分享那个代码作为参考。如果我想添加可排序的 ID,我会从一个做得很好的项目粘贴 ID 生成代码,然后说"这是他们怎样做可排序 ID 的,写一个 plan.md 解释我们如何可以采纳类似的方法"。当 Claude 有一个具体的参考实现可以参考,而不是从零开始设计时,它的表现会显著更好。
但规划文档本身并不是有趣的部分。有趣的部分是接下来发生的事。
这是我工作流程中最独特的部分,也是我增加最多价值的部分。
flowchart TD
W[Claude writes plan.md] --> R[I review in my editor]
R --> N[I add inline notes]
N --> S[Send Claude back to the document]
S --> U[Claude updates plan]
U --> D{Satisfied?}
D -->|No| R
D -->|Yes| T[Request todo list]
在 Claude 写完计划后,我在编辑器中打开它,并直接向文档中添加内联注释。这些注释纠正假设、拒绝方法、添加约束或提供 Claude 没有的领域知识。
注释的长度差异很大。有时候注释只有两个词:"not optional",出现在 Claude 标记为可选的参数旁边。其他时候它是一段话,解释业务约束或粘贴一个代码片段,显示我期望的数据形状。
一些我会添加的真实注释例子:
"use drizzle:generate for migrations, not raw SQL" —— Claude 没有的领域知识
"no — this should be a PATCH, not a PUT" —— 纠正一个错误的假设
"remove this section entirely, we don't need caching here" —— 拒绝一个提议的方法
"the queue consumer already handles retries, so this retry logic is redundant. remove it and just let it fail" —— 解释为什么某件事应该改变
"this is wrong, the visibility field needs to be on the list itself, not on individual items. when a list is public, all items are public. restructure the schema section accordingly" —— 重定向计划的整个部分
然后我把 Claude 送回文档:
I added a few notes to the document, address all the notes and update the document accordingly. don't implement yet
这个循环重复 1 到 6 次。明确的"don't implement yet"保护是必要的。没有它,Claude 一旦认为计划足够好就会跳到代码。直到我说可以,它才足够好。
markdown 文件作为我和 Claude 之间的共享可变状态。我可以按照自己的节奏思考,精确注释哪里出了问题,然后重新参与而不会丢失上下文。我不是试图在聊天消息中解释一切。我是指向文档中出了问题的确切位置,并在那里写下我的更正。
这与试图通过聊天消息引导实现从根本上是不同的。计划是一个结构化的、完整的规范,我可以整体审查。聊天对话是我必须滚动浏览以重建决策的东西。计划每次都赢。
三轮"我添加了注释,更新计划"可以将一个通用的实现计划转变为完美适应现有系统的计划。Claude 擅长理解代码、提议解决方案和编写实现。但它不知道我的产品优先级、我的用户的痛点或我愿意做出的工程权衡。注释循环是我注入那种判断力的方式。
在实现开始前,我总是要求一个细粒度的任务分解:
add a detailed todo list to the plan, with all the phases and individual tasks necessary to complete the plan - don't implement yet
这创建了一个检查清单,用作实现期间的进度跟踪器。Claude 在进行时将项目标记为完成,所以我可以在任何时刻扫一眼计划,看到事情进展的确切位置。在运行数小时的会话中特别有价值。
当计划准备好时,我发出实现命令。我已经将其细化为一个标准 prompt,我在会话中反复重用:
implement it all. when you're done with a task or phase, mark it as completed in the plan document. do not stop until all tasks and phases are completed. do not add unnecessary comments or jsdocs, do not use any or unknown types. continuously run typecheck to make sure you're not introducing new issues.
这个单一 prompt 编码了所有重要的东西:
"implement it all":做计划中的一切,不要精选
"mark it as completed in the plan document":计划是进度的真实来源
"do not stop until all tasks and phases are completed":不要在流程中间暂停以寻求确认
"do not add unnecessary comments or jsdocs":保持代码干净
"do not use any or unknown types":维持严格的类型
"continuously run typecheck":尽早捕获问题,而不是在最后
我在几乎每个实现会话中使用这个确切的措辞(有轻微的变化)。到我说"implement it all"时,每一个决策都已被做出和验证。实现变成了机械的,而不是创造性的。这是故意的。我想要实现是无聊的。创造工作发生在注释循环中。一旦计划是对的,执行应该是直接的。
没有规划阶段,通常发生的是 Claude 在早期做出一个合理但错误的假设,在它上面构建 15 分钟,然后我必须解开一系列更改。"don't implement yet"保护完全消除了这个问题。
一旦 Claude 在执行计划,我的角色从架构师转变为监督员。我的 prompt 变得戏剧性地更短。
flowchart LR
I[Claude implements] --> R[I review / test]
R --> C{Correct?}
C -->|No| F[Terse correction]
F --> I
C -->|Yes| N{More tasks?}
N -->|Yes| I
N -->|No| D[Done]
其中规划注释可能是一段话,实现纠正通常是一句话:
"You didn't implement the deduplicateByTitle function."
"You built the settings page in the main app when it should be in the admin app, move it."
Claude 拥有计划的完整上下文和进行中的会话,所以简洁的纠正就足够了。
前端工作是最迭代的部分。我在浏览器中测试并发出快速纠正:
对于视觉问题,我有时会附加截图。一个表格对齐错误的截图比描述问题传达得更快。
我也经常引用现有代码:
"this table should look exactly like the users table, same header, same pagination, same row density."
这比从头描述设计精确得多。成熟代码库中的大多数特性都是现有模式的变体。新的设置页面应该看起来像现有的设置页面。指向参考传达了所有的隐含需求,而不用拼写出来。Claude 通常会在做更正前读参考文件。
当某件事朝错误的方向发展时,我不试图修补它。我通过丢弃 git 更改来回滚并重新界定范围:
"I reverted everything. Now all I want is to make the list view more minimal — nothing else."
在回滚后缩小范围几乎总是比试图逐步修复一个糟糕的方法产生更好的结果。
虽然我委托执行给 Claude,但我从不给它对什么被构建的完全自主权。我做了绝大多数在 plan.md 文档中的主动引导。
这很重要,因为 Claude 有时会提议在技术上正确但对项目错误的解决方案。也许方法是过度设计的,或者它改变了一个系统其他部分依赖的公共 API 签名,或者它在有更简单选项时选择了更复杂的选项。我拥有关于更广泛系统、产品方向和 Claude 没有的工程文化的上下文。
flowchart TD
P[Claude proposes changes] --> E[I evaluate each item]
E --> A[Accept as-is]
E --> M[Modify approach]
E --> S[Skip / remove]
E --> O[Override technical choice]
A & M & S & O --> R[Refined implementation scope]
从提议中精选:当 Claude 识别出多个问题时,我逐一处理它们:"for the first one, just use Promise.all, don't make it overly complicated; for the third one, extract it into a separate function for readability; ignore the fourth and fifth ones, they're not worth the complexity."我根据对什么现在重要的了解做出项目级别的决策。
修剪范围:当计划包括不错的功能时,我主动削减它。"remove the download feature from the plan, I don't want to implement this now."这防止了范围蔓延。
保护现有接口:当我知道某件事不应该改变时,我设置硬约束:"the signatures of these three functions should not change, the caller should adapt, not the library."
覆盖技术选择:有时我有一个特定的偏好 Claude 不会知道:"use this model instead of that one"或"use this library's built-in method instead of writing a custom one."快速、直接的覆盖。
Claude 处理机械执行,而我做出判断调用。计划在前期捕获大的决策,而有选择的指导处理在实现过程中出现的较小的决策。
我在单个长会话中运行研究、规划和实现,而不是将它们分开到不同的会话中。单个会话可能从深度读取一个文件夹开始,经过三轮计划注释,然后运行完整的实现,全部在一个连续的对话中。
我没有看到每个人在填充 50% 的上下文窗口后谈论的性能降低。实际上,到我说"implement it all"时,Claude 已经在整个会话中构建理解:在研究中读取文件,在注释循环中精化其心理模型,吸收我的领域知识纠正。
当上下文窗口填满时,Claude 的自动压缩保留足够的上下文来继续。而计划文档,这个持久的产物,在压缩后保留完整的保真度。我可以在任何时刻指向它。
深度阅读,写一个计划,注释计划直到正确,然后让 Claude 执行整个事情而不停止,在进行中检查类型。
就这样。没有魔法 prompt,没有精巧的系统指令,没有聪明的黑客。只是一个有纪律的管道,将思考从打字中分离出来。研究防止 Claude 做出无知的更改。计划防止它做出错误的更改。注释循环注入我的判断。实现命令让它在每一个决策都已做出后无中断地运行。
尝试我的工作流程,你会想知道你怎样没有一个注释的计划文档坐在你和代码之间就用编码代理交付过任何东西。
我也在构建 polylane,因为在 2026 年没有人应该值班。