news 2026/9/3 8:14:37

ClaudeCode的计划模式和权限

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ClaudeCode的计划模式和权限

我们把 Claude Code 装好、配好,也写好了 CLAUDE.md。在使用的时候会遇到一个问题。给一个天气 App 加"未来七天预报",我一边想放手让它去改,一边又怕它哪一步删错了文件,或者顺手把我没让它碰的网络层也一起重构了。于是就来回纠结:每步都点"允许",太烦;索性全自动,又不放心。

这篇文章就来拆这个问题。它其实是两件事。第一,动手之前,能不能先看看它打算怎么干?这就是计划模式。第二,动手当中,怎么把"哪些能干、哪些得先问我、哪些绝对不许"定成规则,而且是你说了算的规则?这就是权限系统。后一块也是最容易踩坑的地方,空格、分隔符、路径前缀,差一个字符,你以为配好的规则其实根本没生效。我尽量把它讲准。

文中说法以官方文档(code.claude.com)为准,截至 2026 年中。


一、计划模式:先出方案,不碰你的代码

计划模式(Plan mode)做的事很简单:让 Claude 只研究、只给方案,不动你的源码。

在这个模式下,它可以读文件,可以跑只读命令去摸清代码库,最后给你一份完整的改动计划,但不会编辑任何一个源文件。官方原话是 "reads files and runs read-only shell commands to explore but does not edit your source files"。

这恰好对症"不敢放手"这个病。碰上大改动,或者一个你自己都不熟的代码库,先让它把方案摆出来,你看看思路对不对、它打算动哪几个文件,确认没问题,再放它真改。

怎么进入,有三种方式:

# ① 会话里按 Shift+Tab 循环切到 plan(状态栏会显示当前模式) # ② 只想让某一条提问先走计划,在前面加 /plan /plan 帮天气 App 加一个未来七天预报,先别动手,给我方案 # ③ 启动时就进 plan claude --permission-mode plan

方案出来之后怎么走,这一步很多人没留意。计划就绪时,Claude 会把方案摆给你,并列出五个选项让你挑下一步:

  1. 批准,并切到 auto 模式继续(它自己往下跑)

  2. 批准,并切到 acceptEdits(自动改文件,但跑命令仍要问)

  3. 批准,但每个改动都让你手动逐个确认

  4. 不批准,带着你的反馈继续打磨方案

  5. 用 Ultraplan 在浏览器里进一步细化(进阶,先不展开)

注意第 4 个:方案不满意,不用推倒重来,把意见直接甩给它接着改就行。而只要你批准了方案,就等于退出计划模式、切到你选的那个权限档,它才开始动手。要是你只想退出计划模式、什么都不批,再按一次Shift+Tab就行。

还有两个顺手的小点。方案太长、想自己动两笔,按Ctrl+G能把它在你默认编辑器里打开,改完再让它执行。如果某个项目你希望一进去就是计划模式,在.claude/settings.json里写一行就行:

{ "permissions": { "defaultMode": "plan" } }

回到我那个七天预报。当时就是先/plan,它给的方案里写清楚要动WeatherApi.javaForecastResponse.java两个文件,加一个v7/weather/7d的接口调用。我一看接口路径没错、也没去乱碰 UI 层,才放它改。大改动、不熟的代码,先扫一眼方案再放权,比改完再回头 review 省事得多,主动权也一直在你手里。


二、放权的地基:deny、ask、allow

计划模式管的是动手前,剩下的是动手当中的规则。Claude Code 的权限系统就三种规则,你随时能用/permissions命令可视化地看和改,它会把每条规则、以及规则来自哪个 settings 文件都列出来:

  • allow:免确认,直接用;

  • ask:每次用都问你一下;

  • deny:禁止,根本不给用。

关键在它们怎么裁决。官方原文一字不差是这样:

Rules are evaluated in order: deny, then ask, then allow. The first match in that order determines the outcome, and rule specificity does not change the order.

翻成人话是三句:按 deny、ask、allow 的顺序查;第一个命中的规则就定了结果;规则写得再具体,也不改变这个顺序。

第三句最容易栽跟头。不少人以为"更具体的规则优先级更高",其实不是。看官方那个例子:你写了个宽泛的 denyBash(aws *),又写了条具体的 allowBash(aws s3 ls),心想"除了列 S3,别的 aws 命令都禁"。结果aws s3 ls也被禁了,因为 deny 先查、先命中。deny 规则里开不出"白名单例外"。ask 也一样,命中了 ask 就一定弹窗,哪怕后面有更具体的 allow 也拦不住。

这个顺序跨文件也成立。deny 只要在任意一层出现(企业托管、项目、用户),别的层再 allow 也救不回来。

