阿隆自留地

hacknews-daily

先逼它交计划书,再让它写代码:一个用了9个月的Claude Code工作流

文章摘要

Boris Tane 是 Checkly 的创始人,他花了9个月把 Claude Code 变成自己的主力开发工具,然后写了一篇文章把这9个月摸索出来的工作流说清楚。

核心原则:在Claude写任何一行代码之前,必须有一份书面计划,而且你必须亲自审阅并认可它。

流程分三个阶段。第一阶段是研究——让Claude深度阅读代码库,写出research.md;第二阶段是计划与标注循环——Claude根据研究写出plan.md,你在文档里直接加注释,把它退回去让Claude修改计划(但不要实现),如此反复;第三阶段才是实现——一次性给出指令,让它不停直到所有任务完成,期间持续运行类型检查。

这个流程在HN上引发了929票和568条评论。人们不只是在讨论这个具体流程,更在讨论一个更大的问题:当LLM的行为对提示词的措辞如此敏感,我们到底有没有在做工程,还是在做某种AI时代的占星术?


背景与问题

"大多数人用AI编程的方式是错的"

Tane 的文章开头就是这么说的。他观察到的常见模式是:打开IDE,输入一个提示词,看Claude开始写,发现它走错了方向,中途打断,修正,继续,结果越改越乱,最后要么接受一个自己不完全理解的实现,要么从头来过。

这个描述击中了很多人的痛点——不是因为Claude不够聪明,而是因为**"让模型直接开始写代码"这件事在根本上就跳过了软件开发中最重要的环节:把问题和方案想清楚**。

规划先行不是新想法,只是现在有了新的实施难点

HN评论区里多位有20年以上经验的工程师指出,Tane描述的工作流骨子里就是他们一直以来的工作方式:深度阅读代码库→写设计文档→获得评审认可→实现。AI只是让"实现"这一步快了很多,其他步骤的必要性没有减少。

但LLM带来了一个新的挑战:这个"实现"工具极其强大,能快速生成大量看起来正确的代码,这反而会诱使开发者绕过规划环节,因为你会觉得"这么聪明的工具,让它直接试试不行吗?"——事实证明往往不行。

问题的核心:LLM的失败不在语法,在假设

一位HN评论者的表述让很多人觉得说到了点子上:

"LLM的失败不发生在语法层面,而发生在架构假设层面。它生成的代码可以完全没有语法错误,但它做出了5个错误的业务假设——这些假设你在计划阶段本来是可以捕获的,但在代码层面是看不见的。"

书面计划的作用,是把这些不可见的假设变成可见的、可以被人类审查和纠正的文字。


核心内容解析

3.1 三阶段工作流详解

第一阶段:研究(research.md)

开始任何功能之前,Tane让Claude做的第一件事是深度阅读代码库,然后写一份研究报告:

Read [folder] deeply and in great detail. Pay attention to all the 
intricacies. When done, write a detailed report in research.md.

两个关键词:"deeply""in great details"。这不是装饰性语言——在实践中,不加这些词,Claude会做表面扫描;加上这些词,它会做更彻底的读取(更多的tool calls,更多的推理)。

这份research.md的作用不是给Claude看的,而是给你自己看的。你通过它来确认Claude是否真正理解了代码库的结构和设计意图,然后再让它开始规划。如果research.md里有明显的误解,在规划阶段纠正比在实现阶段纠正要容易得多。

第二阶段:计划与标注循环(plan.md)

Research之后,让Claude写一份完整的实现计划:

Based on the research, write a plan.md that outlines how we should 
implement [feature]. Include file paths, code snippets, and the 
trade-offs of different approaches. Do not implement yet.

最后那句"Do not implement yet"(不要实现)是整个流程的关键守卫——如果不写这句话,Claude很可能在写完计划后直接开始写代码。

计划写完后,Tane打开plan.md在编辑器里直接加行内注释:

## Phase 2: Database Migration

We'll use raw SQL for the migration.
<!-- NO - use drizzle:generate for migrations, not raw SQL -->

The API endpoint should use PUT for this operation.
<!-- This should be PATCH, not PUT - only partial update -->

然后把这个带注释的文档交还给Claude:"address all notes in the plan and update it accordingly. Do not implement yet."

这个循环会重复1到6次,直到你对计划感到满意。整个过程的关键哲学是:在实现开始之前,把所有的设计决策都做完。实现阶段应该是无聊的执行,不应该有任何创造性决策。

第三阶段:实现

当计划通过后,Tane使用的是一条相对标准的实现提示词:

