AI 编程教程中文版
从原理到实战

11 · 该给 AI 多少权限

Claude Code 权限不是安全感按钮,而是把读、写、运行命令、联网和成本拆成不同信任层级。学会用六种模式、Allow/Ask/Deny、沙盒和预算边界。

权限不是让 Claude Code 变弱,而是让它在正确的地方自动做事,在危险的地方停下来问你。真正的问题不是“给不给权限”,而是“什么操作值得信任,什么操作必须留给人判断”。——翔宇

这一篇用 15 分钟换什么:第 10 篇讲 Hooks,让 Claude Code 到点自动检查。第 11 篇讲 Permissions:当 Claude Code 想读文件、改文件、跑命令、联网、调用 MCP 工具时,哪些可以自动放行,哪些必须询问,哪些应该永远拒绝。

1. 从一个 git push 开始

你让 Claude Code 修一个小 bug。

它读了几份文件,改了一行逻辑,跑了测试,最后准备执行:

git push origin main

这时弹窗出现了。

很多新手第一反应是烦:刚才都让你修了,为什么还问?

但换一个角度看,这个弹窗正是权限系统最有价值的地方。读文件不会改变世界;改文件能回滚;跑测试通常安全;直接推到远程分支,影响就变大了。

第一性原理:权限系统不是在判断 Claude Code 聪不聪明,而是在判断某个动作一旦发生,代价由谁承担。

Claude Code 官方 Permission modes 文档说得很直接:当 Claude 想编辑文件、运行 shell 命令或发起网络请求时,会暂停并请求批准;permission mode 决定这种暂停出现得有多频繁。

所以权限不是“限制 AI”,而是把动作按风险分层。

flowchart LR
    Read["读文件<br/>低风险"]
    Edit["改文件<br/>可审查"]
    Bash["跑命令<br/>看命令"]
    Network["联网 / MCP<br/>看目标"]
    Remote["推送 / 部署 / 删除<br/>高影响"]

    Read --> Edit --> Bash --> Network --> Remote

    style Read fill:#dcfce7,stroke:#22c55e,stroke-width:2px
    style Edit fill:#e0f2fe,stroke:#0284c7,stroke-width:2px
    style Bash fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
    style Network fill:#ffedd5,stroke:#f97316,stroke-width:2px
    style Remote fill:#fee2e2,stroke:#ef4444,stroke-width:2px

2. 先分清三层边界

很多人把 Claude Code 的安全能力混成一团:权限、沙盒、Hooks、CLAUDE.md 都往一个篮子里放。

先拆开:

管什么典型问题
CLAUDE.md让 Claude 知道你希望怎么做“这个项目用 pnpm,不用 npm”
Hooks某个事件点必须自动检查“写 .env 前拦住”
Permissions某个工具调用能不能发生“能不能运行 git push?”
SandboxBash 进程能碰到哪里“命令就算跑了,能不能读 SSH key?”

一句话:

  • CLAUDE.md 是说明书。
  • Hooks 是检查点。
  • Permissions 是访问边界。
  • Sandbox 是操作系统围栏。

新手判断法:如果问题是“Claude 应该记住什么”,写 CLAUDE.md;如果问题是“到点必须查什么”,用 Hook;如果问题是“这个工具能不能用”,配 Permission;如果问题是“命令即使跑起来也不能越界”,开 Sandbox。

3. 六种权限模式,不是越松越好

Claude Code 当前有六种 permission mode。旧教程里常说“五种”,现在已经不够了,因为官方把 auto 模式单独放进了权限模式体系。

模式不问你就能做什么适合什么
default读文件新手上手、敏感项目
acceptEdits读文件、改工作目录内文件、常见文件命令你愿意事后看 diff
plan读文件、探索、提出方案,不直接改源码多文件任务、先审方案
auto大多数操作自动执行,但经过后台安全分类器长任务、减少确认疲劳
dontAsk只允许预先批准的工具和只读 BashCI、脚本、锁死环境
bypassPermissions基本全部放行只限隔离容器 / VM

最容易误解的是这三个:

acceptEdits 不是全自动。

它主要是自动接受文件编辑和一些常见文件系统命令,比如 mkdirtouchmvcpsed。但作用范围仍然受 working directory、additionalDirectories 和 protected paths 约束。

plan 不是“不能看代码”。

它正适合看代码。Claude Code 可以先读文件、跑探索命令、写计划,然后让你选择怎么执行。多文件改动、陌生仓库、生产风险高的任务,先用 plan 往往更省时间。

bypassPermissions 不是高手模式。

