寫於 2026 年 8 月 13 日(補 8 月 12 日的排程),9 月才上線(部落格的發佈額度 8 月 10 日就用完了,這批稿子要等到九月才發得出去)。文中的版本號與「目前」都指 8 月 13 日的狀態,Claude Code 更新很快,你讀到時可能已經又改過了。

你在 session 中途存下去的那份 CLAUDE.md,Claude 這一輪不會讀到。它會繼續照 session 啟動時載入的那個版本工作,直到你 /clear/compact 或重開。

這句話是官方文件寫的,不是我測的:

“Your project-root and user-level CLAUDE.md files are read once at session start and held in memory. Editing them mid-session does not invalidate the cache, but the edit also doesn’t apply.”

這篇全部來自官方文件,我沒有跑對照實驗去量每一條的實際 token 數。站上之前寫過的兩篇 prompt caching,講的是你自己呼叫 API 時怎麼放 cache_control breakpoint。這篇的角度不同:Claude Code 這個 client 自己在幫你排快取,而你按下哪些鍵會把它打掉。

為什麼改了不生效,這件事其實很合理

快取的比對方式是關鍵。API 拿你這次請求的開頭去跟最近處理過的內容比對,比對是精確的,前面任何一個字改了,後面全部重算。官方講得很絕:

“The match is exact, so a change anywhere in the prefix recomputes everything after it. There is no per-file or per-segment caching.”

沒有分段快取。想像你去影印店印一疊裝訂好的講義,第 3 頁改一個錯字,整本後面全部重印,不能只換那一頁。你的 session 就是這疊講義,Claude Code 把它分成三層:

內容 什麼時候變
System prompt 核心指令、工具定義、output style 載入的工具集合改變,或 Claude Code 升版
Project context CLAUDE.md、auto memory、未指定範圍的 rules session 啟動,或 /clear/compact 之後
Conversation 你的訊息、Claude 的回覆、工具結果 每一輪

CLAUDE.md 在第二層,位置在整疊講義的前面。中途重讀它就等於改前面那幾頁,代價是後面全部重印。所以 Claude Code 選了另一條路:不重讀。

改 output style 也一樣。它屬於 system prompt 層,session 啟動時讀一次,中途用 /config 改它不炸快取,但也不會生效。這兩條是同一個機制的兩個症狀。

有個例外值得記著:子目錄裡的 nested CLAUDE.md、還有帶 paths: frontmatter 的 rules,是「Claude 第一次讀到符合的檔案」才載入的。在它載入之前編輯有效,載入之後就變成對話歷史的一部分,改了也不會回頭生效。

八件會炸的事

官方直接列了清單。會讓下一輪整份重算的是這些:換模型、換 effort level、開 fast mode、連上或斷開 MCP server、開關 plugin、把一整支工具設成 deny、/compact、Claude Code 升版。

幾條要展開講,因為魔鬼在細節裡。

opusplan 這個設定藏了一個陷阱。它在 plan mode 時解析成 Opus、執行時解析成 Sonnet,所以你每按一次 plan mode 開關,都是一次換模型,快取從零開始。另外 Fable 5 與 Opus 5 上的自動 fallback 也算換模型——安全分類器攔下某個請求、該類別又有 fallback 模型時,Claude Code 會換模型重跑,session 接著在那個模型上繼續。

effort level 也是各自有各自的快取,同一個模型換 effort 一樣整份重算,Claude Code 會先問你要不要套用。

fast mode 只付一次錢。它加的是一個 request header,header 是快取 key 的一部分,所以在 session 開頭打開比在深處打開便宜。官方明說這筆成本一次對話只收一次:之後 Claude Code 會持續送這個 header,只調整速度設定,而速度設定不屬於快取 key。關掉 fast mode、rate limit 之後自動退回標準速度、再打開,這三件事都不會破壞快取。

MCP 這條要看模式。在 deferred tools(支援的模型上是預設值)之下,server 連上、斷開、改變工具清單,只是往後追加內容,不會擾動已經快取的部分。真正會炸的是「工具定義直接載進 prefix」的那種情形。另外改 MCP 設定檔本身不會動到快取,因為新設定要等重啟才生效,那時候才發生連線或斷線。

/advisor 是個例外:它的定義坐在 cache breakpoint 之後,所以開關 advisor 不會弄壞已快取的 prefix。

plugin 那邊比想像中溫和。skills、commands、agents、hooks、LSP servers、monitors、themes 都不會讓快取失效,唯一的例外是提供 MCP server 的 plugin。要是重新載入會觸發整份重讀,/reload-plugins 會先跳警告並且不執行,你得加 --force 才會硬套。反過來,把你這個 session 早先啟用的 plugin 停掉,請求形狀會還原成之前那個,如果那份 prefix 還在存活期內,下一個請求會直接讀到舊的快取條目。

那條最實用的:deny rule 加對了不痛,加錯了整份重算

這條我覺得是全篇最值得記住的:

“Adding a bare tool name like Bash or WebFetch as a deny rule removes that tool from Claude’s context entirely. Built-in tool definitions load into the system prompt layer, so adding or removing one of these rules mid-session invalidates the cache.”

裸工具名(BashWebFetch)、等價的 Bash(*)、還有 "*" 這種工具名位置的 glob,會把那支工具整個從 Claude 的 context 裡拿掉,動的是 system prompt 層,所以炸。

帶參數的就不會:Bash(rm *) 這種指定範圍的 deny rule,還有所有 allow 與 ask 規則,都不改變 Claude 看得到哪些工具,快取安全。

所以 session 中途想擋東西,寫 Bash(rm *),不要寫 Bash。同一個意圖,兩種寫法,代價差一整份 prefix。