所以想开例外,靠的不是再补一条更具体的 allow,而是一开始就别用太宽的 deny 把它拦死。


三、规则怎么写:裸工具名和带括号

规则的格式就两种:Tool,或者Tool(具体内容)

不带括号的裸工具名,匹配这个工具的所有用法。Bash匹配所有命令,Read匹配所有读取,WebFetch匹配所有联网抓取(Bash(*)Bash完全等价)。

这里有个差别,不少人不知道,尤其拿来做 deny 的时候得分清:

  • 裸名 deny(比如Bash),会把这个工具从 Claude 的上下文里整个拿掉,它根本看不到有这么个工具;

  • 带范围的 deny(比如Bash(rm *)),工具还在,只拦住匹配的那几种调用。

所以"我不想让它跑任何命令"和"我只想禁掉 rm",是两种完全不同的写法,别混。

带括号,就是加一个 specifier 做精细控制:Bash(npm run build)只匹配这一条命令,Read(./.env)匹配当前目录的 .env,WebFetch(domain:example.com)匹配这个域名。

简单记:裸名管的是"这个工具用不用",带括号管的是"具体哪些用法";而且裸名 deny 是让工具直接消失,不是拦截。


四、Bash 匹配里,一个空格的差别

这一节和下一节是全篇最需要盯细节的地方。你以为写对了的 Bash 规则,很可能因为一个空格、一个分隔符,根本没照你想的生效。

空格决定边界

直接看官方原文:

The space before*matters:Bash(ls *)matchesls -labut notlsof, whileBash(ls*)matches both.

Bash(ls *)*前面有个空格,这个空格强制了一个"词边界":前缀后面必须跟空格,或者到此为止。所以它匹配ls -la,但不匹配lsofBash(ls*)没有空格,也就没有边界,lsoflsblk这些 ls 开头的全被它圈进来。

就一个空格,放行的范围差出十万八千里。还有个等价写法,:*后缀等同于"空格加星号",Bash(ls:*)Bash(ls *)一个意思。但注意:*只有在结尾才认,写成Bash(git:* push),中间那个冒号会被当成普通字符,什么 git 命令都匹配不到。

复合命令,每一段都得单独过关

老教程常这么吓你:"写了Bash(npm test),它跑npm test; rm -rf .就把你坑了。"现在不是这样了。官方讲得明白:

Claude Code is aware of shell operators, so a rule likeBash(safe-cmd *)won't give it permission to run the commandsafe-cmd && other-cmd.

Claude Code 认识 shell 分隔符,它认的有&&||;||&&和换行。碰上复合命令,它会拆成一段段子命令,每一段都得各自命中规则,整条才放行。所以npm test && rm -rf .,不会因为npm test被允许就整条放过,那个rm还是要单独过一遍权限。

顺带说一句,你对一条复合命令点"Yes, don't ask again",它存下来的是每个需要批准的子命令各一条规则(比如批准git status && npm test,实际存的是npm test),单次最多存 5 条。

进程包装器会先被扒掉再匹配

这条能解释一个常见的困惑:"我只写了Bash(npm test *),怎么timeout 30 npm test也直接过了?"因为匹配之前,Claude Code 会先剥掉一组固定的进程包装器:timeouttimenicenohupstdbuf,还有不带参数的xargs,剥完再拿里头真正的命令去匹配。

但要当心那些没在剥离名单上的"运行器":npxdocker execdevbox rundirenv exec,这些不剥。它们会把后面一整串都当命令执行,于是Bash(devbox run *)就等于把devbox run rm -rf .也放行了。要用就写具体点:Bash(devbox run npm test)

只读命令本来就不弹

最后一个省心的地方:有一组内置的只读命令,任何模式下都直接跑、不弹窗——ls cat echo pwd head tail grep find wc which diff stat du cd,还有 git 的只读形式。这些你不用专门写 allow。

一句话,ls *ls*不是一回事,复合命令逐段过关,包装器会被先扒掉。规则光"看着对"不够,得"真能匹配上"才算数。


五、路径锚点:/开头,不是你以为的绝对路径

管"能读、能改哪些文件"的 Read、Edit 规则,路径写法照 gitignore 的规范来,一共四种锚点。这里藏着一个头号陷阱,先看表:

写法

含义

例子

实际指向

//path

绝对路径(从文件系统根)