它跳过权限提示和安全检查。官方明确建议只在隔离环境里用,比如容器、VM、无互联网访问的 dev container。不要在你的日常开发机上把它当省事开关。

最危险的误解bypassPermissions 不是“我很信任 Claude”。它是“这个环境坏了也无所谓”。如果环境不是一次性的,就不要把它当默认工作模式。

切换方式也别记错:

claude --permission-mode plan
claude --permission-mode acceptEdits
claude --permission-mode dontAsk
claude --permission-mode bypassPermissions

CLI 里 Shift+Tab 默认循环 defaultacceptEditsplandontAsk 不在循环里;autobypassPermissions 只有满足条件或用启用参数启动后才会出现。

4. auto 模式:减少弹窗,不等于没有风险

auto 是这篇必须单独讲的新模式。

它的目标不是"全部放开",而是让 Claude Code 少问你,同时让后台 classifier(安全分类器)检查动作是不是超出了你的请求、是不是碰了不认识的基础设施、是不是像被恶意内容带偏。

classifier 怎么"判":底层是 Anthropic 训练的一个专用安全分类模型——每次 Claude 决定动手前,把"动作 + 当前上下文"送给 classifier 二次判断。它不是规则引擎(写死哪些命令禁止),是模型(看动作语义和当前任务的相关性)。为什么这样设计:规则引擎覆盖不了"组合危险"——rm -rf + 当前在 / 是危险,但在临时目录是正常;规则引擎只看命令字符串两者一样,模型能看上下文区分。代价:classifier 本身要花推理时间 + token——这是 auto 模式跟 bypassPermissions 在体感上"似乎都没弹窗" 但底层完全不同的原因。

官方当前文档列了几个关键边界:

官方当前文档列了几个关键边界:

  • 状态:research preview,不保证绝对安全。
  • 账号:不是所有计划都可用,Pro 不可用。
  • 模型 / 供应商:有模型和 Anthropic API 条件限制。
  • 默认信任:工作目录、本仓库 remote、只读 HTTP、声明依赖安装等更容易放行。
  • 默认阻止:curl | bash、外发敏感数据、生产部署、云存储批量删除、IAM / repo 权限变更、force push 等。
  • 会话边界:你在对话里说“不要 push”,classifier 会把它当阻止信号。

这就是 autobypassPermissions 的核心差别:

模式表面体验底层含义
auto少弹窗仍有后台安全判断
bypassPermissions不弹窗跳过权限层和安全检查

一句话理解:想减少弹窗,优先考虑 auto 或 sandbox;想完全跳过检查,只有一次性隔离环境才考虑 bypassPermissions

5. 细粒度规则:Allow / Ask / Deny

权限模式是“整体姿态”,规则才是“具体边界”。

官方 Permissions 文档把规则分成三类:

规则含义例子
allow自动允许,不弹窗Bash(npm test)
ask每次询问Bash(git push *)
deny直接拒绝Read(./.env)

顺序也很重要:denyaskallow。第一条匹配的规则生效,所以拒绝永远优先。

一个新手可直接照着改的配置:

{
  "permissions": {
    "defaultMode": "acceptEdits",
    "allow": [
      "Bash(npm test)",
      "Bash(npm run lint)",
      "Bash(git diff *)",
      "WebFetch(domain:docs.anthropic.com)"
    ],
    "ask": [
      "Bash(git push *)",
      "Bash(npm publish *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./secrets/**)",
      "Bash(rm -rf *)"
    ]
  }
}

这份配置表达的是:

  • 测试、lint、看 diff,可以自动做。
  • push、publish,必须问我。
  • .env、读 secrets、跑 rm -rf,直接拒绝。

不要写过宽的 allowBash(*) 看起来省事,实际是在把 shell 的风险整体交出去。能写窄,就写窄到具体命令。

新手最常见的两类配置失控

  1. 嫌弹窗烦直接 bypassPermissions:第一周用 Claude Code 觉得弹窗烦,改默认模式为 bypassPermissions——结果某天 Claude 在 ~/Documents 里跑了 rm -rf node_modules 但目录算错位置,删了真实数据。修复:日常 acceptEdits 而不是 bypassPermissions——前者编辑自动通过但 Bash / 网络仍受 ask 约束,后者是"全部跳过"。
  2. Bash(*) 当 allow:嫌每次确认烦,写 allow: ["Bash(*)"] 把所有 shell 命令都通过——等于 sudo all 给 Claude,连 rm -rf 都不弹。修复:allow 只列频繁 + 安全的具体命令(Bash(npm test) / Bash(git diff *) / Bash(ls *)),频繁但有风险的(git push)放 ask,永远不该的(rm -rf)放 deny。

