Home Projects Blog Resume Contact 中文
Back to list
2026年7月2日 3,754 words 9 min read

06:Planning & Task State:Claude Code 怎么使用 plan 稳住任务

上一篇讲 Context Management,重点是:Claude Code 每一轮到底让模型看见什么。

#Claude Code#Coding Agent#工程化#Agent Runtime

06:Planning & Task State:Claude Code 怎么使用 plan 稳住任务

上一篇讲 Context Management,重点是:Claude Code 每一轮到底让模型看见什么。

但模型看见材料以后,还要继续往前走一步。它需要把用户目标、项目上下文、工具结果和已有约束整理成一个可以执行的路径。否则上下文越多,反而越容易变成“看到哪里就追到哪里”。

所以这一篇只抓住一个问题:

Claude Code 是怎么使用 plan,把一个模糊任务变成可执行、可校正、可验证的工作路径?

这里的 plan,不是为了让回复看起来更有条理。它更像动手前临时固定下来的一份工作草稿:当前理解是什么,准备先看哪里,可能改哪里,哪些范围先不碰,最后用什么结果判断完成。

这篇文章要拆的主线:Claude Code 怎么使用 plan

05 讲的是“这一轮看什么”。06 要接着讲“看见以后怎么组织行动”。

Claude Code 做代码任务时,用户给的入口经常很短:

修一下构建失败。

把这个页面样式调一下。

参考前面的讨论改 。

这些话能表达目标,但不一定能直接变成安全的文件改动。真正开始做之前,Claude Code 需要先判断几件事:

  • 问题可能在哪些文件或模块里。
  • 需要先读哪些上下文。
  • 改动会不会牵涉多个位置。
  • 哪些地方暂时不该碰。
  • 最后用什么方式证明任务完成。

plan 的价值就在这里。它把“我要做什么”先压成一个临时工作假设,让后面的工具调用围绕这个假设推进。

这和上篇讲的上下文管理正好接上。上下文管理负责把材料摆到模型面前,plan 负责把材料变成行动路线。

为什么需要 plan:防止工具调用变成随手反应

Claude Code 的强项是能连续调用工具。它可以读文件、搜代码、改文件、跑命令、看测试结果,再继续下一轮。

这个能力很强,也很容易失控。

如果没有 plan,任务可能变成一串局部反应:

  1. 看到构建报错,就去改报错文件。
  2. 改完发现另一个文件类型不匹配,又继续改。
  3. 搜索时看到旧代码顺手重构。
  4. 测试失败后开始追另一个问题。
  5. 最后改了不少东西,却说不清最初目标有没有完成。

每一步单独看都合理,连起来就可能跑偏。

plan 解决的不是“模型会不会思考”,而是“每一步工具调用是不是还服务于原始任务”。它让 Claude Code 在动手前先给任务划出一个临时边界:

plan 要固定的内容它防止什么问题
目标防止做着做着换成另一个目标
范围防止读到哪里改到哪里
步骤防止工具调用变成随手反应
边界防止顺手重构和无关改动
验证方式防止“看起来完成”代替真实完成

所以 plan 更像 Agent Loop 里的方向盘。工具让 agent 能动手,plan 让它知道每次动手要朝哪个方向。

plan 出现在什么时候

计划有成本。

它会多占一轮思考,也会多占一些上下文。如果只是修一个错别字、改一行文案、加一个很明确的日志,显式 plan 反而显得笨重。

Claude Code 的最佳实践里也把节奏讲得很清楚:先探索,再计划,再编码。这个节奏主要用于不确定、范围较大、需要先审方案的任务[1]。如果能用一句话说清楚 diff,通常可以直接做。

更适合显式 plan 的场景,大概有几类:

  1. 多文件改动。 用户需要知道会碰哪些地方,Claude Code 也需要避免漏掉依赖关系。

  2. 不熟悉代码库。 先读文件、看调用链、理解错误,再计划,能减少“解错题”的概率。

  3. 重构或迁移。 步骤之间有顺序,先后错了容易留下半成品。

  4. 验证路径不明确。 不知道该跑哪个测试、看哪个页面、检查哪个输出时,plan 要先把验证方式列出来。

  5. 需要用户先看范围。 有些任务不是不能做,而是动手前最好让用户确认改动边界。

