Claude Code 实战 01|装好之后的第一天:CLI 心智模型与权限体系原创
# Claude Code 实战 01|装好之后的第一天:CLI 心智模型与权限体系
把 Claude Code 当补全插件用,你会失望;把它当一个「有完整工具箱、会自己决定下一步」的终端 Agent 用,第一件要搞懂的事不是 prompt,而是它凭什么能碰你的文件和命令,以及你怎么把这条缰绳握在手里。
# 1. 一句「发布前先确认」为什么拦不住它
一个很常见的场景:你希望某个高危动作——比如 git push 到远端之前必须人工二次确认——于是把「push 前先确认」这句话写进上下文文件(CLAUDE.md),以为立了规矩。
结果它该 push 还是 push。
根因很朴素:为了少打断,很多人会开「自动允许权限」(auto-accept)。在这个模式下,Claude Code 不再为每个操作弹窗询问——而那句「铁律」只是自然语言,属于"软提示",会被自动模式直接跳过。用一句话去拦一个已经被授权自动执行的动作,等于没拦。
这件事把 Claude Code 的本质摊开了:它不是等你一句一句喂指令的工具,它是一个会连续决策、自己调用工具的 Agent。你能不能睡得着,取决于你对它的权限体系理解到什么程度。
# 2. 它和 Copilot 根本不是一类东西
先校准心智模型,否则后面的权限配置都是无的放矢。
| 补全式 Copilot | Claude Code | |
|---|---|---|
| 交互 | 你写,它补下一行 | 你说目标,它自己拆步骤 |
| 能力边界 | 只在编辑器里出文本 | 读写文件、跑 shell、搜代码、调外部工具 |
| 谁决定下一步 | 你 | 它(在你给的权限内) |
| 风险面 | 生成错代码 | 执行错命令 / push / 删文件 |
关键差别在最后一行:Copilot 的错误停留在"文本",Claude Code 的错误会落到磁盘和远端。所以它的价值和风险是同一枚硬币——能自己执行既是它比补全工具强十倍的地方,也是你必须先立护栏的原因。
它的工具箱大致是:Read/Write/Edit(文件)、Bash(命令)、Grep/Glob(搜索),以及通过 MCP 接入的外部工具(数据库、浏览器、私有 API——本系列后面单独讲)。每一类工具都可以被独立地允许、询问或禁止,这就是权限体系的抓手。
# 3. 三级权限:从"每次都问"到"底层硬拦"
Claude Code 的权限不是一个开关,而是三层,从松到紧、从"靠自觉"到"靠机制"。
# 3.1 默认模式:每个动作都问你
装好后什么都不配,就是这个状态:它每要执行一次 Bash、每要写一次文件,都会把命令摊给你看、等你按同意。新环境、碰生产、跑陌生仓库,就用这个。慢,但每一步都在你眼皮底下。
# 3.2 项目级 allow/deny:.claude/settings.json
每次都点同意太累。用项目配置把"哪些安全操作预授权、哪些永远禁止"固化下来:
{
"permissions": {
"allow": [
"Read(./docs/**)",
"Bash(npm run lint:*)",
"Bash(npm test:*)"
],
"deny": [
"Bash(git push:*)",
"Read(./.env)",
"Read(./**/.env)"
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
预期效果:读文档目录、跑 lint/测试脚本——放行不打断;git push 和读任何 .env——直接拒。
这里有两条关键原则:
- allow 要窄。给的是"具体脚本 + 参数模式",不是一整个
Bash(*)。一旦开了裸Bash,等于把整台机器交出去。 - deny 优先级最高。哪怕后面手滑把
Bash(*)加进 allow,deny 里的git push、.env依然拦得住。把不可逾越的红线写进 deny,而不是指望 allow 写得足够全。
# 3.3 自动模式 + Hook:当"问"这一步被跳过时
想更省心,可以开自动允许(auto-accept),预授权的操作不再弹窗。但——回到开头那个教训——一旦开了自动模式,任何"靠弹窗、靠自然语言提醒"的拦截都失效了。
这时唯一可靠的护栏是 PreToolUse Hook:在工具真正执行之前,用一个你自己写的脚本拦一道。它不是提示,是代码级的"准或不准"。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "python3 .claude/hooks/gate_push.py" }
]
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
gate_push.py 的逻辑:读到即将执行的命令,只要包含 git push,且命令里没有人工给出的"确认哨兵"(一个约定的确认词),就返回非零退出码,直接把这次工具调用拒掉。
#!/usr/bin/env python3
import json, sys
data = json.load(sys.stdin) # 钩子从 stdin 拿到工具调用详情
cmd = data.get("tool_input", {}).get("command", "")
if "git push" in cmd and "CONFIRM-PUSH" not in cmd:
print("拦截:push 前需人工确认(在指令中带上确认哨兵)", file=sys.stderr)
sys.exit(2) # 非零 → Claude Code 拒绝执行该工具
2
3
4
5
6
7
验证:开着自动模式让它 push,命令在落到远端之前就被 Hook 掐断,会话停下来等人工确认。这次,那条铁律终于有牙齿了。
# 4. 上手第一天最容易踩的三个坑
# 坑 1:以为"自然语言铁律"能当护栏
- 症状:CLAUDE.md 里写了"不许 push / 不许删库",它照做不误。
- 原因:自然语言指令在自动模式下是软提示,会被跳过;它也可能在长对话里"忘了"。
- 解药:红线一律下沉到机制层——
deny列表 + PreToolUse Hook。能用配置表达的约束,就别用一句话表达。
# 坑 2:把 Bash(*) 直接塞进 allow
- 症状:图省事放开全部命令,某次它自作主张跑了个有副作用的命令。
- 原因:裸
Bash等于系统级信任,工具级的细粒度权限形同虚设。 - 解药:allow 只写"具体命令 + 参数前缀"(如
Bash(python3 scripts/scan_leaks.py:*));宁可多点几次同意,也不开总开关。
# 坑 3:让它"自己试错"去修敏感凭证
- 症状:
.env里的某个 API Key 填错了位置,让它"想办法修好",它开始排列组合猜密钥。 - 原因:Agent 会把"修配置"理解成"试出能用的组合",而这恰恰是最危险的行为。
- 解药:Claude Code 本身有一层 凭证探测(Credential Exploration)安全策略会拦下这类猜测;而正确姿势是——让它只做"格式诊断"(告诉你哪个字段格式不对:这是 UUID、那是 Hex),由人工填正确值。凭证的最后一公里必须是人。
顺带一个延伸教训:工具级权限 ≠ 系统级隔离。就算你在 toolset 里没给它"终端"工具,只要它手里还有能跑代码的口子、机器上又躺着 SSH 密钥,它照样能绕过去。真正的隔离要落到执行环境(沙箱出站策略、密钥可见性),不能只靠"少给一个工具"。
# 5. 可复用要点
- 红线进机制,不进 prompt:不可逆的操作(push / 删除 / 改生产)用
deny+ PreToolUse Hook 兜底,别指望自然语言。 - allow 窄、deny 狠:allow 只放"具体命令",deny 写死红线且优先级最高。加宽 allow 时,deny 依然是最后一道墙。
- 权限模式和护栏要配套:一旦开自动允许,所有靠"问"的拦截全部失效,必须同步上 Hook。
- 凭证最后一公里留给人:Agent 只做格式诊断,不做试错修复;密钥永远由你确认。
- 工具级权限不是隔离:真隔离靠执行环境(沙箱、密钥可见性、出站策略)。
# 6. Agent 可直接解析的元数据块
{
"_meta": {
"doc_version": "2026-07-28",
"article_id": "claude-code-01-mindset",
"profile_context": "any",
"estimated_setup_time": "20min"
},
"quick_start": {
"step_1": "在项目根创建 .claude/settings.json,配置 permissions.allow / permissions.deny",
"step_2": "把不可逆操作写进 deny:Bash(git push:*)、Read(./**/.env)",
"step_3": "开自动模式前,先写 PreToolUse Hook 脚本 .claude/hooks/gate_push.py 兜底"
},
"safety_rules": [
"永不把 Bash(*) 放进 permissions.allow",
"红线操作必须同时在 deny 列表和 PreToolUse Hook 中拦截,不依赖自然语言提示",
"开启自动允许权限时,必须已配置 PreToolUse Hook",
"Agent 不得试错猜测敏感凭证,仅做格式诊断,由人工填写正确值"
],
"verification": {
"check_1": "开自动模式,让 Agent 执行不带确认哨兵的 git push,确认被 Hook 拦截并停止",
"check_2": "让 Agent 读取任意 .env,确认被 deny 规则拒绝"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
AI Agent 使用指南:
- 当用户说"帮我把 Claude Code 的权限收紧" → 生成
quick_start.step_1/step_2的 settings.json,并逐条核对safety_rules。 - 当用户说"开自动模式" → 先确认
quick_start.step_3的 Hook 已就位,再执行verification.check_1。
- 02
- MySQL 性能压测:Sysbench 1.0 实战 原创07-29
- 03
- MySQL Router 实现读写分离 原创07-29