1. 先搞清楚切 Permission Mode 到底动了什么Claude Code 里的 Permission Mode 是控制「哪些操作需要你点头」的开关。default 模式下改文件、跑命令基本都要确认acceptEdits 会自动批准文件编辑和工作目录内一组固定的文件系统命令plan mode 则让 Claude 先读文件、出方案批准前不碰磁盘。这些模式可以在 settings.json 里用 defaultMode 设默认值也能在单次会话里用 --permission-mode 覆盖交互中还能用 ShiftTab 循环切换。很多人一看到模式变了第一反应是「system prompt 是不是也换了缓存是不是全废了」。这个担心可以理解但方向偏了。Permission Mode 改的是执行层的门禁策略不是模型看到的那份基础说明书。Claude API 的 prompt caching 是按请求前缀工作的顺序是 tools → system → messages只要这三段里被缓存的内容没变缓存前缀就能对上。切 default 到 acceptEditstool definitions 没动system prompt 没动历史消息也没被重写缓存自然还在。真正需要单独拎出来看的是 opusplan。官方把 opusplan 定义成一个模型别名plan 阶段用 Opus执行阶段切回 Sonnet。这时候进 plan mode 就不只是权限模式变化了底层模型也跟着换了。模型一变缓存就不能按同一个引擎来复用。所以结论要分两层普通 permission mode 切换通常 cache-safeopusplan 下的 plan mode 切换要按 model switch 对待。下面我把配置骨架、验证动作和排障路径都写出来你可以直接在本地复现这套判断。2. 前置准备TaoToken 接入与 Key 获取要在本地稳定复现 Claude Code 的缓存行为先得有一个能正常发请求的接入点。我用的是 TaoToken 的 API 通道官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 注意这个地址后面不加 UTM 参数。拿 Key 的路径很直接进控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 创建一个新 Key。创建时建议按用途命名比如 claude-code-cache-test方便后面区分是哪个环境在跑。拿到 Key 之后先别急着改 Claude Code 的配置。我习惯先用模型对话页面 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 发一条最简单的请求确认 Key 本身是通的。这一步能排掉大部分「配置写对了但 Key 没生效」的低级问题。如果你后面要跑长期的编码任务或者 Agent 流程可以顺带看一下 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合持续性的会话场景。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 配置字段有疑问时对着查最快。3. 可复制的 settings.json 配置骨架Claude Code 的配置分两层一层是接入信息走哪个 API 基址、用哪个 Key一层是行为策略defaultMode、模型别名等。我把这两层拆开写方便你按需改。先看接入层。Claude Code 读的是环境变量不是直接写在 settings.json 里的密钥。你可以在 shell 的启动文件里导出export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的TaoToken密钥如果你用的是 Claude Code 的 Anthropic 兼容通道配置项名称可能略有差异具体以接入文档为准。设置完记得 source 一下启动文件或者重开终端。再看行为层也就是 settings.json。下面这份骨架覆盖了 defaultMode 和模型别名两个关键字段{ defaultMode: default, model: claude-sonnet-4-5, permissions: { allow: [ Edit, Bash(mkdir:*), Bash(touch:*), Bash(mv:*), Bash(cp:*) ], deny: [] } }几个字段的含义要分清。defaultMode 决定会话启动时的权限模式可选值包括 default、acceptEdits、plan、auto、dontAsk、bypassPermissions。model 决定用哪个模型这里填普通模型别名时plan mode 只是权限模式一旦把 model 设成 opusplanplan mode 就同时变成模型路由开关。如果你要专门验证 opusplan 的行为把 model 改成{ defaultMode: plan, model: opusplan }这份配置的意思是会话默认进 plan mode且 plan 阶段走 Opus、执行阶段走 Sonnet。用它来复现「模式切换 模型切换」叠加的场景最合适。改完配置后用 --permission-mode 做单次覆盖测试claude --permission-mode acceptEdits这条命令会临时把权限模式切成 acceptEdits但不会改 settings.json 里的默认值。用它来对比「同一份配置下不同 permission mode 的缓存表现」很方便。4. 验证请求怎么确认缓存没被打碎配置写好了接下来是验证。核心思路是构造一个足够长的前缀工具定义 system prompt 多轮历史然后在不同 permission mode 之间切换观察缓存命中情况。第一步先跑一个长上下文会话。让 Claude Code 读一批文件比如十几个源码文件加测试日志积累出可观的 message history。这一步的目的是把缓存前缀撑大让命中与否的差异足够明显。第二步在 default 模式下发一轮请求记录返回里的缓存相关字段。Claude API 的响应里会带 cache_creation_input_tokens 和 cache_read_input_tokens 两个计数。第一次请求通常是 creation 较大、read 为 0第二次相同前缀的请求read 应该显著上升。第三步切到 acceptEdits再发一轮。如果 tool definitions 和 system prompt 没变历史也没被重写你应该看到 cache_read_input_tokens 仍然保持在高位而不是掉回 0。这就是「permission mode 切换 cache-safe」的直接证据。第四步切到普通 plan modemodel 仍是普通别名再发一轮。预期和 acceptEdits 类似read 计数依然稳定。第五步把 model 改成 opusplan进 plan mode 再发一轮。这时候你会看到 read 计数明显下降因为请求已经发给了另一个模型旧缓存不能跨模型复用。这一步是整组验证里最关键的反例。如果你不想手动数 token可以在请求里显式加 cache_control 断点把断点放在 system prompt 末尾或历史消息的某个位置然后对比断点前后的命中情况。断点之前的前缀一致命中就在前缀被改写命中就丢。5. 本篇常见错排查报错一切了 acceptEdits 后 cache_read 掉到 0。先别怀疑 permission mode。检查是不是同时改了 model、output style 或者 MCP 工具集合。这几个才是真正会动 system prompt 或 tool definitions 的字段。permission mode 单独变化不会导致这个结果。报错二opusplan 下 plan mode 切换后响应变慢、费用上升。这是预期行为不是 bug。opusplan 在 plan 阶段用 Opus执行阶段用 Sonnet模型切换本身就意味着缓存不能跨模型复用。要优化的话把长会话里的 plan 阶段控制得短一些别让 Opus 反复接手大段历史。报错三settings.json 里改了 defaultMode 但没生效。检查是不是被 --permission-mode 命令行参数覆盖了或者当前会话是用旧配置启动的。Claude Code 的配置在会话启动时读取改完文件要重开会话。报错四缓存命中率一直很低但没切过模式。排查顺序是tool definitions 有没有变比如新加了 MCP 工具、system prompt 有没有被 output style 改写、历史消息里有没有插入时间戳之类每次都变的内容。这些比 permission mode 更常见。报错五接入层报 401 或连接失败。回到第 2 节确认 ANTHROPIC_BASE_URL 指向 https://taotoken.net/api Key 是从控制台新建的且没有多余空格。先用模型对话页面单独验证 Key再回来跑 Claude Code。6. 把边界记清楚少走弯路Permission Mode 和 prompt cache 的关系一句话概括门禁策略变了不等于模型说明书变了。default、acceptEdits、普通 plan 之间的切换不动 tools、不动 system、不改历史前缀缓存可以继续复用。opusplan 是唯一的例外它把 plan mode 变成了模型路由的一部分进 plan 用 Opus、出 plan 用 Sonnet这时候要按 model switch 处理不能按 permission mode 估算成本。实操上我建议你把验证动作固化成一个小流程长会话打底 → default 测基线 → 切 acceptEdits 对比 → 切普通 plan 对比 → 切 opusplan 看反例。跑一遍下来你对缓存的直觉就建立起来了。配置和 Key 都就绪之后如果只是验证模型行为用模型对话页面最快如果要跑长期编码任务Coding Plan 更合适接入字段有疑问就翻接入文档。把这几条路径记住后面调优会顺很多。
