Plan 模式:带计划文件的逻辑隔离预演
在处理复杂的代码库重构或多步骤逻辑修改时,人类开发者往往会先打草稿。Claude Code 的 Plan 模式(计划模式)正是为了将这一行为标准化、工程化而设计的特殊运行状态。它是一套强制性的“思考-审批-执行”工作流,而非简单的“只读模式”。
一句话讲清楚
Plan 模式本质上是 推理能力与副作用操作的逻辑隔离层。
- 它不是什么:它不是简单的“只读浏览模式”。它要求模型在
plan.md中物化其思维链(Chain of Thought),并在进入实际修改阶段前向人类递交“施工图纸”。 - 它的核心理念:通过强迫模型将复杂目标分解为可审计的子任务,并在一个绝对安全的“逻辑沙箱”内完成所有的探索性读取工作。
实现机制
Plan 模式的驱动核心位于 claude-code-opensource/src/tools/EnterPlanModeTool/ 和 claude-code-opensource/src/utils/plans.ts:
1. 状态切换(State Transition)
当模型判定当前任务需要深度构思并调用 EnterPlanModeTool 时,AppState 中的 permissionMode 会被切换为 plan。这一切换会立即触发全局的权限短路。
2. 权限短路(The Logical Circuit Breaker)
在 plan 模式下,权限引擎 canUseTool(位于 claude-code-opensource/src/utils/permissions/permissions.ts)会应用最严格的过滤规则:
- 只读放行:允许所有的读取(
FileRead)、搜索(Grep/Glob)和上下文探知工具。 - 写操作拦截:任何试图修改文件(
FileWrite/Edit)或执行 Bash 命令的尝试都会被权限引擎预先拦截。模型会收到提示:“当前处于计划阶段,严禁执行修改,请先完善plan.md”。这种拦截甚至不经过用户询问,直接由系统在逻辑层执行“静默拒绝”。
3. 计划物化与思维对齐
系统会通过 src/utils/plans.ts 在当前工作区创建一个显式的 plan.md 文件。
- 实时同步:模型被鼓励(通过系统指令)在探索过程中不断回填和修正
plan.md。 - CoT 效应:将计划写入文件有两个目的:供用户审阅,同时让模型自己维持一个长期的任务状态栈,减少在复杂重构中的逻辑发散。
4. 受控退出(The Exit Handshake)
退出 Plan 模式是一个必须由模型显式发起或人类确认的“握手协议”。通过 ExitPlanModeTool,系统会:
- 最终审计:强制用户最后一次审阅
plan.md的内容。 - 环境对齐:询问用户是否需要将当前的计划内容合并到主对话流中,或者作为执行阶段的元数据保留。
- 权限复原:只有当握手完成后,
permissionMode才会恢复到default或用户指定的其他状态。
限制与陷阱
- 读写绝对性:在
plan模式下,连BashTool的只读命令(如ls)有时也会受限,如果该命令可能产生未预料的副作用,系统会倾向于保守地要求模型使用原生的 Node.js 读取工具。 - 非永久性文件:
plan.md通常是临时性的,其主要目的是驱动当前的推理流。如果你需要长期保留方案,应在退出前明确告知模型将其转录为正式的项目文档。 - 上下文继承:在 Plan 模式中读取的所有文件、搜索到的所有符号定义,在切换回执行模式后依然保留在模型的短期上下文(Transcript)中。这种无缝衔接保证了“想清楚”后能立即“写得准”。
- 手动干预优先级:如果用户在命令行中手动强制退出(如使用 Ctrl+C 或特定命令),系统会回退到上一个安全状态,但不保证
plan.md的最终一致性。
推荐阅读路径
- 如果你想了解 Claude 如何在没有人工干预的情况下自动判断安全性,请看 Auto Mode:基于分类器的自动化审批。
- 如果你关心权限引擎是如何实施这些拦截的,请看 权限与沙箱:双层防御体系。
- 如果你想了解如何配置启动时的默认模式,请看 设置优先级:managed 与 local 的权衡。
源码锚点
- claude-code-opensource/src/utils/permissions/PermissionMode.ts —
plan模式的状态枚举与全局配置定义。
📄 src/utils/permissions/PermissionMode.ts — `plan` 模式的状态枚举与全局配置定义。L52-58 of 142
typescript
plan: {
title: 'Plan Mode',
shortTitle: 'Plan',
symbol: PAUSE_ICON,
color: 'planMode',
external: 'plan',
},1
2
3
4
5
6
7
2
3
4
5
6
7
- claude-code-opensource/src/tools/EnterPlanModeTool/ — 进入计划模式的工具实现入口。
- claude-code-opensource/src/utils/plans.ts —
plan.md文件的生命周期管理(生成、读写、合并逻辑)。
📄 src/utils/plans.ts — `plan.md` 文件的生命周期管理(生成、读写、合并逻辑)。L25-49 of 398
typescript
const MAX_SLUG_RETRIES = 10
/**
* Get or generate a word slug for the current session's plan.
* The slug is generated lazily on first access and cached for the session.
* If a plan file with the generated slug already exists, retries up to 10 times.
*/
export function getPlanSlug(sessionId?: SessionId): string {
const id = sessionId ?? getSessionId()
const cache = getPlanSlugCache()
let slug = cache.get(id)
if (!slug) {
const plansDir = getPlansDirectory()
// Try to find a unique slug that doesn't conflict with existing files
for (let i = 0; i < MAX_SLUG_RETRIES; i++) {
slug = generateWordSlug()
const filePath = join(plansDir, `${slug}.md`)
if (!getFsImplementation().existsSync(filePath)) {
break
}
}
cache.set(id, slug!)
}
return slug!
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25