权限引擎决定每个 tool 调用是否被允许、需要询问还是直接拒绝。

决策链

HasPermissionsToUseTool() 按以下优先级依次检查(对标 TypeScript permissions.ts):

1a. deny rule → deny(bypass-immune)
1b. ask rule → ask(bypass-immune)
1c. tool.CheckPermissions() → 返回 deny/ask/passthrough
    1d. 结果为 deny → deny
    1e. tool.RequiresUserInteraction() && ask → ask(bypass-immune)
    1f. 内容级 ask rule(来自 tool)→ ask(bypass-immune)
    1g. safety check ask(来自 tool)→ ask(bypass-immune)
2a. bypassPermissions 模式 → allow
2b. allow rule → allow
3.  默认 → ask

bypass-immune:即使在 bypassPermissions 模式下仍然需要询问(例如 safety check、用户配置的 ask rule)。

PermissionBehavior 枚举

值含义
allow直接允许
ask需要询问用户
deny拒绝
passthrough由 tool 自身决策(等同于继续向下走)

PermissionMode

模式说明
default遇到 ask 时提示用户
bypassPermissions跳过所有非 bypass-immune 的 ask
dontAsk遇到 ask → 自动 deny
planPlan mode:当 IsBypassPermissionsModeAvailable=true 时等价于 bypass

Headless agent(ShouldAvoidPermissionPrompts=true)遇到 ask 也自动 deny。

规则系统

配置的权限规则(settings.json 中的 permissions.allow/deny)格式:

{
  "permissions": {
    "allow": ["Bash(git commit:*)", "FileRead"],
    "deny": ["Bash(rm -rf:*)"]
  }
}

internal/permissions/parser.go 解析工具名和可选的内容匹配模式(括号内)。

internal/permissions/classifier.go 实现工具输入的内容匹配逻辑。

Safety Check

tool.CheckPermissions() 返回的 DecisionReason.Type = "safetyCheck" 表示安全检查告警(如写入 .git/、.claude/ 等保护目录),这类 ask 为 bypass-immune,即使在 bypass 模式下也不会自动允许。

相关页面

  • hooks — Hook 可在 PreToolUse 中覆盖权限决策
  • architecture — 权限检查在执行流中的位置
  • tools — tool.CheckPermissions() 实现