细粒度权限
第三章讲了四种权限模式,是宏观开关。这一节讲开关的下一层:具体到某个工具、某条命令、某个路径、某个域名。写好细粒度规则之后,你的 Claude Code 能自动放行
git status,但仍然会拦下git push --force。
为什么要细化
default 模式下 Claude 每动一次工具都要问你,很烦。bypassPermissions 又太放任,一个 rm 错了没人拦。真正实用的是介于两者之间的做法:把"肯定安全"的事情写进 allow list 自动放行,把"肯定危险"的事情写进 deny list 直接拒绝,剩下的模糊地带才走人工审批。这样每天需要人干预的次数会从几十次掉到个位数。
Claude Code 的权限规则支持四种粒度,从粗到细依次是工具、命令、路径、域名。你完全可以在一个 settings.json 里混用。
工具粒度
最粗的一层,直接按工具名放行或拒绝。
{
"permissions": {
"allow": [
"Read(**)",
"Grep(**)",
"Glob(**)"
]
}
}2
3
4
5
6
7
8
9
上面这段的意思是 Read、Grep、Glob 三种只读工具在任何路径都自动放行。这三类是读操作,风险接近零,放开之后 Claude 探索项目会顺畅很多,不必每次读一个文件都问你。
如果你想让 Edit 也自动放行,那就用 Edit(**)。括号里的部分是路径 pattern,** 表示任意路径。
路径粒度
只让 Claude 自动编辑某些目录,其他目录仍然需要问。
{
"permissions": {
"allow": [
"Edit(src/**)",
"Edit(tests/**)",
"Write(scratch/**)"
]
}
}2
3
4
5
6
7
8
9
src/** 匹配 src 目录下任意深度的文件,包括 src/index.ts 也包括 src/routes/users/handler.ts。Write 只让写到 scratch/**,是因为草稿目录反正会被 gitignore,写坏了没事,但根目录下的关键文件必须走审批。
路径 pattern 遵循标准 glob 语法:* 单层通配、** 任意层通配、? 单字符通配,可以在同一条规则里组合使用。
命令粒度
Bash 是最容易出事的工具,也是最需要细化的一类。命令粒度的规则用 Bash(<prefix>:*) 语法。
{
"permissions": {
"allow": [
"Bash(git status:*)",
"Bash(git diff:*)",
"Bash(git log:*)",
"Bash(git branch:*)",
"Bash(npm test:*)",
"Bash(pnpm test:*)",
"Bash(pnpm exec tsc --noEmit:*)"
],
"deny": [
"Bash(git push --force:*)",
"Bash(git push -f:*)",
"Bash(git reset --hard:*)",
"Bash(rm -rf:*)"
]
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
冒号加星号是必须的,表示这条规则匹配以该前缀开头的所有 Bash 命令。Bash(git status:*) 会放行 git status、git status --short、git status -uno 等所有变体,但不会放行 git statusfoo(因为要求以完整词组作为前缀)。
deny 优先级高于 allow。哪怕你写了 Bash(git push:*) 放行 push,只要 deny 列表里有 Bash(git push --force:*),force push 依然会被拒绝。团队共享的 settings 里,deny 列表是最重要的资产,写得越具体越安全。
域名粒度
WebFetch 工具用得多的团队还要控制外网访问。
{
"permissions": {
"allow": [
"WebFetch(https://docs.claude.com/**)",
"WebFetch(https://github.com/**)",
"WebFetch(https://*.mycompany.internal/**)"
],
"deny": [
"WebFetch(http://**)"
]
}
}2
3
4
5
6
7
8
9
10
11
12
这段配置放行了官方文档、GitHub、公司内网所有子域名,同时拒绝一切明文 HTTP。域名 pattern 里的 * 只匹配单一子域段,** 匹配路径任意深度。
additionalDirectories
Claude Code 默认只能访问工作目录及其子目录。有时候你需要它读工作目录以外的文件,比如另一个仓库的 schema、或者一份放在家目录下的私有配置。
{
"permissions": {
"additionalDirectories": [
"../shared-schema",
"~/.config/mytool"
]
}
}2
3
4
5
6
7
8
配置之后 Claude 能读这些目录的文件,允许列表里那些 Read、Edit 规则也会作用到它们。这个字段是"让工作目录变大",不是"绕过权限",具体的 allow/deny 规则依然要写。
别把家目录整个加进来
additionalDirectories 加一整个 ~ 意味着 Claude 能看到你所有的私人文件。加你真的需要的具体子目录,别偷懒。
Deny 列表:把敏感文件锁死
有些文件即使在 allow 模式下也绝对不能碰。敏感文件的显式 deny 是防御的最后一道墙。
{
"permissions": {
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(**/credentials.json)",
"Read(**/secrets/**)",
"Read(**/*.pem)",
"Read(**/*.key)",
"Edit(.env)",
"Edit(.env.*)"
]
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
Read 拒绝之后 Claude 连内容都看不到,不会出现在上下文里,不会被误发到聊天记录里。Edit 拒绝防止 Claude 误改凭证文件。哪怕未来某天你手滑开了 bypassPermissions,deny 依然会挡住这些路径。
MCP 工具权限
第六章会详细讲 MCP。这里先说权限层怎么写。MCP 提供的工具名格式是 mcp__<server-name>__<tool-name>,写规则时用同样的完整名字。
{
"permissions": {
"allow": [
"mcp__lark-doc__read_docx",
"mcp__lark-sheets__read_range"
],
"deny": [
"mcp__lark-doc__delete_docx",
"mcp__lark-drive__delete_file"
]
}
}2
3
4
5
6
7
8
9
10
11
12
只读的 MCP 工具通常都可以放行,写和删这类破坏性操作留给审批。命名规范里 __ 是双下划线,容易看错,配置时复制粘贴不要手打。
完整示例:团队共享 settings.json
把上面全部粒度串起来,一份可以直接进 git 的团队配置长这样。
{
"permissions": {
"additionalDirectories": [
"../shared-schema"
],
"allow": [
"Read(**)",
"Grep(**)",
"Glob(**)",
"Edit(src/**)",
"Edit(tests/**)",
"Write(scratch/**)",
"Bash(git status:*)",
"Bash(git diff:*)",
"Bash(git log:*)",
"Bash(git branch:*)",
"Bash(pnpm test:*)",
"Bash(pnpm exec tsc --noEmit:*)",
"Bash(pnpm exec prettier --write:*)",
"WebFetch(https://docs.claude.com/**)",
"WebFetch(https://github.com/**)",
"mcp__lark-doc__read_docx"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(**/credentials.json)",
"Read(**/secrets/**)",
"Read(**/*.pem)",
"Edit(.env)",
"Edit(.env.*)",
"Bash(git push --force:*)",
"Bash(git push -f:*)",
"Bash(git reset --hard:*)",
"Bash(rm -rf:*)",
"WebFetch(http://**)",
"mcp__lark-doc__delete_docx"
]
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
这份 settings.json 放到 ./.claude/settings.json 提交到仓库,团队里任何人 clone 之后开 Claude Code 都是同一套规则。个人偏好放到 ./.claude/settings.local.json(gitignore 掉),互不干扰。
从紧到松,一次只加一条
不建议一上来就把所有 allow 一口气都开。先从 Read、Grep、Glob 开起,跑一周看看哪几类 Bash 命令你每天都在按同意,把那几条加进 allow。这样加出来的规则贴近你真实的使用习惯,也不容易漏掉重要的 deny。
deny 是防线,不是唯一防线
bypassPermissions 模式会绕过 allow 但仍然遵守 deny。不过 deny 只挡了显式列出的路径,能列的都是你已经想到的。真正的安全依赖多层组合:deny 列表挡已知敏感文件,Hooks 拦已知危险命令,人工审批处理未知情况,三者缺一不可。