权限引擎决定每个 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 |
plan | Plan 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() 实现