6. Protected paths:有些地方默认更敏感

Claude Code 对一些路径有特殊保护,因为这些路径一旦被改坏,会影响仓库状态、编辑器配置或 Claude 自己的配置。

典型 protected paths 包括:

典型 protected paths 包括:

  • 仓库状态:.git.gitmodules
  • 编辑器 / Git hooks:.vscode.idea.husky
  • Claude 配置:.claude.claude.json.mcp.json
  • Shell 启动文件:.bashrc.zshrc.profile
  • 搜索配置:.ripgreprc

这里有一个容易过时的细节:官方当前说明是,除了 bypassPermissions 之外,protected paths 都不会被自动批准;在 defaultacceptEditsplan 里会询问,在 auto 里走 classifier,在 dontAsk 里拒绝。

bypassPermissions 从 v2.1.126 起也会放行 protected paths。只有类似 rm -rf /rm -rf ~ 这种指向根目录或 home 目录的删除,仍然会触发最后的断路保护。

这就是为什么旧经验不可靠:权限细节会随版本变。写教程时不能只靠印象,必须按当前官方文档核对。

7. Sandbox:权限之外再加一圈围栏

权限规则是在 Claude Code 层面判断“这个工具调用可不可以发生”。沙盒是在操作系统层面限制“这个 Bash 进程和它的子进程能碰到哪里”。

官方 Sandboxing 文档的关键点是:

两者的边界:

  • 作用对象:权限规则覆盖 Bash、Read、Edit、WebFetch、MCP 等所有工具;Sandbox 主要覆盖 Bash 和它启动的子进程。
  • 执行层级:权限规则在 Claude Code 应用层;Sandbox 在操作系统层。
  • 文件边界:权限规则用 Read / Edit / deny 等表达;Sandbox 限制进程读写路径。
  • 网络边界:权限规则里 WebFetch 管 domain;Sandbox 通过代理和域名 allow / deny 限制网络。
  • 典型价值:权限规则不让 Claude 尝试危险操作;Sandbox 让命令即使运行也不能越界。

在 macOS 上,沙盒使用 Seatbelt;Linux 和 WSL2 使用 bubblewrap。它不是 Claude 的“自觉”,而是系统级限制。

你可以在 Claude Code 里用:

/sandbox

打开沙盒菜单。默认思路是:当前工作目录内可以更自由,越出边界就提示或阻止。

实操策略:日常开发不要只靠权限弹窗。能开 sandbox 的场景就开 sandbox,再配少量 deny 规则,把弹窗留给真正高风险动作。

8. 成本也是一种边界

很多人讲权限只讲安全,不讲成本。

但对自动化 Agent 来说,成本边界和安全边界是一类问题:都是防止系统在无人盯着的时候跑出你能承受的范围。

官方 Costs 文档里,现在推荐用 /usage 看当前会话的 token 和估算成本。旧稿里常见的 /cost 说法不适合继续写进新教程。

日常你记这三类就够:

日常你记这三类就够:

  • 看当前用量:/usage
  • 降低思考成本:/effort/model/configMAX_THINKING_TOKENS
  • SDK 自动化限额:max_budget_usd / maxBudgetUsd

注意边界:

  • /usage 里的金额是本地估算,不一定等于最终账单。
  • Pro / Max 订阅用户看到的是订阅用量,不等同于 API 账单。
  • max_budget_usd / maxBudgetUsd 是 Agent SDK 里的预算参数,不要把它误写成所有 CLI 场景都有的通用开关。

一句话理解:权限防止 Claude Code 做错事,预算防止 Claude Code 做太久。两者都是边界设计。

9. 新手该怎么选

不用一开始就追求“最安全”或“最自动”。按项目风险选。

flowchart TD
    Start["这次任务风险高吗?"]
    Sensitive["会碰生产、密钥、部署、远程分支?"]
    Multi["会改很多文件或你不熟悉仓库?"]
    Review["你愿意事后看 diff 吗?"]
    CI["是不是无人值守脚本 / CI?"]
    Isolated["环境坏了也无所谓?"]

    Plan["用 plan 先审方案"]
    Default["用 default"]
    Accept["用 acceptEdits + 看 diff"]
    DontAsk["用 dontAsk + allowlist"]
    Bypass["隔离环境才用 bypassPermissions"]

    Start --> Sensitive
    Sensitive -->|是| Plan
    Sensitive -->|否| Multi
    Multi -->|是| Plan
    Multi -->|否| Review
    Review -->|是| Accept
    Review -->|否| Default
    CI --> DontAsk
    Isolated --> Bypass

    style Plan fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
    style Bypass fill:#fee2e2,stroke:#ef4444,stroke-width:2px