Implement it all. When done with a task, mark it completed in the plan. 
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.

几个细节值得注意:要求它标记完成的任务(保持进度可见);明确要求持续跑类型检查(机器验证,减少需要人工审查的错误);明确禁止不必要的注释(防止代码噪音)。

实现阶段的监督是非常简短的。发现视觉问题就截图传过去,文字修正极其简洁("wider","still cropped","2px gap on the right")。遇到方向错误,直接revert并重新定义范围,而不是继续在错误的基础上打补丁。

一个额外技巧:参考实现

对于有良好开源参考实现的功能,Tane会把那个参考代码直接粘进去:"I want to add sortable IDs. Here's how [OSS project] does it. Write a plan.md explaining how we can adopt a similar approach."给Claude一个具体的参考实现,比让它从头设计要可靠得多。

3.2 "deeply"这个词到底在起什么作用

这是HN评论里持续时间最长、分歧最大的讨论之一。

有效果的观察:几乎所有实际使用过这个技巧的人都报告它有效果。加了"deeply"和"in great detail"之后,Claude确实做了更彻底的阅读。

为什么有效果?几种解释

注意力机制解释:这些词把提示向量指向了"深度专业分析"对应的概念空间,在训练数据中,这类描述词与高质量的深度分析文本高度相关。

实效解释(最被接受的):这些词让Claude倾向于发出更多的tool calls(读取更多的文件),以及在推理时分配更多的计算资源(更多的思考token)。从这个角度来看,它不是心理学效应,而是行为指令——它告诉模型要做更多的工作。

Claude对情感刺激有响应的研究:有人引用了2023年的一篇论文(arXiv: 2307.11760),发现LLM对情感刺激有可测量的响应。说"please"、"thank you"、或者表达这个任务很重要,确实会影响输出质量。

怀疑者的立场

另一部分评论者的立场同样有力:"你不能在相同的提示词上得到一致可重复的结果,因为这个系统本质上是随机的。你只是在优化某些随机种子下的输出,然后把这个优化当作了因果规律。这不是工程,这是占星术。"

这个争论没有在讨论里得到解决,因为它触及的是一个尚无定论的基础问题:对于不确定性系统,"有可测量平均提升效果"和"可重复的确定性工程"之间的区别在哪里?

3.3 ".md文件作为人机共享状态"的设计洞察

HN一位评论者提出了一个让很多人觉得透彻的表述:

"Tane实际上是把.md文件当作人类和AI之间的共享可变状态(shared mutable state)在使用。这是个非常干净的接口:人类可以读它、修改它、推理它;AI也可以读它、修改它、基于它规划。这比任何对话式交互都更透明。"

plan.md不只是一个文档,它是一个协作界面。它把双方的理解状态外显化,让误解变得可见。这也是为什么"在计划里加行内注释"比"另起一个对话窗口告诉Claude修改"更有效——注释和计划内容在同一个文档里,上下文是完整的。

3.4 更复杂的工作流变体

HN的评论天然成为了这个工作流的扩展讨论板。几个值得注意的变体:

多文档分层:多位评论者描述了比Tane更复杂的文档系统——Specs(静态,描述整体架构)→ Plans(每个功能的实现计划)→ Working Memory(当前状态跟踪)。这在大型项目里能更好地管理上下文。

TDD式集成:在实现前先让Claude写API级别的测试,然后你审查和注释这些测试,等测试确定了再写实现。这把人类审查的关口前移到了测试定义阶段,而不是代码层面。

批量实现代替一次性实现:Tane的流程是"写完计划后一次性实现",但多位评论者认为"按阶段实现+每阶段提交"更稳健,出问题时回退的代价更小。

"证明"步骤:一位评论者提出在实现前加一个"Prove"步骤——让Claude证明计划是可行的,枚举所有风险并说明计划如何缓解这些风险。在这个步骤中,模型偶尔会发现自己之前计划里的盲点。


深度分析与思考

4.1 这个工作流值钱的地方

Tane工作流的核心贡献不是那些提示词技巧,而是一个思维框架的转变:实现(implementation)应该是无聊的,所有真正的决策都应该在规划阶段发生。

这个原则在传统软件工程里也是成立的,但程序员很少真的做到它——因为"开始写"比"认真规划"更有即时回报感,而且规划的不足往往要在写代码很久之后才暴露。

AI工具恰好放大了这个矛盾:它让"开始写"的成本降到了接近于零,但它规划阶段的不足并没有消失,只是被掩盖在大量生成的代码里了。通过强制计划先于实现,Tane的工作流其实是在给这个加速了的"开始写"过程加上了一个强制性的减速阀。

