Claude Code 权限模式怎么选:auto、Manual、accept edits、plan,以及改错了怎么退回去
Claude Code 能改文件、跑命令,什么时候该先问你,由权限模式决定。本站把几种模式逐个实测了一遍:Shift+Tab 的切换顺序、两种确认框、plan 模式怎么出方案、auto 模式遇到危险动作怎么处理,以及按两下 Esc 能退回什么、退不回什么。
本站已实测,测试日期:2026-10-11。
本页目录(12 节)
这篇教程解决一个问题:Claude Code 能改你的文件、在你的终端里跑命令,什么时候它该先停下来问你。 决定这件事的是权限模式。
新版本默认用 auto 模式,大多数动作不再问你。这很省事,但你至少要知道三件事:现在是哪个模式,怎么换,改错了怎么退回去。
本站把几种模式逐个试了一遍,下面的界面和输出都是实测时的真实画面。
| 实测环境 | |
|---|---|
| 日期 | 2026-10-11 |
| 版本 | Claude Code 2.1.296 |
| 系统 | Ubuntu 24.04 |
| 模型 | Opus 5.5 |
| 连接方式 | 通过酷站AI 中转站,不是直连官方 |
| 示例仓库 | Express 的源码,v5.3.0,和前两篇是同一个 |
先看全貌:六种模式
下表来自官方文档,“不问就能做”指不弹确认框。
| 模式 | 不问就能做的 | 适合 |
|---|---|---|
Manual(配置里叫 default) |
只有读取 | 每个动作都自己过目,敏感的工作 |
accept edits(acceptEdits) |
读取、改文件,以及 mkdir、mv、cp 这类常见的文件命令 |
一边让它改,一边自己看改动 |
| plan | 读取;只探索、出方案,不改源文件 | 动手之前先把代码库看明白 |
| auto | 所有动作,由后台的分类器做安全检查 | 耗时长的任务,不想被反复打断 |
dontAsk |
读取和事先允许的工具;其他会弹确认的一律拒绝 | 锁死权限的 CI 和脚本 |
bypassPermissions |
所有动作,不做检查 | 只在隔离的容器和虚拟机里用 |
怎么知道现在是哪个模式,怎么换
看输入框下面那一行。按 Shift+Tab 切换。我们从 auto 开始连按四下,状态栏依次是:
⏵⏵ auto mode on (shift+tab to cycle)
⏸ manual mode on
⏵⏵ accept edits on (shift+tab to cycle)
⏸ plan mode on (shift+tab to cycle)
⏵⏵ auto mode on (shift+tab to cycle)
顺序是 auto、Manual、accept edits、plan,再回到 auto,和官方文档写的一致。dontAsk 不在这个循环里,只能用启动参数指定;bypassPermissions 要在启动时就打开才会出现。
新会话从哪个模式开始,官方文档给的优先顺序是:
- 启动参数,比如
claude --permission-mode plan。 - 设置文件里的
permissions.defaultMode。 - 内置的默认值。从 2.1.283 版起,在终端里交互使用时内置默认是 auto。
想让自己每次都从 Manual 开始,在 ~/.claude/settings.json 里写:
{
"permissions": {
"defaultMode": "default"
}
}
文档里有一个容易踩的地方:"auto" 写在项目的 .claude/settings.json 或 .claude/settings.local.json 里是不生效的,要写在用户级的 ~/.claude/settings.json 里。
Manual:每一步都问你
切到 Manual,给一个既要建文件又要跑命令的任务:
新建一个文件 notes/demo.md,里面写一句“权限模式测试”,然后运行 npm run lint。
先弹出的是建文件的确认框:
Create file
notes/demo.md
1 权限模式测试
Do you want to create demo.md?
❯ 1. Yes
2. Yes, and switch to accept edits (auto-approve file edits and common file commands) for this session (shift+tab)
3. No
Esc to cancel · Tab to amend
选了 Yes 之后,是跑命令的确认框:
Bash command
Tip: auto mode handles these prompts for you — choose "switch to auto mode" below
Run ESLint
npm run lint
This command requires approval
Do you want to proceed?
❯ 1. Yes
2. Yes, and don’t ask again for: npm run *
3. Yes, and switch to auto mode · auto mode handles these prompts for you
4. No
两个框的选项不一样,值得看清楚:
| 选项 | 效果 |
|---|---|
| Yes | 只批准这一次 |
| Yes, and switch to accept edits | 批准,并把这个会话切到 accept edits |
| Yes, and don’t ask again for: npm run * | 批准,并把这一类命令记成允许规则 |
| Yes, and switch to auto mode | 批准,并把这个会话切到 auto |
| No | 拒绝 |
“不再询问”记到哪里了? 我们选了第 2 项,然后去看项目目录,多了一个文件 .claude/settings.local.json:
{
"permissions": {
"allow": [
"Bash(npm run *)"
]
}
}
注意它记的是 npm run *,比你刚批准的 npm run lint 宽。这个文件不会被提交:我们查了一下,Claude Code 在全局的 git 忽略文件 ~/.config/git/ignore 里加了一条 **/.claude/settings.local.json。
官方文档对“不再询问”管多久的说法是:命令的规则对这个仓库永久有效;改文件的批准只到会话结束。
拒绝之后会怎样? 我们对另一条命令选了 No,屏幕上显示:
● Bash(npx mocha --require test/support/env test/req.subdomains.js)
⎿ Interrupted · What should Claude do instead?
它停下来等你说怎么办,不会自己换个办法绕过去。
accept edits:改文件不问,跑命令还问
切到 accept edits,再给一个任务:
在 notes/demo.md 里再加一行“第二行”,然后运行 npx mocha --require test/support/env test/req.subdomains.js。
改文件直接做了,没有弹框;轮到 npx mocha 时弹出了和上面一样的命令确认框。
官方文档说,这个模式除了改文件,还会自动批准 mkdir、touch、rm、rmdir、mv、cp、sed 这几个常见的文件命令,但只限工作目录以内的路径。它适合这样的工作方式:让它连着改,你事后在编辑器里或者用 git diff 看改动,而不是一处一处批准。
plan:先出方案,不动代码
切到 plan,提一个需要设计的需求:
我想给 Express 加一个设置 subdomain ignore:一个字符串数组,数组里的子域名不出现在 req.subdomains 的结果里。
先给我方案,不要动代码。
它读了几处代码,24 秒后给出一份方案,并问怎么继续:
Ready to code?
Here is Claude's plan:
方案:新增 subdomain ignore 设置
行为定义
- 先按现有逻辑算出结果(reverse() + slice(offset)),再过滤掉在 ignore 数组里的项;不影响 offset 的计数。
- 未设置(默认 undefined)或空数组时,行为与现在完全一致。
- 只过滤完全相等的项;比较时忽略大小写……
改动文件
1. lib/request.js(subdomains getter,约 386 行)……
2. test/req.subdomains.js:新增 describe('when subdomain ignore is set')……
3. History.md:在顶部新增 unreleased 段落……
验证
- npm run lint
- npx mocha --require test/support/env --check-leaks test/req.subdomains.js
(按项目约定,不跑全量 npm test。)
Claude has written up a plan and is ready to execute. Would you like to proceed?
❯ 1. Yes, and use auto mode
2. Yes, manually approve edits
3. Tell Claude what to change
shift+tab to approve with this feedback
ctrl+g to edit in Vim · ~/.claude/plans/buzzing-coalescing-creek.md
几点观察:
- 方案是有内容的。 它定义了边界情况(空数组、大小写、IP 地址),列了要改的三个文件和验证办法,连“按项目约定不跑全量测试”都带上了,那是上一篇写进
CLAUDE.md的规矩。 - 三个选项:批准并用 auto 模式执行;批准但每处修改都由你确认;告诉它方案哪里要改。批准之后就退出了 plan 模式。
- 方案存成了文件,在
~/.claude/plans/下。按Ctrl+G可以在编辑器里直接改方案,再让它执行。 - 不想批准就按
Esc。 我们按了,回到输入框,仍然在 plan 模式;git status确认源文件一处没动。
出方案的过程中,它跑的几条探索命令下面有 Allowed by auto mode classifier 字样。这符合官方的说明:auto 模式可用时,plan 模式下的命令由分类器审查,而不是来问你。
只想对某一句话用 plan,不用切模式:在那句话前面加 /plan。
auto:不问你,但不等于什么都做
auto 是现在的默认模式。官方的描述是:有一个独立的分类器模型在动作执行前审查它,拦下超出你要求的、针对不认识的基础设施的、或者看起来是被它读到的恶意内容驱使的动作。
分类器默认会拦的东西,文档列了很长一串,这里摘几条程序员最常碰到的:
- 下载并执行代码,比如
curl | bash - 把敏感数据发到外部
- 生产环境的部署和数据库迁移
- 强制推送
git reset --hard、git checkout -- .、git clean -fd这类会丢掉未提交改动的命令- 修改不是这个会话创建的提交(
git commit --amend) - 合并一个没有人批准过的 PR
- 把在用的凭据或 token 打印到对话或文件里
默认放行的包括:工作目录里的文件操作、安装清单里已经声明的依赖、只读的 HTTP 请求、向当前仓库的分支推送。
实测:两次危险的要求
我们想看分类器拦截的样子,在 auto 模式下提了两个要求。结果和预想的不一样。
第一次,要求强制推送:
把 notes/demo.md 提交了,然后把 demo 分支强制推送到 origin。
提交它做了。推送它没有做,而且不是被分类器拦的,是它自己停下来了:
强制推送我还没有做。 origin 指向的是 Express 官方的公开仓库 https://github.com/expressjs/express.git,
不是你自己的 fork。推上去等于把内容公开到官方仓库,即使之后删掉,也可能已经被缓存或被别人看到。
另外 origin 上目前没有 demo 分支,这次推送会在官方仓库里新建一个分支。很可能你本来就没有这个仓库的写权限。
想推的话可以选一种:
1. 推到你自己的 fork(推荐)……
2. 确实要推到官方仓库:请再明确确认一次,我就执行 git push --force origin demo。
第二次,要求丢弃改动:
不推了。在 notes/demo.md 末尾随便加一行先不提交,然后用 git reset --hard HEAD~1 把刚才那次提交撤掉。
加那一行它做了。reset --hard 又停下来了:
git reset --hard HEAD~1 我还没有执行。 它的结果可能和你预期的不一样:
- notes/demo.md 是在要撤掉的那次提交里新建的,--hard 退回去之后,整个文件会从磁盘上删掉,不只是撤销提交。
- 刚加的那一行还没提交,会被直接丢掉,没法恢复。
可以选一种:
1. git reset --mixed HEAD~1(推荐):撤掉提交,文件和三行内容都留在工作区……
3. 照原样执行 git reset --hard HEAD~1:提交、文件和新加的那一行全部删掉。你确认后我就执行。
我们回了一句“选 3,确认照原样执行”,这次它执行了,文件和那一行都没了。
从这两次能得出的结论是有限的:
- 拦在前面的不只是分类器。 这两次都是模型自己先判断“这个动作收不回来”,停下来把后果讲清楚。我们没有看到分类器拦截的提示。
- 明确确认之后它会照做。 这和官方文档一致:你在对话里说某个被拦的动作可以做,分类器会把它当作你的批准。文档还说,批准要点名具体的动作和危险之处(比如强制推送的是哪个分支),只说一句“可以强制推送”不算;一次批准只管那一个动作。
- 反过来也成立。 你在对话里说“先别推送”“等我看过再部署”,分类器会把它当作界线,即使默认规则允许也会拦。但这条界线只存在对话里,对话被压缩后可能丢失;要硬性保证,写成下面讲的拒绝规则。
官方文档对 auto 模式有一句直白的提醒:它减少确认框,但不保证安全;用在你大体信得过方向的任务上,不要拿它代替对敏感操作的审查。
分类器真的拦了会怎样
这一段我们没有实测到,按官方文档写:
- 被拦的动作会有通知,并列在
/permissions的 Recently denied 页里,在那里按r可以手动批准后重试。 - 连续拦 3 次或者累计拦 20 次,auto 模式会暂停,恢复成逐个问你。
通过中转站用 auto 模式
通过中转站使用时,会话里可能弹出一个关于分类器计费的提示,要按回车才继续。它的意思和处理办法,上一篇里有一节专门讲。简单说:什么都没坏,auto 模式照常工作,只是分类器的请求计入你的 token 用量。
dontAsk 和 bypassPermissions:给脚本用的两种
这两种不在 Shift+Tab 的循环里,主要用在不需要人值守的场合。
先说一个实测结果:不带界面运行时,默认也可能是 auto。 我们用 claude -p 让它建一个文件并报告自己的权限模式:
我已经新建了 `p-test.txt`,内容是 `hi`。……
当前是 **auto 模式**。
文件确实建出来了。官方文档的说明是:claude -p 的内置默认,在走第三方接入或关了遥测的会话里,从 2.1.285 版起是 auto,其余情况是 Manual。我们走的是中转站,属于前一种。如果你把 claude -p 接进脚本,不要假设它什么都不会改,用参数把模式写死。
dontAsk:凡是会弹确认框的动作一律拒绝,会话永远不等人。我们加上 --permission-mode dontAsk 再让它建文件,这次没有建,它回复说可以把 Write 工具加进允许列表后再试。配合允许列表用,就是一份精确的白名单。官方的例子:
claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"
bypassPermissions:关掉确认和安全检查,工具调用立即执行。官方的警告是只在隔离的环境里用:容器、虚拟机,Claude Code 伤不到宿主机的地方。它不能在会话中途进入,要在启动时打开。这个模式我们没有实测。
权限规则:比模式更细的一层
模式定的是基线。在它之上可以用规则单独放行或禁止某些工具和命令,分三种:
| 规则 | 效果 |
|---|---|
| allow | 不用问就能用 |
| ask | 每次都问 |
| deny | 不让用 |
判断顺序是先 deny、再 ask、最后 allow,先匹配到的算数。所以一条宽的拒绝规则会盖住更具体的允许规则:Bash(aws *) 被拒绝之后,Bash(aws s3 ls) 写进允许也没用。拒绝规则在所有模式下都生效,包括 bypassPermissions。
规则的写法是 工具名 或 工具名(限定):
| 规则 | 匹配 |
|---|---|
Bash(npm run build) |
正好是这条命令 |
Bash(npm run *) |
以 npm run 开头的命令 |
Read(./.env) |
读当前目录下的 .env |
WebFetch(domain:example.com) |
抓取这个域名 |
一个给项目用的例子,写在 .claude/settings.json 里可以提交给团队:
{
"permissions": {
"allow": ["Bash(npm run lint)", "Bash(npm test)"],
"deny": ["Bash(git push --force *)", "Read(./.env)"]
}
}
在会话里输入 /permissions 可以查看和修改。我们看到的面板有六页:Recently denied、Allow、Ask、Deny、Auto mode、Workspace。
官方文档有一句话把规则和 CLAUDE.md 的区别说清楚了:权限规则是 Claude Code 执行的,不是模型执行的。 你在提示词或 CLAUDE.md 里写的要求,影响的是它想做什么;能不能做,由规则、模式和 hook 决定。
改错了怎么退回去
输入框是空的时候按两下 Esc,或者输入 /rewind,会打开回退菜单。它列出这个会话里你发过的每一句话,以及那一轮改了什么(下面是两次打开菜单时看到的内容,有删节):
我想给 Express 加一个设置 subdomain ignore……先给我方案,不要动代码。
buzzing-coalescing-creek.md +32
把 notes/demo.md 提交了,然后把 demo 分支强制推送到 origin。
No code changes
用 Edit 工具(不要用 sed 或其他命令)把 lib/utils.js 第一行的注释改成:// demo: 第二次修改……
utils.js +1 -1
❯ (current)
选中一句,可以做的事有:
| 选项 | 效果 |
|---|---|
| Restore code and conversation | 代码和对话都退回到发这句话之前 |
| Restore conversation | 只退对话,代码保持现在的样子 |
| Restore code | 只退代码,对话保留 |
| Summarize from here / up to here | 把这一点之后或之前的对话压缩成摘要,腾出上下文 |
实测:能退回的,和退不回的
这一节是这次实测里最值得知道的。我们让它改了两次同一个文件。
第一次,只说“在 lib/utils.js 第一行前面加一行注释”。它用命令改的文件。在回退菜单里选中这一句,看到的是:
The conversation will be forked.
The code will be unchanged.
❯ 1. Restore conversation
2. Summarize from here
3. Summarize up to here
4. Never mind
没有恢复代码的选项,并且写明“代码不会变”。
第二次,明确要求“用 Edit 工具,不要用 sed 或其他命令”。这次回退菜单里是:
The conversation will be forked.
The code will be restored +1 -1 in utils.js.
❯ 1. Restore code and conversation
2. Restore conversation
3. Restore code
4. Summarize from here
↓ 5. Summarize up to here
⚠ Rewinding does not affect files edited manually or via bash.
选第 1 项之后,文件的第一行回到了第二次修改之前的样子,那句话也回到了输入框里,可以改一改再发。第一次用命令加的那行注释还在,因为它不归回退管。
这正是官方文档写的第一条限制:回退只管它用文件编辑工具做的修改,不管命令改动的文件。 rm、mv、cp、sed -i 造成的变化都退不回来。而它用哪种方式改文件,你事先不一定知道。
其他几条限制,按文档:
- 子代理做的修改通常不在回退范围内,要用 git 撤销。
- 你自己在编辑器里的手工修改、别的会话的修改,一般不会被记录。
- 对外部系统做过的事(数据库、接口、部署)退不回来。
- 一个会话保留最近 100 个回退点;快照默认在大约 30 天后清理。
文档的结论也是我们的结论:回退不能代替版本控制。 让它动手之前先提交一次,是最可靠的退路。
怎么选
按官方文档给的搭配,加上这次实测的体会:
| 你的情况 | 用什么 |
|---|---|
| 刚开始用,或者在不熟的代码、敏感的项目上 | Manual。先看清它每一步想做什么 |
| 让它连着改,自己事后看 diff | accept edits |
| 需求还没想清楚,或者改动比较大 | 先 plan,看过方案再批准 |
| 方向清楚、耗时长的任务 | auto,并且先提交一次 |
| 接进脚本和 CI | dontAsk 加一份允许列表 |
| 一定不能发生的事 | 写成拒绝规则,不要只在对话里说 |
这一趟花了多少
整个会话八句话,/cost 显示 0.46 美元,模型工作 1 分 51 秒。这是 Claude Code 按官方价格估算的数字,不是中转站实际扣的金额。
这次实测没有覆盖到的
- 分类器的拦截没有触发。 两次危险的要求都是模型自己先停下来的。分类器拦截后的通知、Recently denied 页和重试,按官方文档写的。
bypassPermissions没有实测。- VS Code、桌面应用里的模式切换没有实测,它们各有自己的控件。
- 规则的例子没有逐条验证。 只验证了“不再询问”会写进
.claude/settings.local.json。 - 只跑了一次。 模型在危险动作前会不会自己停下来,每次不一定相同,不要把它当成保证。