更具体一点:

更具体一点:

  • 第一次用 Claude Code:default
  • 熟悉项目、频繁小改:acceptEdits
  • 多文件重构 / 陌生仓库:plan 开始,审完再执行。
  • 想减少弹窗但还要安全检查:符合条件时用 auto
  • CI / 自动脚本:dontAsk + 明确 allowlist。
  • 一次性容器 / VM:必要时才用 bypassPermissions

反模式:不要因为弹窗烦,就直接开 bypassPermissions。正确顺序是:先收窄 allowlist,再考虑 sandbox,再考虑 auto,最后才是隔离环境里的 bypass。

10. 和 Hooks 放在一起看

第 10 篇讲 Hooks,这一篇讲 Permissions。两者经常一起用,但职责不同。

职责边界可以这样记:

  • “能不能运行 git push?”:Permission。
  • “每次写 .env 前必须拦住并解释原因”:Hook。
  • “如果测试输出太长,自动只保留失败信息”:Hook。
  • “任何 MCP 浏览器工具都不许点发布按钮”:Permission + Hook。
  • “只允许读取 docs,不允许读 secrets”:Permission。

官方 Permissions 文档也说明了这个关系:PreToolUse hook 会在权限提示前运行,hook 可以 deny、强制询问或跳过提示;但 hook 决策不能绕过 deny / ask 规则。匹配到 deny 的规则仍然会阻止调用。

flowchart LR
    Action["Claude 准备调用工具"]
    Hook["PreToolUse Hook<br/>运行自定义检查"]
    Rules["Permission Rules<br/>Deny / Ask / Allow"]
    Mode["Permission Mode<br/>default / auto / ..."]
    Run["工具执行"]
    Block["阻止或询问"]

    Action --> Hook --> Rules --> Mode
    Hook -->|blocking| Block
    Rules -->|deny / ask| Block
    Mode -->|允许| Run

    style Hook fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
    style Rules fill:#e0f2fe,stroke:#0284c7,stroke-width:2px
    style Block fill:#fee2e2,stroke:#ef4444,stroke-width:2px

一句话理解:Permission 负责“这类工具调用能不能过”;Hook 负责“过之前或过之后要不要做额外检查”。

11. 本章自检

试着用自己的话回答:

  1. 为什么权限弹窗不是"AI 不够强",而是"动作后果需要分层"?对应 §1-§2。
  2. acceptEditsautobypassPermissions 的差别是什么?对应 §3-§4。
  3. 为什么 deny 规则应该比 allow 规则更窄但更坚决?对应 §5。
  4. Sandbox 为什么只能补强 Bash 边界,不能替代所有 Permission?对应 §7。
  5. 动手题 ⭐:在你最常用的项目根 .claude/settings.json 写 3 条规则——1 条 allow(写一条你真的常用的命令,比如 Bash(pnpm test))、1 条 ask(写一条频繁但有风险的命令,比如 Bash(git push *))、1 条 deny(写一条永远不该自动执行的,比如 Read(./.env))。每条解释为什么放这一档。这一题做完你才会真懂"分层"不是道理,是配置文件。对应 §5 + §9。

过关标准:你能为一个真实项目写出三条规则:一个 allow、一个 ask、一个 deny,并能解释为什么这三条对应不同风险。

📖 本篇术语速查表
  • Permission:权限。Claude Code 工具调用能不能执行的规则体系。
  • Permission mode:权限模式。一次会话的整体批准策略。
  • default:默认模式。读文件自动,其他高风险动作询问。
  • acceptEdits:自动接受编辑。文件改动自动通过,适合事后看 diff。
  • plan:计划模式。先探索和出方案,不直接改源码。
  • auto:自动模式。少弹窗,但后台 classifier 做安全检查。
  • dontAsk:不询问模式。只执行预批准工具,其他自动拒绝。
  • bypassPermissions:跳过权限。跳过权限提示和安全检查,只适合隔离环境。
  • Allow:允许规则。匹配后自动通过。
  • Ask:询问规则。匹配后要求人工确认。
  • Deny:拒绝规则。匹配后直接阻止。
  • Sandbox:沙盒。对 Bash 进程做操作系统级文件和网络隔离。
  • Classifier:安全分类器。auto 模式下判断动作是否越界的后台模型。
  • Protected paths:受保护路径。.git.claude 等不应轻易自动修改的位置。

官方资料

接下来去哪

如果只记一个判断:权限不是越松越先进,也不是越严越安全;好的权限配置,是让低风险动作自动发生,让高影响动作必须经过你。

本页目录