想放棄一條路,用 /rewind 不要用 /compact

這兩個指令看起來都是「把對話弄短」,快取行為完全相反。

/rewind 把對話截回到早先某一輪,剩下的歷史就是當初建快取時的同一份內容。那個 prefix 一直被後面每一輪讀過,所以就算原本那一輪已經過了 TTL,條目還是熱的。

/compact 是生一份新的短歷史換掉舊的,講義的後半段等於重印一次。官方 tip 講得很明白:

“If you’ve gone down a path you want to abandon entirely, /rewind to an earlier turn instead. Rewinding truncates back to a prefix that is already cached, rather than building a new one as compaction does.”

/compact 的成本還跟時機有關。快取還熱的時候,那個請求會從快取讀你的 prefix,所以中途 compact 的花費比 context 大小看起來的要少得多,大部分時間花在生成摘要。反過來,休息時間超過快取存活期之後再回來,沒有快取可讀,摘要請求要把整段歷史當成未快取的輸入重新處理。這就是為什麼恢復一個舊 session 的時候 /compact 最貴。

升版也是同一個坑。自動更新在背景下載、下次啟動才套用,絕不會在 session 中途換掉。但升版之後恢復舊 session,整段對話歷史會在新的 system prompt 後面重新處理,一次 cache hit 都沒有。歷史越長越貴,回到一個長 session 的第一輪,可能是你送出去最貴的一個請求。想控制升版時機的話,DISABLE_AUTOUPDATER=1

八件不會炸的事,跟一個沒人講的範圍問題

不會讓快取失效的:改 repo 裡的檔案、中途改 CLAUDE.md、改 output style、改 permission mode、叫用 skills 與 commands、跑 /recap、rewind、開 subagent。

其中兩條前面講過,不炸但也不生效。剩下的可以放心用。

subagent 這條值得多說一句。它會開一段自己的對話,有自己的 system prompt 和工具集,跟父層是分開的,所以它建自己的快取,第一次呼叫沒有 cache hit,之後在自己的輪次裡慢慢熱起來。而且 subagent 用五分鐘 TTL,就算你是訂閱制也一樣,因為自動的一小時 TTL 只給主對話。fork 相反,它完整繼承父層的 system prompt、工具與對話歷史,第一個請求就讀得到父層的快取。

範圍這件事更少人知道:快取實際上綁在一台機器的一個目錄上。

“The system prompt embeds the working directory, platform, shell, OS version, and auto-memory paths, so two sessions in different directories build different prefixes and miss each other’s cache. That includes worktrees of the same repository.”

同一個 repo 的兩個 worktree,各自有各自的工作目錄,所以互相吃不到對方的快取。同一個目錄裡平行跑的 session 反而是互通的,prefix 一樣就讀彼此的快取。前後接續的 session 要共用 prefix,還得看啟動時的 git 狀態快照對不對得上,因為 system prompt 也記了分支與最近的 commit。

TTL 是誰決定的

不是你,是你的認證方式決定的,除非你動環境變數。

訂閱制之下,Claude Code 會自動去要一小時 TTL,所以中間離開一小時之內回來快取還在。開始吃 usage credits 的時候,一小時 TTL 的寫入成本比五分鐘高,Claude Code 會自動降回短的;想維持一小時就設 ENABLE_PROMPT_CACHING_1H=1。用 API key 或第三方平台的人是按 token 計價,預設就是便宜的五分鐘,要長的同樣設這個變數。

反方向也有:FORCE_PROMPT_CACHING_5M=1 不管認證方式一律壓回五分鐘,官方說這在你想除錯快取行為、比較兩種 TTL、或要覆蓋 managed settings 裡別人設的 ENABLE_PROMPT_CACHING_1H 時有用。

完全關掉的變數有五個,這是官方表格的全集:DISABLE_PROMPT_CACHING(全部模型)、DISABLE_PROMPT_CACHING_HAIKUDISABLE_PROMPT_CACHING_SONNETDISABLE_PROMPT_CACHING_OPUSDISABLE_PROMPT_CACHING_FABLE。官方對這件事的立場只有一句:"For normal use, leave caching enabled."

要看有沒有在作用,盯兩個欄位:cache_creation_input_tokens 是這一輪寫進快取的量,按寫入費率計;cache_read_input_tokens 是從快取讀出來的量,大約是標準輸入費率的一成。官方說最直接的觀測方式是寫個 statusline script 去讀 current_usage 物件。判準很簡單:讀得多、寫得少,快取在幹活;每一輪寫入都居高不下,代表你的 prefix 有東西一直在變。至於「多少比例算健康」,文件沒給數字,我也不編一個給你。

這一整份清單其實只有一條規則

回到開頭那句話。CLAUDE.md 改了不生效,聽起來像個 bug,實際上是那疊講義的必然結果:你能便宜地做的事只有往後面追加,任何動到前面的操作都要重印全本。

從這一條可以自己推出整份清單,不用背。判準只有一個:這個動作有沒有動到講義前面那幾頁。Bash 這條 deny rule 貴而 Bash(rm *) 不貴,就是因為前者改變了「Claude 看得到哪些工具」,而那是印在前段的東西。

實務上留一句可帶走的:模型和 effort 在 session 開頭就選好,/compact 留給任務之間的自然斷點。官方自己的建議就是這樣,理由也只有一句——任務中途改的東西越少,cache 命中率越高。

還有一個延伸的用法。既然快取綁目錄、綁啟動時的 git 狀態,那 monorepo 裡怎麼切目錄又不重燒,站上寫過一篇專門講 /cd 的,可以接著看。

原文來源:Claude Code Prompt caching 官方文件Context windowReduce token usageLessons from building Claude Code: prompt caching is everything