Claude Code 学习站

计划模式与权限控制

先让 Claude 只读研究、产出计划,你批准后再动手;再用六种权限模式和 allow/ask/deny 规则把每一步操作管起来。

痛点:Claude 直接乱改一通

你说"把登录模块迁到 JWT",Claude 立刻开始改文件。等你反应过来,十几个文件已经被动过,方向还跟你想的不一样 —— 现在你得一个个 git diff 看它干了什么,再决定 revert 哪些。

问题不在 Claude,而在你没机会在它动手前喊停。两件事能解决:

  1. 计划模式(plan mode):让 Claude 先只读研究、产出一份计划,你批准后再动手。
  2. 权限控制:用模式 + allow/ask/deny 规则,精确决定"哪些操作自动放行、哪些必须问你、哪些直接禁止"。

进入计划模式

计划模式下 Claude 会读文件、跑探索性 shell 命令、写出一份计划,但不修改任何源文件,直到你批准。三种进入方式:

# 启动时就进 plan mode
claude --permission-mode plan

会话中临时切换,按 Shift+Tab 循环:

default  →  acceptEdits  →  plan

切进去后状态栏会显示当前模式。再按一次 Shift+Tab 可以在不批准计划的情况下直接退出。

只想让单条提示走计划模式,用 /plan 前缀:

> /plan 把 src/auth 从 session cookie 迁到 JWT

注意:plan mode 不是"只读 shell"。它的权限行为跟 default 一样 —— Claude 仍可运行 shell 命令探索代码,这些命令照样受权限提示约束。它只是不写源文件


看计划 → 批准 → 切到执行模式

计划写好后,Claude 把计划呈现给你,并问你怎么继续。批准对话框里的选项决定批准后切到哪个执行模式:

| 选项 | 批准后切换到 | | --- | --- | | Approve and start in auto mode | auto 模式 | | Approve and accept edits | acceptEdits 模式 | | Approve and review each edit manually | default 模式 | | Keep planning with feedback | 留在 plan mode 继续迭代 |

典型流程:

> /plan 给 NotificationService 补齐边界条件的测试
 
  [Claude 读完相关文件,输出一份计划:
   1. 在 notification.test.ts 新增 5 个用例
   2. 覆盖空收件人 / 超长正文 / 重复发送
   3. 复用现有 mock,不引入新依赖]
 
  ? 如何继续?
  > Approve and review each edit manually

选 "review each edit manually" 后会话切回 default,Claude 开始按计划改,每个编辑你都过一遍。想再次计划,重新用 /plan 或按 Shift+Tab 切回。

小技巧:呈现计划时按 Ctrl+G 可以在你默认的文本编辑器里直接打开并修改计划,再交还给 Claude 执行。


六种权限模式怎么选

权限模式决定"哪些操作不用问你就能跑"。一共六种:

| 模式 | 无需确认就能跑 | 适合 | | --- | --- | --- | | default | 只读 | 起步、敏感改动 | | acceptEdits | 读 + 文件编辑 + 常见文件系统命令(mkdir/mv/cp 等) | 一边写一边 review | | plan | 只读 | 改之前先摸清代码库 | | auto | 几乎全部,带后台安全检查 | 长任务、减少打断 | | dontAsk | 仅预批准的工具 | 锁死的 CI / 脚本 | | bypassPermissions | 全部 | 仅限隔离容器 / VM |

几条选择经验:

  • 日常就用 default,需要连续改多个文件、你会事后看 diff 时切 acceptEdits
  • dontAsk自动拒绝一切未预批准的工具(连 ask 规则都直接拒),适合无人值守的 CI。
  • bypassPermissions 外,所有模式都不会自动放行对受保护路径(.git.claude 等)的写入。

切换方式回顾:Shift+Tab 循环(只在 default/acceptEdits/plan 间)、--permission-mode <mode> 启动参数、或写进 settings 的 defaultMode:

{
  "permissions": {
    "defaultMode": "acceptEdits"
  }
}

auto 不在 Shift+Tab 默认循环里,且把 defaultMode: "auto" 写进项目级 .claude/settings.json 会被忽略(防止仓库给自己授权);要让它成默认,得写进用户级 ~/.claude/settings.jsonplan 没有这个限制,项目级写 defaultMode: "plan" 完全有效。


用 allow/ask/deny 规则让弹窗消失

模式定基线,规则做精调。在 settings.json 的 permissions 里写三个列表:

{
  "permissions": {
    "allow": [
      "Bash(npm run test:*)",
      "Bash(git commit:*)",
      "Read(src/**)"
    ],
    "ask": [
      "Bash(git push:*)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Read(./.env)"
    ]
  }
}
  • allow:匹配的调用直接放行,不再弹窗 —— 这是消灭"每次都问 npm test 行不行"的正解。
  • ask:即使在宽松模式下也强制弹一次确认。
  • deny:始终拦截,任何模式都不放行。

规则的评估顺序是固定的:

deny  →  ask  →  allow

第一个匹配的规则说了算,粒度不影响优先级。所以 ask: ["Bash"] 配上 allow: ["Bash(npm test)"] 时,npm test 仍会弹窗 —— 因为 ask 先命中。要避免,就把 ask 也写成带 specifier 的精确形式。

不想手写 JSON?在会话里输入 /permissions 打开交互面板,增删规则、查看每条规则来自哪个 settings 文件,改完即时生效。

路径语法坑:Read(*.env) / Read(./.env) 这种相对写法是相对当前目录(cwd);只有单斜杠 Edit(/src/**/*.ts) 才相对项目根目录;真要写文件系统绝对路径得用双斜杠 Read(//etc/**)。三种锚点别混。


沙箱里放手跑

想让 Claude 在长任务里少打断你,但又不敢用 bypassPermissions?两条路:

一是 auto 模式 —— 几乎不弹窗:只读操作和工作目录内的文件编辑会被直接放行,其余动作才交给一个独立的分类器模型做安全检查,拦截"超出你请求范围""打到陌生基础设施""被恶意内容驱动"的操作(受保护路径的写入即便有 allow 规则也会走分类器)。比 bypassPermissions 安全得多:

claude --permission-mode auto

你在对话里立的边界也算数 —— 说一句"先别 push,等我 review",分类器就会拦住匹配的动作,直到你后面解除。

二是用 sandbox 跑 Bash —— 把命令关进文件系统 / 网络隔离的沙箱里,即使放手跑也伤不到宿主。沙箱由会话内的 /sandbox 面板开启(配置写进 .claude/settings.local.json)。它独立于权限模式工作:沙箱内的受限操作可被自动放行,/sandbox 本身不是一种 permission mode,也不靠 defaultMode 调节。

底线:bypassPermissions 跳过几乎所有检查和受保护路径写入,只在没有外网的容器 / VM / dev container里用。它对 prompt injection 毫无防护;想"少弹窗"请优先选 auto,而不是 bypass。


回到 示例列表 →