这篇文章第一次写完时,我把权限白名单骂得很重。
我那份 settings.json 里确实躺过大约 80 行低复用率的规则。最离谱的一条连 SQL 后面的 LIMIT 20 都存了进去。于是旧稿得出一个很顺手的结论:别点「永久允许」,弹窗只会帮你积攒垃圾。
结论很痛快,可惜现在已经不对了。
本机 Claude Code 已经是 2.1.247。再对照当前官方文档,权限弹窗现在会为命令前缀写入通配规则。真正需要担心的已经从“规则太窄”变成了“规则可能宽得过头”。同一篇工具文章放了几天,最先过期的恰好是它最用力的一段。
所以这一版不再提供一份万能 settings.json。命令会改名,模型别名会移动,权限模式也会增加。比较耐用的是四条边界:上下文什么时候该丢,执行权限放到哪一层,账号与模型路由怎么隔离,CLAUDE.md、skill 和 MCP 各自管什么。
/clear 不是上下文管理的唯一按钮
我常用的命令一直不多。旧稿列了六个,现在重新对照官方文档,能继续当作稳定工作流写下来的只有这些。
/clear 会给当前会话换成一份空上下文,之前的对话仍然保存在本地,可以恢复。它适合任务真的换了:刚查完构建失败,接下来要设计评论系统,这两件事没必要共用一份上下文。
同一个任务做到一半,我更少用 /clear。Claude 已经花了不少轮次摸清目录、约束和失败路径,直接清空意味着下一个回答又要从头建立这幅地图。此时有两个更合适的动作:用 /context 看空间被什么占掉,或者在一个自然断点运行 /compact,把前面的对话压成摘要。官方会话文档 对三者的边界写得很清楚:clear 是重新开始,compact 是替换历史,context 只负责查看。
! 前缀仍然好用。输入:
! git log --oneline -20命令会直接执行,输出进入当前会话。它省掉的是一轮无意义的转述,但不会省上下文;一条打印两千行日志的命令,仍然会把两千行日志塞进来。交互模式文档 也把它定义成 shell mode,而不是“免费执行”。
跑偏时用 Esc Esc 或 /rewind。当前 rewind 菜单可以只恢复对话、只恢复代码,或者两者一起恢复。这里有一条很容易漏掉的边界:checkpoint 只跟踪 Claude 文件工具产生的编辑,通过 Bash 命令改掉的文件并不在它的恢复范围内。Checkpointing 文档 明确写了这个例外。让 Claude 跑迁移脚本之后再按 rewind,数据库不会跟着时光倒流。
旧稿还推荐过 # 前缀,把一句话记进 memory。当前官方 commands、interactive mode 和 memory 文档里已经找不到这个稳定入口,我没有在这次改稿里替读者猜它是否仍会在某个版本、某种终端下工作。要检查长期指令,直接用 /memory 查看已加载的 CLAUDE.md、rules 和 auto memory,路径更长一点,语义也更清楚。
权限弹窗修好了旧问题,也带来了新问题
当前 Claude Code 的 permission rule 仍然使用 Tool(specifier) 这种形状,但 Bash 规则已经支持任意位置的 *。选择 “Yes, don’t ask again” 时,弹窗会为命令前缀写入带空格的通配形式。例如:
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git log *)"
]
}
}这正面解决了我那 80 行尸体的问题。也正因为如此,旧稿里“手写模式,别信弹窗”的建议需要收回一半:现在弹窗本身已经会写模式。
剩下那一半反而更重要。通配符匹配的是命令字符串,不是你脑子里想象的操作边界。官方文档特意举了一个不太舒服的例子:Bash(git * main) 既可能匹配查看日志,也可能匹配向 main 推送。Bash(ls *) 和 Bash(ls*) 甚至因为一个空格而有不同边界。权限规则文档 值得在手写规则前读一遍,不然“少点两次确认”很容易变成“多放开一整类命令”。
我现在会把控制分成三层。
CLAUDE.md 写项目判断。例如这个博客仓库明确写着:Jenkins 流水线故意不跑 go test、npm test;React/DOM/UI 和 e2e 测试也不在自动化范围内。这些规则拦的不是语法错误,而是一种看起来很正确的好心。代码本身无法告诉 agent “这里故意没做什么”,项目说明必须补上这层信息。
permission rules 决定一次工具调用要直接允许、询问还是拒绝。它们是审批规则,但仍然不是操作系统边界。要限制 Bash 子进程能读写的目录和能够访问的网络,需要启用 sandbox,并配置文件系统与域名范围。Claude Code 当前默认并不会替你开启 sandbox。设置文档 和权限文档 把两层分得很开。
最后才是 permission mode。终端里的 Shift+Tab 现在默认在 Manual、Accept edits 和 Plan 之间循环;Auto 与 Bypass permissions 是否出现,取决于账号、模型、启动参数和组织策略,并不是一个固定的“自动接受”开关。权限模式文档 列出了各端差异。
我过去一天里大部分时间都在 bypass 下干活,这个经历是真的。但把“工作区干净,有 Git 就行”写成通用建议,边界太松了。Git 能恢复受版本控制的文件,撤不回已经发出的网络请求,也救不了未跟踪文件和泄露出去的凭据。Anthropic 当前给出的建议更保守:bypass 不提供针对提示注入或意外操作的保护,适合放在隔离容器或 VM 里。要的是少弹窗而不是彻底拆掉闸门,可以先看 sandbox 或有后台安全检查的 Auto mode。
多套配置目录解决身份串线,解决不了所有登录问题
我最早用 shell 函数切第三方模型:
claude_gateway() {
export ANTHROPIC_BASE_URL=...
export ANTHROPIC_AUTH_TOKEN=...
claude "$@"
}能跑,缺点也很直接:export 出去的值留在当前 shell 里。切过一次网关,同一个终端里再运行 claude,请求仍然会走那个地址。后来我又写函数负责 unset。写到需要配套擦除函数时,这个方案已经在提醒我,它的隔离边界是漏的。
CLAUDE_CONFIG_DIR 更适合这个问题:
alias claude-personal='CLAUDE_CONFIG_DIR=~/.claude-personal claude'
alias claude-gateway='CLAUDE_CONFIG_DIR=~/.claude-gateway claude'官方环境变量文档说明,settings、session history 和 plugins 都会跟随这个目录,给出的用途之一就是并行使用多套账号配置。CLAUDE_CONFIG_DIR 文档 支持这个做法。
macOS 上要多加一句。Claude 订阅账号的登录凭据放在系统 Keychain,不会因为换了目录就自然变成另一套官方登录态;Linux 和 Windows 使用的 .credentials.json 才会跟随自定义配置目录。认证文档 写明了这个平台差异。我实际确认过的是一套官方账号加多套第三方 token,不能顺手外推成“两个官方账号也能干净并存”。
第三方网关的模型配置也不再适合总结成“八个变量必须设满”。当前版本至少有三条路。
如果网关实现 Anthropic Messages 格式和 /v1/models,可以选择开启模型发现:
{
"env": {
"ANTHROPIC_BASE_URL": "https://gateway.example.com",
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY": "1"
},
"apiKeyHelper": "~/bin/get-claude-gateway-token"
}apiKeyHelper 不是必须项,但比把长期 token 明文塞进 .zshrc 或 settings.json 更适合需要轮换凭据的环境。网关如果不支持模型发现,或者模型 ID 不符合发现规则,再用 ANTHROPIC_CUSTOM_MODEL_OPTION 把一个非标准模型加入 picker,或用 ANTHROPIC_DEFAULT_OPUS_MODEL、ANTHROPIC_DEFAULT_SONNET_MODEL、ANTHROPIC_DEFAULT_HAIKU_MODEL 映射实际会用到的别名。LLM Gateway 文档 和模型配置文档 给出了各自的适用条件。
CLAUDE_CODE_SUBAGENT_MODEL 现在是一个强覆盖项:它会盖过单次调用参数和 subagent 自己声明的模型。只有确实想把所有 subagent 固定到同一个模型时才需要设。把它机械地塞进每份配置,等于主动丢掉更细的模型选择。
还有一个比“配几个变量”更容易让功能表现异常的点:当 ANTHROPIC_BASE_URL 指向非 Anthropic 地址时,MCP Tool Search 默认关闭,因为多数代理不会转发 tool_reference block。只有确认网关支持后,才应该显式设置 ENABLE_TOOL_SEARCH=true。环境变量文档 对这个回退行为有明确说明。旧稿把某些 MCP 或 subagent 问题都归因于模型名没映射全,解释得太早了。
至于哪些活值得换模型,我的判断没有变:批量改字段名、整理日志、生成容易核验的样板,可以用便宜模型;跨文件重构、接口或 schema 变更、以及连自己都说不清正确答案长什么样的任务,不要只看单次调用价格。这里没有通用 benchmark,只有验证成本。一个字段在九个文件里改对、第十个漏掉,省下的调用费很快就会从 review 和 debug 里讨回来。
CLAUDE.md、skill、MCP,分别放不同的东西
旧稿把 skill 叫作“说明书”,把 MCP 叫作“多长一只手”。方向没错,表达太绝对。
CLAUDE.md 是每次都加载的项目背景和约定,适合放“不加 e2e”“先改契约再改三端”这种持续成立的判断。它告诉 agent 应该怎么做,但不是安全边界。必须保证的限制,应该落在 permissions、sandbox、hooks 或干脆不存在的工具接口上。
skill 是按需加载的知识与工作流,可以带参考文件、模板和脚本。它不只是几段提示词,也不是一条外部系统连接。Claude Code 会根据 skill 的名称与 description 判断何时加载,所以“处理数据相关任务”这种描述几乎等于没写;触发条件必须接近用户真正会说的话。Claude Code Skills 文档 对发现、优先级和 description 的作用都有说明。
MCP 负责接入外部工具和数据。这个博客的 MCP server 暴露了文章读取、整稿保存、版本冻结、媒体登记、发布和只读 SQL;同时在 server instructions 里写明两条跨工具纪律:发布会触发一次 Jenkins 全站构建,草稿写入和冻结使用的 lock_version 必须来自最近一次读取。工具签名提供能力,server instructions 补上单个工具无法表达的代价与顺序。
这三层组合起来,才是一套能工作的流程:CLAUDE.md 交代仓库边界,skill 规定调研、写作、审查和批准门,MCP 提供读取线上草稿与保存版本的手。少任何一层都不是不能跑,只是错误会换一种方式出现。
Codex 也使用 Skills 和 MCP,但不要把 Claude Code 的路径、快捷键或 permission mode 原样搬过去。OpenAI 的当前定义同样把 Skills 视为包含 instructions、resources 和 scripts 的可复用工作流,把 MCP 定义为第三方工具与上下文连接;Codex 还会读取 MCP server 的 instructions 作为跨工具约束。OpenAI Skills 与OpenAI MCP 支持这条概念边界,具体配置仍然要查各自产品文档。
最后留下四个检查问题
准备 /clear 前,先问:任务真的换了吗,还是只需要 /compact?
准备放宽权限前,先问:这是审批便利,还是需要 sandbox 提供系统级边界?
准备给第三方网关补一串环境变量前,先问:网关能否发现模型,实际用到了哪些别名,是否支持 Tool Search?
准备把一条规则塞进 CLAUDE.md 前,先问:它是长期项目判断、按需工作流,还是必须由工具和权限强制执行的限制?
这四个问题没有配置文件那么方便复制,却比旧稿里那份配置活得久一点。至少下一次 Claude Code 更新时,不必先去清理又一批 80 行尸体。