上个月我让Claude Code做一次跨模块重构,没有开Plan模式,直接一句“开始改造吧”。结果它沿着一条看似合理的路径连改了二十几个文件,中途我发现它把老接口的兼容层改没了,等于是让线上的老客户端全部连不上。后面一整天,我都在git reset和重做里救场。
那次之后我养成了一个习惯:凡是涉及多个文件、存在设计取舍的任务,一律先切到Claude Code的Plan模式。这个模式本质上是一个任务前置规划器——它先以只读方式分析代码库,产出一份包含改动清单、依赖关系、风险点的可审阅方案,等你批准后才真正动手改代码。这篇文章就围绕这个模式展开:它到底解决什么问题、底层是怎么运作的、在多文件重构里怎么用、哪些任务反而别开Plan,以及你在接入DeepSeek、Qwen、GLM或者本地模型时,这个模式会出哪些幺蛾子。
1. 为什么复杂任务必须前置规划:一次硬拆大型项目的教训
1.1 让Claude Code直接动手的那次翻车
我当时给一个内部运营后台加一套基于角色的数据权限过滤。需求听起来不复杂:用户在后台看到的数据范围,要根据他的角色和所属部门来过滤。真正动起来才发现牵一发动全身——service层要注入角色上下文,controller层得改参数,数据库查询要拼过滤条件,前端菜单还要按角色收敛。
我图省事,没有做任何前置规划,直接跟Claude Code说“开始吧”。前二十分钟进展飞快,它连续改了十多个文件。等我巡检的时候冷汗就下来了:它把几个公共工具类里原本无关的逻辑顺手也改了,说是“为了统一数据权限入口”;更麻烦的是它在改一个老接口时把兼容层删了,这个接口还有存量客户端在用,一上线就是生产事故。
最后我只能让整个分支回滚,把它的改动一条条挑出来重新评估。那一整天什么都没干成,全耗在给AI擦屁股上。
1.2 问题不在模型脑力,在于任务结构
事后复盘,这口锅不在模型智商,而在任务结构。复杂任务有两个特征:存在决策依赖,存在隐藏约束。改A文件之前你得先知道B文件依赖A,还得知道有一个存量调用方在走老协议。Claude Code天然倾向于尽早产出代码,因为它的交互目标偏向“较快给出结果”。如果没人逼它先把全局想清楚,它就会走一步看一步,每一步都局部最优,最后整体跑偏。
人类工程师面对大活会先画依赖图、先列改动清单,不是因为性格谨慎,而是因为返工成本太高。AI执行代码也一样:方向上错了,它后续的每一条代码都建立在错误的地基上。前置规划这件事,不是流程上的仪式感,而是复杂任务的刚需。
1.3 关键认知:Plan模式是权限层约束,不是提示词技巧
不少人在普通模式下输入“先给我一份方案再动手”,然后发现模型嘴上答应,写了一会儿还是忍不住开始改文件。原因很简单:提示词是软约束,模型偶尔会“越权”。Plan模式不一样,它在工具权限层直接禁用了写操作——这个模式下Claude Code只能读文件和搜索代码,它想改也改不了,最多提交一份计划等你审批。这是工程上防呆的设计思路。
这个认知很重要,它意味着Plan模式不是玄学,而是一种可靠的机制保证:分析阶段不会污染代码库,也不会出现“方案还在讨论、文件已经被改了一半”的尴尬。
2. Plan模式底层到底做了什么:从只读探索到ExitPlanMode
2.1 一次Plan会话的完整工作流
我实际用下来的感受是,Plan模式并不是简单地“让AI多想想再说”,它背后有一套完整的工作流:
- 输入任务。你可以用普通自然语言描述需求,最好带上背景、约束和验收标准。
- 只读探索。模型开始grep定位符号、读取关键文件、梳理接口调用关系。这个过程相当于工程师动手前把相关代码翻一遍。
- 分析输出。模型会把对问题的理解、候选路径写在对话里,你能实时看到它在读哪些文件、为什么读。
- 提交计划。通过ExitPlanMode,把所有结论压缩成一份结构化计划:涉及文件、改动步骤、依赖顺序、风险、测试方案。
- 用户审批。approve进入执行;deny会带着你的修改意见要求重新规划。
- 执行阶段。批准后模型开始实际改文件,但此时它手里拿着自己写的计划,按图索骥。
这里最容易被忽略的是第5步。很多人把退出计划当成了一个“开关”,要么直接同意,要么直接放弃。但deny加一条具体反馈,才是Plan模式真正的威力所在:它让规划成为人和模型之间的迭代对话,而不是一次性的单选题。
2.2 token开销的账要算清楚
很多人觉得Plan模式浪费token:反正模型都要读代码,多一次规划不是多花一轮吗?我把账算给你看。
直接执行模式下的典型翻车路径是这样的:模型改到第8个文件时发现前面某个设计假设错了,于是回去改第3个文件,连带第5、6个文件重新改一遍,然后接口变动又触发新的调用方调整……中间每一次返工都要重新读取相关文件、重写代码片段,上下文里的历史记录也越来越长,最终token消耗动辄是预期的好几倍。
Plan模式下的token消耗是另一个结构:探索阶段读一批文件,输出计划,执行阶段按计划写。它不是不读代码,而是不重复读代码。所以只要任务复杂度超过一定阈值,Plan模式总开销反而更低。
我自己在大型重构里观察到的经验规律:直接执行,如果中途跑偏一次,总token大约是正常执行的1.8到2.5倍;开了Plan模式,前期会多花一部分探索成本,但总体验证下来往往更省。
| 对比维度 | 直接执行 | Plan模式 |
|---|---|---|
| 探索方式 | 边改边读,方向错了会重复读 | 前置集中探索,读一遍出计划 |
| 返工重写 | 常发生,每次回退都烧token | 计划被批准后极少返工 |
| 复杂任务总开销 | 跑偏一次约1.8-2.5倍 | 计划+执行,总账更省 |
| 代码库污染风险 | 高 | 极低 |
2.3 ExitPlanMode与计划审批的细节
计划里除了文件清单,模型通常还会列出它会运行的命令,比如跑测试、安装依赖。这些命令在批准后会被执行,所以审阅计划时不能只看改哪些文件,还要看它会跑什么命令。
如果计划太长,可以让模型压缩成“分阶段执行”:只批准第一阶段,完成后回来讨论再继续。在CLI里可以输入approve或deny,VSCode插件则是界面确认。这里没有太多玄学,但很多人没意识到deny加补充要求才是规划质量的关键。我经常把一版计划deny掉三次,每一次都补充新的约束,最后产出的方案和第一版完全是两个水平。
3. 实战拆解:用Plan模式规划一次多文件重构
3.1 任务描述怎么写,决定计划质量
我拿一个非常典型的场景举例:一个Express内容管理API,读多写少,响应偏慢,要加Redis缓存层。假设项目里没有自动化测试,只有Postman冒烟。
我一般会这样描述任务:
目标:给这个Express项目增加Redis缓存层。先不要改代码,只做规划。 背景:目前GET /posts/:id和GET /posts的响应平均在300ms左右,数据库是MongoDB,接口读多写少。 约束:不能改动现有客户端的请求参数和响应结构;缓存失效不能影响数据一致性;要用环境变量控制缓存开关。 验收标准:计划里必须包含缓存键设计、TTL建议、失效策略、需要修改的文件清单、测试方案。
这里有几个关键点:写清楚“先不要改代码”是保险;给背景是让模型知道现状;给约束是划定红线;给验收清单是让计划逐项覆盖你的关注点。
模型读完代码后生成的计划,通常会长这样:建议在数据访问层做缓存,因为多个路由会复用底层方法,比在路由层做更通用;缓存键设计为posts:{id}、posts:list:{page};TTL建议列表接口30秒、详情接口60秒;失效策略是写操作后主动删除对应键,TTL兜底;修改文件清单5个核心文件,外加一个新增的cache模块;测试方案是先跑现有冒烟,再针对缓存命中与失效写脚本。
3.2 进阶技巧:让Plan模式做方案对比
Plan模式的规划能力,在开放式问题上特别好用。我会在任务描述里多写一句:“请给出两到三个候选方案,并对比优缺点,最后推荐一个。”
比如缓存层放在数据访问层、路由层还是中间件层,模型会分别给出耦合度、改造成本、测试难度。你作为架构师做选择题,而不是做填空题。这一步能让规划从“它替我决定”变成“它给我决策依据”,沟通价值完全不一样。
3.3 审阅计划的四个必盯位置
第一,冷门调用方。模型很容易只盯着主要入口,但项目里往往有定时器、队列、后台任务也在读写同一些数据。如果计划里没有涉及这些异步路径的缓存失效,批准执行后会出现“缓存不失效”的数据不一致。
第二,缓存一致性的表述。计划不能只写“写操作后删除缓存”,要写清楚哪些写操作、在哪个函数里删除、删除失败怎么办。表述越具体,执行阶段越不会跑偏。
第三,公共层污染。模型很容易把缓存逻辑塞进公共工具类,表面上是复用,实际是给所有模块加了隐式依赖。审阅时要问:这个是业务通用能力,还是该接口的特有能力?
第四,可回滚性。计划里是否包含环境变量总开关。如果没有,加上再批准。
如果你发现任何一条不满足,最省事的做法不是自己改计划,而是deny掉,把你发现的问题写清楚,让模型带着反馈重新规划。这一来一回看着多花了几分钟,实际上是把坑填在执行之前。
3.4 批准后的执行与diff验证
批准后模型进入执行。我的做法是不一次性批准全部执行,而是让它按阶段来。例如先加缓存模块和配置,再改详情接口,跑通后,再改列表接口。
每完成一个阶段,立刻git diff。主要看实际改动和计划清单是否一致,有没有模型“自作主张”加的东西。如果diff里出现计划外的改动,第一时间停下来问它为什么。大多数情况是把执行中的小优化当成了顺手的事,但这种“顺手”往往就是后面出事的源头。
这整套流程下来,AI的角色从“独立开发者”变成了“按审阅过的方案施工的工程师”,你的角色从“写代码的人”变成了“评审人”。对复杂任务来说,后者才是安全且高效的协作方式。
4. Plan模式的边界:不是所有任务都值得开Plan
4.1 简单任务直接执行,Plan是多余动作
改个文案、加一行日志、修一个琐碎的类型错误,这些任务的目标和路径都清晰,Plan模式引入的额外轮次只是徒增等待。我见过有人开着Plan模式让AI改一个函数名,模型先读半天文件再输出一个八行计划,纯属多此一举。
我的经验法则是:凡是改动范围可能超过3个文件、或涉及设计取舍(缓存、状态、权限、接口契约)的任务,再开Plan。判断标准不是任务描述有多长,而是“这个任务是否有不止一个合理的实现路径”。如果有多个路径,就需要前置规划和方案对比;如果路径是唯一的,直接执行更快。
4.2 探索型任务用普通模式反而更好
Plan模式面向的是“要产生变更”的任务。如果你只是想知道“这段代码里有一个隐藏的幂等性问题吗”“这个bug最可能在哪一层”,那是探索,不是施工。普通模式下让模型读代码然后给结论,链路更短更直接。这时候让模型走Plan,反而会看到一份过度形式化的计划书,信息密度低,浪费时间。
4.3 计划的附加价值:当成评审文档用
Plan模式还有一个容易忽略的用法:计划本身可以作为人和人之间沟通的中间物。我现在项目里遇到需要技术评审的需求,会把Claude Code切到Plan模式,让模型先产出一份结构化的变更计划,然后我拿这份计划去当评审底稿。因为模型在计划里会把文件依赖、风险点列得比较规整,哪怕最后实现不是它做的,这份计划也省掉了大量从零写文档的工作。
有时候我把计划贴在团队的PR描述里,同事看完直接就能评论“漏了一个缓存删除点”,比让所有人从头读代码快得多。
5. 接入第三方模型时,Plan模式的稳定性与取舍
5.1 第三方模型怎么跑进Claude Code
这个话题被问得很多。Claude Code默认走Anthropic自己的模型和端点,但配置上支持把模型请求指向其他兼容端点。常见做法是配置环境变量,指定base URL和模型名,或者通过cc-switch这类工具在多个API配置之间快速切换,把DeepSeek、Qwen、GLM这些模型映射进来。本地部署场景则可以把LMStudio、Ollama这类工具的本地服务端点接到Claude Code上。
有一点必须先说清楚:Plan模式是Claude Code这个客户端工具层面的能力,它负责禁写、要求结构化计划、审批后才执行。所以第三方模型能不能无缝使用Plan模式,核心取决于该模型对工具调用(tool calling)的支持程度和稳定性,而不是取决于Plan模式本身。
5.2 不同模型在Plan模式下的表现差异
我实测下来的感受是,参数规模够大、工具调用训练得好的模型,走Plan会话基本没问题。它们能接住“只读探索—提交计划”的流程,只是规划深度和对仓库状态的敏感度一般弱于Claude系列。
工具调用不稳定的小模型,常见毛病是:让它规划,它越说越兴奋,又开始输出代码片段甚至尝试改文件;或者在探索中途把文件内容搞混,输出一份“名不符实”的计划。本地小模型还有一个现实问题:上下文窗口有限,而Plan模式要探索多个文件,探索一多,它就记不住关键依赖了。最后给你的计划可能是一个看起来很完整、实际漏了一堆冷门依赖的空架子。
所以我的建议很直白:如果你用的是第三方模型,复杂任务更要主动收窄探索范围。别让模型自己漫无目的地全仓库考古,而是在任务描述里把关键文件标出来,或者用@文件名直接把核心依赖喂进去。
5.3 用Plan模式管理有限上下文
Plan模式在第三方模型和本地模型场景下还有一个隐藏价值:上下文预算管理。直接执行一个大重构,模型每翻一次车,上下文里就堆进大量重复读取和错误代码;大模型上下文一旦接近上限,后面的行为会显著变笨。Plan模式因为先集中探索、出计划、再按计划执行,上下文里留下的杂质少,等于给有限上下文加了保护。
另外一个实操注意点:本地模型的推理速度慢,Plan模式的探索阶段会反复读取文件,等待时间可能让你怀疑它卡死了。把探索范围收窄之后,这个体验会有质的改善。如果实在慢,就退而求其次:让它在少量核心文件上做规划,然后你手动补详细设计。
6. 在VSCode里搭一套Plan模式工作流
6.1 环境与插件准备
VSCode接入Claude Code的常规路径是装官方插件,或者在集成终端里用CLI版本。插件面板里有模式切换入口,和CLI里的模式切换是等效的。settings.json里可以配置一些项目级选项,比如权限、界面展示细节等;如果你在接第三方模型,模型端点相关配置也可以看这里。基本逻辑是先把Claude Code跑起来,再让Plan模式成为你的默认习惯。
6.2 我推荐的日常Plan工作流
我现在处理中型以上任务的标准流程是这样的:
- 新建git分支,确保随时能回滚。
- 在聊天窗粘贴需求上下文,开头注明“先规划,不要改代码”,并附上约束。
- 切到Plan模式,等模型输出计划。
- 把计划里的文件清单、命令列表、风险点做成一个checklist,逐步核对。
- 批准执行,但每完成一批文件就git diff一次。
- 全部完成后跑全量测试,并检查有没有计划外改动。
- 把计划文件存一份到docs目录,后面写技术评审文档时直接用。
这套流程看起来步骤多,但因为每步都很轻,反而是所有模式里翻车成本最低的。我用下来的体感是,它的重点不是“让AI更聪明”,而是“让AI的错误更廉价”。
6.3 几个容易踩的坑
第一个坑:批准计划后忘了确认是否真的进入了执行模式。我遇到过一次:模型输出完计划,界面显示等待批准,我批准后就去忙别的,回来发现它其实还在Plan模式下把计划又复述了一遍,什么代码都没改。从那以后,批准后我会盯着它开始改第一个文件才离开。
第二个坑:计划太长被截断。任务过于庞大时,模型输出上限或者上下文限制会让计划不完整。这时候别硬撑,把任务拆成两三个子Plan,一个阶段一个阶段来。
第三个坑:计划里带了不该自动执行的命令。有些模型的计划会包含“运行数据库迁移”或者“自动安装依赖”,批准执行后就真的跑了。审阅计划时一定要看它列出的命令清单,不该自动执行的命令要么删掉,要么改成你手动跑。
我个人现在的习惯是:只要是涉及多个文件的改动,不管任务大小,先切Plan模式花三分钟要一份计划,这已经成了肌肉记忆。开Plan不是为了把流程变重,而是把风险前置到最便宜的时候——改文档比改代码便宜,改计划比改实现便宜,改实现比上线后回滚便宜。另外,每次看到模型输出一份结构漂亮的计划时,别急着夸它,先拿前面那四个必盯位置去审一遍,审过的计划才是真的计划。