Claude Code 学习站

Plan mode 与权限

考点 3.4 · Plan mode & permissions · 所属域权重 20% · Claude Code 配置与工作流

本页目录5

这个考点是什么

3.4 考的是 Claude Code 在“改代码之前”这一层的两种控制机制:先想清楚再动手的 plan mode,以及决定“哪些操作要不要弹窗确认”的权限系统(六种 permission modes + settings.json 里的 allow/ask/deny 规则)。两者经常被放在一起考,因为它们都回答“Claude 现在能自主到什么程度”,但控制的维度不同——plan mode 管的是“写不写源文件”,权限系统管的是“执行前要不要问我”。

plan mode 进入后 Claude 只做研究:读文件、跑探索性 shell 命令、产出一份计划,源文件写入在批准计划前始终被挡住(bypassPermissions 场景例外)。

但要注意,plan mode 里的 shell 命令判定并不是简单套用 default 模式那套“非只读命令一律弹窗”的逻辑:

  • 当账号具备 auto mode 资格、且 useAutoModeDuringPlan 设置开启(官方文档标注默认就是开启)时,超出内置只读命令集合的 shell 调用会被交给 auto mode 的 classifier 自动审批或拒绝,不再走常规确认弹窗;

  • 只有在 auto mode 不可用的账号/场景下,才会退回到跟 default 模式一样的“非只读命令必须确认”流程。

批准计划后,Claude 按你选的选项切到 auto / acceptEdits(手动逐条审) 等执行模式继续干活。

权限系统则是六种模式(default/acceptEdits/plan/auto/dontAsk/bypassPermissions)定基线,settings.json 里的 allow/ask/deny 三个列表做精调,顺序固定是 deny→ask→allow,第一个匹配的规则说了算、粒度不影响优先级;这套规则在所有 settings 作用域间是合并而非覆盖,这跟大多数配置项“最高作用域覆盖低作用域”的逻辑不是一回事。

hooks(尤其 PreToolUse)是在这套规则之外再加一层可编程拦截,靠退出码把阻断决定传回 Claude。

为什么考

常见出题角度有三类:

  • 一是给定 allow/deny 规则组合,判断某条命令最终放不放行,考察 deny→ask→allow 的固定顺序、以及“规则跨作用域合并而非按最高作用域覆盖”是否被记混成普通配置项的覆盖逻辑;

  • 二是给一个开发场景,判断该用 plan mode 还是直接执行,考察能否分清“任务存在探索型不确定或架构决策”与“泛化的谨慎心态”这两种截然不同的理由;

  • 三是 hooks 退出码语义(exit 2 阻断、exit 1 不阻断)和“settings 整体优先级”与“权限规则合并”两套不同机制的混淆。

plan mode 与 default 模式在 shell 命令判定上是否等同,是容易被想当然简化的一个细节陷阱。

核心辨析

  1. 1

    plan mode 不是“全只读沙箱”,它对 shell 命令的判定路径其实和 default 模式不完全一样:

    • 当 auto mode 可用且 useAutoModeDuringPlan(默认开启)生效时,超出内置只读集合的命令交给 auto mode 的 classifier 自动审批或拦截,不走常规确认弹窗;

    • 只有 auto mode 不可用时才退化成和 default 一样的“非只读命令必须确认”。

    唯一在所有情况下都成立的是:批准计划前源文件写入始终被挡住(bypassPermissions 场景除外)。

  2. 2

    普通配置项(如 defaultMode)按 managed > 命令行参数 > local > project > user 逐级覆盖,最高作用域生效;但 permission 的 allow/ask/deny 列表是跨作用域合并成一份清单,再统一按 deny→ask→allow 顺序找第一个匹配规则——这是两套不同的机制,不要混用同一套“谁覆盖谁”的直觉。

  3. 3

    规则粒度不决定优先级

    allow 里写了精确的 Bash(aws s3 ls),deny 里写了宽泛的 Bash(aws *),结果仍是被拒——因为 deny 这个类别整体排在 allow 前面判定,而不是“更具体的规则赢”。

  4. 4

    hook 退出码不符合 Unix“非 0 即失败”的直觉

    PreToolUse 场景下只有 exit code 2 会真正阻断工具调用,并把 stderr 回传给 Claude 当拒绝理由;exit code 1 只是非阻断错误,动作照常继续执行。

  5. 5

    acceptEdits 不等于“全自动”

    它自动放行文件写入和 mkdir/touch/mv/cp 这类常见文件系统命令,但其他 Bash 命令(网络请求、非常见 CLI)仍要靠 --allowedToolspermissions.allow 显式放行,否则 headless 运行会直接中止。

  6. 6

    该不该用 plan mode 看任务是否需要探索型信息或架构级决策——多文件依赖不明确、服务边界待定的才该先 plan;需求和修法已经明确的单文件小改动直接执行即可,不要用“任何改动都可能出错”这种放之四海而皆准的理由去套。

反模式对照

常见做法

认为 plan mode 里的 shell 命令和 default 模式走同一套“非只读就弹窗”逻辑,区别只在于不能写文件

正确做法

plan mode 下超出内置只读集合的命令,在 auto mode 可用且 useAutoModeDuringPlan 开启时改由 classifier 自动审批或拦截;只有 auto mode 不可用才退化成和 default 一样的确认弹窗

两条路径判定机制不同,唯一恒定不变的只有“批准前不写源文件”这一条,不能把 shell 命令判定也简化成两者等同。

常见做法

以为规则更具体就能“开个口子”绕过范围更宽的 deny 规则

正确做法

deny 这一整个类别先于 allow 判定,想放行例外只能收窄 deny 的范围本身,或改用更精确的 deny specifier

allow Bash(aws s3 ls) + deny Bash(aws *) 的组合结果仍是拒绝,因为顺序是 deny→ask→allow,不是“最具体的规则赢”。

常见做法

把项目级 .claude/settings.json 里写的 defaultMode: "auto" 当作能对所有克隆者生效的团队默认

正确做法

要让 auto 成为默认模式,必须写进用户级(或 managed)settings;项目级/local 级配置对 auto 会被直接忽略

这是为了防止仓库通过提交配置文件就让所有人的 Claude 无提示放手跑;plan 模式写在项目级则完全有效,没有这层限制。

常见做法

认为任何改动都“可能出问题”,所以一律先进 plan mode 再动手

正确做法

只有任务需要探索代码库、权衡多个方案或做架构级决策时才用 plan mode;需求和修法已经明确的小改动直接执行

泛化的“谨慎”理由会让 plan mode 变成事事必用,失去筛选价值——区分点在于任务是否存在探索型不确定,而不是单纯有风险。

练这个考点