这也是 plan mode 的位置。它让 Claude Code 可以先研究和提出方案,在没有批准前不改源码。这个能力的重点不是“多一个模式”,而是把研究、计划和编辑拆开:先弄清路线,再进入执行[2]。

plan 怎样生成:先观察,再整理路径

一个有用的 plan 通常不应该凭空生成。

如果用户只说“修构建失败”,Claude Code 一上来就列:

  1. 检查构建。
  2. 修改代码。
  3. 跑测试。

这类计划很整齐,但信息量很低。它没有说明错误可能在哪,准备先看什么,也没有说明验证方式。

更好的顺序是先观察。

Claude Code 会先把 05 讲过的上下文选择用起来:看用户目标,读已有约束,找相关文件,查看命令输出或错误信息。等到有了基本证据,再整理 plan。

可以把这个过程拆成五步:

  1. 读目标。 确认用户真正要的结果,是修失败、改样式、补文档,还是只做分析。

  2. 找约束。 包括用户明确说过的边界、项目规则、当前文件结构、前文已经确定的方向。

  3. 读证据。 看错误、相关文件、搜索命中、测试输出、已有 diff。

  4. 形成路径。 决定先检查哪里、再改哪里、最后怎么验证。

  5. 写出边界。 说明哪些东西暂时不碰,哪些风险需要留意。

这样生成的 plan 才会贴着任务走。

它不是“通用开发流程”,而是基于当前上下文的执行假设。

一个有用的 plan 应该包含什么

plan 不需要很长,但要有抓手。

我会把 Claude Code 的 plan 理解成六个小块:

小块要回答的问题
目标这次到底要解决什么
范围会看或改哪些文件、模块、章节
步骤先观察什么,再修改什么,再验证什么
边界哪些地方暂时不碰
风险哪些判断可能被后续证据推翻
验证用什么结果说明任务完成

比如“修构建失败”的 plan,可以不是一大段流程,而是这样:

  • 目标:让当前构建命令重新通过。
  • 范围:先检查报错指向的配置和引用文件,不做顺手重构。
  • 步骤:复现构建失败,定位第一处真实错误,读取相关文件,做最小修改,再重跑构建。
  • 边界:不改无关模块,不为了风格调整扩大 diff。
  • 风险:构建失败可能是多个错误连锁触发,需要按第一个根因处理。
  • 验证:构建命令退出码为 0,并检查 diff 只覆盖相关文件。

这种 plan 的好处是清楚。

用户能看懂 Claude Code 准备怎么动手,Claude Code 后续也能用它约束自己:读文件是为了定位根因,编辑是为了最小修复,跑命令是为了证明结果。

plan 如何影响后续执行

plan 写出来以后,真正的价值才开始。

它会影响后续每一次工具调用。

读文件,不是漫无目的地浏览仓库,而是为了确认 plan 里的某个判断。编辑文件,不是看到可以优化就顺手改,而是为了完成 plan 里的某个步骤。运行命令,也不是为了“做点验证动作”,而是为了检查 plan 里的完成标准。

可以把执行过程看成一个小闭环:

当前 plan
-> 工具调用
-> 工具结果
-> 判断 plan 是否仍然成立
-> 继续执行或修正 plan

这里最关键的是“修正”。

plan 不是不可修改的合同。它更像一份当前最佳假设。只要工具结果回来,Claude Code 就要重新判断:

  • 这个结果支持原计划吗?
  • 是否发现了更准确的问题位置?
  • 是否有步骤已经不需要了?
  • 是否有新风险需要告诉用户?
  • 是否需要先停下来重新确认范围?

比如原计划认为构建失败来自 TypeScript 配置,结果读完日志发现真正问题是某个导入路径大小写不一致。此时继续按原计划研究配置,就是在浪费上下文。更好的做法是更新 plan:从“检查配置”改成“修正导入路径并验证构建”。

这个更新动作很重要。

成熟的 plan 系统不是让 agent 死守第一版计划,而是让每次偏离都有理由。工具结果改变了判断,计划就跟着变;用户补充了限制,计划也跟着收窄。

plan 和完成不是一回事

plan 只能说明“准备怎么做”,不能证明“已经做好”。

很多长任务会在这里出问题。Claude Code 完成了 plan 里的几个步骤,就可能产生一种“任务应该结束了”的感觉。但用户真正要的不是步骤被执行,而是结果成立。