Read(//Users/alice/secrets/**)/Users/alice/secrets/**
~/path

家目录起算

Read(~/Documents/*.pdf)

你家目录下的 Documents

/path

项目根相对

Edit(/src/**/*.ts)<项目根>/src/**/*.ts
path

./path

当前目录相对

Read(*.env)

当前目录下的 .env

陷阱就在第三行。官方专门加了句警告:

A pattern like/Users/alice/fileis NOT an absolute path. It's relative to the project root. Use//Users/alice/filefor absolute paths.

以单个/开头,指的是"项目根目录",不是系统绝对路径。想写真正的绝对路径,得用两个斜杠//。这条我在第 2 篇提过,这次把它放进完整的四锚点里,因为太多人在这儿写错:本想 deny 掉系统里某个绝对路径,结果写成单斜杠,规则悄悄指到了项目里一个根本不存在的路径,等于白写。

再补两个常用的细节。裸文件名按 gitignore 在任意层级匹配,Read(.env)等价于Read(**/.env),当前目录连同所有子目录下的 .env 都算;而Read(//**/.env)才是匹配整个文件系统里的所有 .env。另外,Read/Edit 的 deny 也会管住 Claude 在 Bash 里识别出来的catheadsed这类读文件命令,但它管不了一个 Python 脚本自己open()文件,那种 OS 级别的封堵得靠 sandbox(后面的篇章再讲)。

记住//才是绝对路径、/是项目根就行。就这一个斜杠的差别,能让你的 deny 规则彻底落空。


六、六种权限模式,和"保护路径"这道兜底

第 2 篇入门时讲过常用的"四档"(default、acceptEdits、bypassPermissions、plan)。这篇补全到官方的六种:

模式

不用问就能做的

适合

default

只读

起步、敏感工作

acceptEdits

读 + 改文件 + 常见文件系统命令(mkdir/touch/mv/cp/rm/sed,仅限工作目录内,且保护路径与rm -rf /rm -rf ~仍会拦下)

边改边审

plan

只读

动手前先探索、出方案

auto

几乎全部,但有后台分类器做安全审查

长任务、减少打断

dontAsk

仅预先 allow 的,其余自动拒(不弹)

CI / 锁定环境

bypassPermissions

全部

仅隔离容器 / VM

有两点容易被忽略。

一是Shift+Tab默认只在 default、acceptEdits、plan 这三档之间循环。auto、dontAsk、bypassPermissions 不在默认循环里:auto 要账号满足条件才会出现,bypass 得用--dangerously-skip-permissions(或者--permission-mode bypassPermissions)启动之后才进循环,dontAsk 干脆只能靠启动参数指定。其中 auto 这个新模式值得了解一下,它放行大部分操作,但后台有个独立的分类器模型在审查,挡住"下载并执行代码、把敏感数据发往外部、强推 main"这类危险动作。不过官方也明说了,它是研究预览,能少打断你几次,但不等于安全,别拿它当 review 的替代品。

二是最实用的那道兜底,保护路径。除了 bypassPermissions,对一批关键路径的写入永远不会被自动批准,连 allow 规则都没法预先放行(安全检查跑在 allow 之前)。这批路径包括.git.claude.vscode、各种 shell 配置文件(.zshrc.bashrc.envrc),还有gradle-wrapper.propertiesmaven-wrapper.properties

还记得第 2 篇那张实拍吗?Claude 核对天气 App 时发现"仓库没有 gradle-wrapper"。而gradle-wrapper.properties恰好就是保护文件之一。就算你开了 acceptEdits,它也不会擅自帮你改 wrapper 配置,而是停下来问你。这套兜底,正是"放权但不至于失控"的最后一道防线。

所以日常用Shift+Tab那三档就够了。放权放得再大,.git、shell 配置、wrapper 这些保护路径也不会被自动改,除非你进了沙箱专用的 bypass。


七、三段可以直接抄的配置

机制讲了这么多,落到~/.claude/settings.json或者项目的.claude/settings.json里,给你三段能直接抄的。

① 日常提速:放行常用,守住危险

{ "permissions": { "allow": [ "Bash(npm run *)", "Bash(git commit *)", "Bash(git push origin *)" ], "deny": [ "Bash(git push * main)", "Read(.env)", "Read(.env.*)", "Read(./secrets/**)" ] } }

npm rungit commit免确认;推 main 被 deny 兜底拦下;.env 和 secrets 目录对 Claude 直接隐身。记住第二节的教训,别想着在 allow 里加一条git push * main来开例外,deny 先查,例外开不出来。

② 不熟的项目,默认先出方案

{ "permissions": { "defaultMode": "plan" } }

③ 用域名白名单替代 curl,更靠谱

{ "permissions": { "deny": ["Bash(curl *)", "Bash(wget *)"], "allow": ["WebFetch(domain:docs.qq.com)", "WebFetch(domain:*.mycompany.com)"] } }

为什么不直接写Bash(curl https://xxx *)去限制 curl 的目标?因为那样很脆。官方列了一串绕过的法子:把-X GET放到 URL 前面、换成 https、用短链接重定向、用变量URL=... && curl $URL,甚至多打一个空格,都能让你的规则失效。靠谱的做法就是上面这样,deny 掉命令行的联网工具,改用WebFetch(domain:...)走域名白名单。

allow 放高频的、deny 守底线、敏感文件让它看不见、联网走域名白名单。这套组合下来,比全程点确认省心,比全自动安全。


八、两条边界,必须记住

这篇讲的是放权。越是讲放权,越得把边界说清楚,不然就是帮倒忙。

第一,权限规则是 Claude Code 在执行,不是模型在执行。你在 CLAUDE.md 或者提示词里写"不要碰数据库",那只影响它想不想去碰;真正决定允不允许它碰的,是这篇讲的权限规则、权限模式,或者 PreToolUse hook。想要硬边界,就写 deny 规则,别指望靠一句叮嘱。

第二,靠约束命令参数的规则天生脆弱,别拿它当安全墙。第七节那个 curl 的例子就是典型。真要封网络或者文件访问,靠域名白名单、PreToolUse hook,或者 OS 级的 sandbox,这些是后面进阶篇(第 7 篇)的内容。权限规则挡得住"Claude 主动想去做的事",挡不住一个它跑起来的脚本在底层自己干的事。

说到底,权限是"你说了算"的硬规则,不是"叮嘱它"的软约束。要硬边界,用 deny 和 hook,别拿脆弱的参数匹配凑数。


九、放权的本质,是把判断写成规则

回到开头那个纠结:全程确认太烦,全自动又不放心。

这篇给的其实是同一把钥匙的两面。动手前,用计划模式先看清它要干什么;动手中,用权限规则把"你能干、你先问、你绝对不能"固定下来。这两件事都到位,你既不用一步步盯着点"允许",也不用把方向盘整个交出去、还蒙着眼。

再往深一层看,这跟整个系列反复碰到的那条线是一致的:Claude Code 用得好不好,说到底是你能不能把对它的约束,从"脑子里的担心"变成"系统里的规则"。CLAUDE.md 是把上下文写成规则,权限配置是把放权写成规则。规则写准了,手才放得安心。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 8:13:52

基于ROS2与Nav2打造开源可定制扫地机器人:从硬件选型到导航实战

简介&#xff1a;本资源是一套基于ROS2开发的导航扫地机器人完整工程实现&#xff0c;面向高校人工智能、机器人工程方向的本科生与研究生&#xff0c;适用于毕业设计、课程设计及ROS2实践项目。资源聚焦机器人自主导航与清扫功能集成&#xff0c;覆盖感知、定位、建图、路径规…

作者头像 李华
网站建设 2026/9/3 8:09:48

Android - app - 面试题

Android - app - 面试题&#xff0c; 架构 (mvvm 常见架构区别&#xff0c;livedata/databinding&#xff09;四大组件 acitivity&#xff08;两种启动方式区别应用场景例子&#xff0c;四种启动模式区别应用场景 &#xff0c;java版flag模拟实现四种启动模式例子&#xff0c;…

作者头像 李华
网站建设 2026/9/3 8:09:04

AI聊天机器人技术解析:从LLM原理到伦理风险防范

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/3 8:06:30

基于STM32F4与DRV8825的四轴步进电机运动控制板全流程设计

简介&#xff1a;本资源是一套完整的四轴运动控制系统工程资料&#xff0c;面向自动化控制工程师、嵌入式开发者及高校机电/机器人方向学习者&#xff0c;聚焦基于PCL6045芯片的硬件驱动设计与STM32平台软件实现&#xff0c;解决多轴协同定位、脉冲生成、编码器反馈闭环等核心问…

作者头像 李华
网站建设 2026/9/3 8:04:48

MATLAB机器人工具箱:从运动学建模到ROS集成的完整开发指南

简介&#xff1a;本资源是面向机器人学研究者、自动化专业师生及MATLAB工程实践者的Robotics Toolbox&#xff08;机器人工具箱&#xff09;完整MATLAB开发包&#xff0c;聚焦于机械臂建模、运动学/动力学仿真与轨迹规划等核心问题。资源共855个文件&#xff0c;涵盖467个MATLA…

作者头像 李华
网站建设 2026/9/3 8:02:53

基于MATLAB/Simulink的风光柴储混合能源系统建模与仿真实践

简介&#xff1a;本资源是一套完整的风光柴储四源联合发电并网系统MATLAB仿真方案&#xff0c;面向新能源电力系统方向的本科生、研究生及科研工程师&#xff0c;用于理解多能源协同控制、并网稳定性分析与能量管理策略设计。仿真涵盖背靠背永磁直驱风电系统&#xff08;含MPPT…

作者头像 李华