4.2 对不同读者的实际价值

个人开发者 / 独立工程师:这个工作流对独立开发者价值最高。它帮助你系统化地把"想清楚"和"做出来"分开,防止在错误方向上浪费大量AI token和自己的时间。research.md的习惯特别有价值——很多bad Claude outputs的根源是Claude没有真正理解代码库。

团队开发者:plan.md有一个非常实用的副作用:它是优秀的技术文档。当你把注释和决策过程都留在计划文件里,未来的维护者(包括你自己)能理解"为什么这样设计"。多位评论者指出,这解决了一个传统软件开发里长期存在的问题:代码告诉你"是什么",但从不告诉你"为什么"。

技术领导者:这个工作流的可看点不是提示词,而是它揭示的LLM失败模式。如果你在领导一个使用AI辅助开发的团队,最重要的投资是在"审查阶段"建立清晰的标准——不只是审查代码,而是审查AI的规划。

怀疑AI辅助开发的工程师:这个工作流对你最有说服力的部分是它承认了AI辅助开发的局限性,并在设计上明确应对这些局限。它不是"把一切交给AI",而是"你仍然是工程师,AI是一个需要管理的实现工具"。

4.3 争议点:这只是在用复杂的方式做原本简单的事吗?

一部分评论者有保留意见,这些意见值得认真对待。

"这其实就是Claude Code内置的计划模式":有评论者指出,Tane描述的流程本质上就是Claude Code内置计划功能在做的事,只不过Tane用自己的.md文件替代了内置工具。Tane自己也在文章里承认了这一点,并说"内置计划模式很烂(sucks)"。是否值得这个替换,取决于你对内置工具的满意程度。

"你花了大量时间管理计划文档,但没人测量这究竟值不值":反对复杂计划文档的评论者指出,维护plan.md、research.md本身是有成本的,当模型更新时过去的计划可能失效,计划文档的质量本身也无法保证。

没有测试的工作流是不完整的:多位评论者指出,Tane的文章里对测试的描述近乎于无。一个只依赖类型检查而没有测试覆盖的实现,很难保证长期可维护性。

4.4 关于"AI辅助工程"的本质

HN的评论里有一个引人深思的讨论链:有人把当前的AI辅助开发描述为"工程界的占星术"——相同的提示词,不同时间运行,可能得到不同结果;有人总结出有效的"魔法咒语",但无法解释为什么有效;功能可能在某个模型版本上工作,在下一个版本上失效。

这个批评有其合理性,但一个反驳同样成立:软件工程里有大量公认有效的实践,它们的"有效"也只是统计意义上的,而不是数学证明意义上的。Code review减少bug,这是行业共识,但没有人能证明对任意一次code review这个因果关系都成立。

区别可能在于:好的工程实践有可解释的机制,哪怕机制是统计性的。"在计划阶段捕获架构假设,比在实现阶段捕获更便宜"这个命题,有可解释的理由;"在提示词里加'deeply'会让输出更好"这个命题,只有事后归纳,没有足够透明的机制。

我们可能处在AI辅助工程的一个过渡阶段:部分实践已经有了工程解释,部分实践仍然是"经验上有效但机制不透明的技巧"。随着我们对LLM的理解加深,边界会移动。


技术栈/工具清单

核心工具

  • Claude Code:Anthropic发布的AI编程工具,支持工具调用(读写文件、执行命令等)
  • Claude Sonnet / Opus 系列:Anthropic的模型,Opus 4.6是最新评估版本
  • Codex(OpenAI):另一个主流AI编程工具,部分评论者对比了两者的工作流差异

工作流格式

  • research.md:代码库研究报告,Claude生成,工程师审查
  • plan.md:实现计划,Claude生成,工程师标注,反复迭代
  • CLAUDE.md:Claude Code的项目级配置文件,定义项目惯例

辅助工具(讨论中提到)

  • Plannotator:Claude Code的计划注释插件(github.com/backnotprop/plannotator)
  • Superpowers / Obra:社区构建的Claude Code扩展技能集(github.com/obra/superpowers)
  • SpecKit(GitHub):spec驱动开发框架,提供specify→plan→tasks→implement流程
  • BMAD Method:另一个AI辅助开发的方法论框架

相关学术引用

  • arXiv 2307.11760:Large Language Models Understand and Can be Enhanced by Emotional Stimuli — 关于情感刺激对LLM输出质量影响的研究

相关资源与延伸阅读