所以计划的最后一步一定要回到验证。

验证可以是:

  • 测试通过。
  • 构建成功。
  • lint 或 typecheck 干净。
  • diff 只触及预期范围。
  • 页面截图和目标状态一致。
  • 用户明确确认方案或结果可接受。

Claude Code 最佳实践里也强调,要给 Claude 一个能自己读取的检查信号。没有检查时,“看起来完成”就是唯一信号;有测试、构建、脚本、截图这类可读反馈时,Claude 才能自己闭环迭代[1]。

这里可以轻轻带到 todo 和 goal 的位置。

todo 更像过程记录,告诉当前做到哪一步。goal 或验收条件更像终点判断,告诉任务什么时候可以停。它们都可以服务 plan,但这篇不展开它们的产品机制。

这一篇只保留一个结论:

plan 负责组织执行,验证负责判断结果。

把这两件事分开,Claude Code 才不容易把“我按计划做了”误当成“任务已经完成”。

plan 和长任务交接

短任务里,plan 通常只需要在当前会话里起作用。

长任务会更麻烦。上下文会膨胀,会压缩,会恢复,也可能中途换人或换会话。Anthropic 关于长任务 harness 的文章里提到,长时间运行的 agent 需要进度文件、增量推进、测试验证和清晰交接,不能只依赖上下文压缩[3]。

放到 plan 上,就是一句话:

计划如果要跨阶段继续,就要留下能接手的状态。

这里不需要把每一步都写成正式文档,但至少要保留几类信息:

  • 当前目标是什么。
  • 已经完成了哪些步骤。
  • 哪些判断被工具结果推翻过。
  • 哪些文件已经改过。
  • 哪些验证已经跑过,结果是什么。
  • 下一步应该从哪里继续。

这些信息可以留在会话摘要、任务状态、progress 文件、PR 描述或项目文档里。它们不一定都属于 Claude Code 的长期记忆,但它们是长任务继续推进时的接力棒。

这也解释了为什么 05 讲上下文压缩时,要保留目标、关键文件、已改内容、验证结果、风险和下一步。压缩后的摘要如果没有这些字段,plan 就很难继续工作。

对我写 Agent 的启发

如果自己做一个 coding agent,我会把 plan 当成一个可更新对象,而不是一段一次性文本。

最小字段可以这样设计:

字段作用
goal当前任务要达成什么
scope本轮准备查看或修改的范围
steps接下来按什么顺序推进
boundary哪些动作或文件暂时不碰
verification用什么结果判断完成
risks哪些地方可能改变计划
updated_reason为什么这次更新计划

这里面最重要的是 updated_reason

计划改变不可怕,悄悄改变才可怕。每次工具结果回来以后,agent 都应该问一句:

这个结果是在支持当前 plan,还是要求我调整 plan?

如果要调整,就把原因写出来。比如“测试失败显示问题不在配置,而在导入路径”,或者“用户补充不要改样式,所以移除 UI 调整步骤”。

我还会给 plan 加三条约束:

  1. 先观察再计划。 不熟悉代码时,先读关键文件、错误输出和项目规则,再列步骤。

  2. 计划要有边界。 每个 plan 都应该说清楚暂时不碰什么。边界能减少顺手重构和范围漂移。

  3. 完成必须靠验证。 plan 执行完以后,还要用测试、构建、diff、截图或用户确认来收尾。

这样写出来的 agent 会更稳一点。它不是每一步都显得很隆重,而是在任务真正复杂时,有一个可以回头看的工作草稿。

我现在对 Claude Code 使用 plan 的理解可以收成一句话:

plan 把上下文里的材料整理成行动假设,再让工具结果不断校正这个假设。

参考资料

Claude Code 文档

相关机制

下一篇继续追的问题

这一篇先把 plan 理解成 Claude Code 的行动草稿。

它解决的是:

看到上下文以后,准备怎么做。

但计划本身不会执行。真正动手时,Claude Code 还要判断这些动作能不能做、是否需要用户确认、会不会触碰敏感文件、外部系统或不可逆命令。

所以 07 继续追:

Claude Code 如何通过权限、settings、hooks 和 sandbox,把 plan 里的行动变成受控执行?