中午離開一個多小時,回到那個從早上聊到現在的 session,照設定文件的說法,對話裡可能已經多了一行 Compacted while idle, before the prompt cache expired。你什麼都沒按,它趁你不在,把整段對話壓成了一份摘要。

它急著在你回來之前動手,理由寫在官方的 costs 頁:「your first message after a break longer than the cache lifetime misses the cache and reprocesses your full context.」休息時間超過快取壽命,回來的第一則訊息就會錯過快取,把整段 context 重新處理一次。同一段接著寫,訂閱方案內的快取壽命是一小時,改用 usage credits 之後降為五分鐘,API key 與雲端供應商預設五分鐘。

要是沒有它,一早上的對話,換來一句「好,繼續」整段重算。

這個功能叫 idle compaction。設定文件的描述是:對一段你已經離開的長對話,在 prompt cache 過期前不久先把它壓縮掉,你下一則訊息送出去的就是摘要,不是整段對話。

它是哪一版加的,兩份官方原文說法不同,我只能並陳。CHANGELOG 把它列在 ## 2.1.299 區塊的 Added 底下(2.1.299 上 npm 的時間是 2026 年 10 月 14 日 UTC),可是同一條寫的是「Both need v2.1.290 or later」;設定文件也寫「The key requires Claude Code v2.1.290 or later」(2.1.290 上 npm 是 2026 年 10 月 5 日 UTC)。CHANGELOG 從 2.1.290 到 2.1.296 的各區塊(中間沒有 2.1.297、2.1.298 這兩個版本號)都沒有出現 idle compaction,至於 2.1.290 的程式本身有沒有這個功能,我沒有查證。寫這篇時(10 月 16 日)本機 claude --version 回的是 2.1.301 (Claude Code)。

「快過期前先壓縮」聽起來像個貼心小功能。可是它挑的時間點,是被快取的運作方式逼出來的,而且要過五道關卡,任何一道沒過,它就安靜地不發生。

快取只認開頭

prompt caching 頁講快取怎麼比對,寫得很短:API 拿每個請求的開頭(文件叫它 prefix)去跟最近處理過的內容比對,「The match is exact, so a change anywhere in the prefix recomputes everything after it. There is no per-file or per-segment caching.」

比對是逐字的,前綴裡任何一處變了,後面全部重算。沒有「這個檔案還在快取裡」這種按檔案或按段落的快取。

想像你把一疊三百頁的講義寄放在影印店櫃台。下次去,只要你遞過去的稿子從第一頁開始跟寄放的那疊一模一樣,店員就直接從那疊接著印,只收新增頁數的錢。可是櫃台有規矩,一小時沒人來拿,那疊就清掉。你晚了五分鐘到,店員手上什麼都沒有,三百頁從第一頁重新掃描。

對話就是那疊講義。每一次你送出訊息,前面整段歷史都是前綴,快取暖著的時候只付新增的那一點;快取清掉了,前綴整段變回沒快取的輸入。

壓縮也得把整疊讀一遍

那回來先 /compact 一下不就好了?

不行。壓縮自己也是一個請求。要產生摘要,模型得先讀過整段歷史。prompt caching 頁寫得很明白:「After a break longer than the cache lifetime, there is no cache left to read, so the summarization request reprocesses the full history as uncached input. This is why /compact costs the most when you resume an old session.」

快取過期之後才壓縮,摘要請求一樣要把全部歷史當成沒快取的輸入讀一遍。所以回到一個舊 session 時跑 /compact,正好是它最貴的時候。

快取還暖著的時候,情況整個反過來:「While the cache is warm, that request reads your prefix from the cache, so a mid-session /compact costs a fraction of what the context size suggests and spends most of its time generating the summary.」同一個摘要請求,前綴可以從快取讀,費用只有 context 大小看起來那樣的一小部分,時間多半花在生成摘要本身。

把兩句擺在一起,idle compaction 的設計就說得通了。壓縮這個動作的成本,幾乎全看快取當下是暖是冷。等你回來再壓,一定是冷的;要壓得便宜,只能在你還沒回來、快取還沒清掉的那幾分鐘裡由它自己動手。設定文件寫的時間是閒置「about 54 minutes」,對照一小時的快取壽命,落在過期前不久。為什麼是 54 而不是 50 或 58,文件沒有解釋,我也不知道。

回到影印店:店員在清櫃台前最後幾分鐘,趁那疊講義還在手邊,把它濃縮成一頁摘要留給你。你回來遞過去的,就是那一頁。

壓縮本身也有代價。prompt caching 頁說,壓縮會用摘要取代你的訊息歷史,依設計會讓對話那一層的快取失效。摘要留下什麼、丟掉什麼,設定文件指向 context-window 頁的 what-survives-compaction 一段,那段原文我沒有讀到,所以這篇不判斷壓完之後少了哪些細節。

五道關卡,少一道就不發生

設定文件列了預設啟用的條件,原文用的是「meets all of these conditions」,五項全中才算。我把每一項跟「什麼情況會讓它過不了」排在一起:

條件(文件原文) 過不了的情況 對應的官方文件
Session:interactive terminal session 非互動執行,例如 -p 或 SDK settings-reference#idlecompaction
Prompt cache:one-hour prompt cache TTL 主對話不是一小時 TTL 同上、prompt-caching#which-ttl-each-request-gets
Feature flags:Claude Code can fetch feature flags from Anthropic 設了 DISABLE_GROWTHBOOK、DISABLE_TELEMETRY、DO_NOT_TRACK、CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC;或用 Amazon Bedrock、Microsoft Foundry 等第三方供應商(除非嵌入的主機平台設了 CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST);或 Claude apps gateway session env-vars#features-that-need-feature-flag-fetching
Size:context 達到門檻,預設 200,000 對話還沒長到門檻 settings-reference
Idle time:距上一個請求約 54 分鐘,且電腦當下醒著 閒置時間不夠,或電腦睡著了 settings-reference

第二道關卡,哪些情況預設是一小時,prompt caching 頁有一張表:

Request bucket Claude subscription, within plan usage Usage credits, API key, or cloud provider
Main conversation One hour Five minutes
Everything else Five minutes, except the server-controlled helper requests, which get one hour Five minutes

主對話的 TTL 也可以自己選,用 promptCacheTtl 設定或 CLAUDE_CODE_PROMPT_CACHE_TTL 環境變數,值只吃 5m 或 1h,文件寫兩者都需要 v2.1.242 以上。

五道裡面我覺得最容易踩到的是第三道,因為它跟 idle compaction 本身一點關係都沒有。如果你為了隱私或公司政策,在 shell 設定檔裡放過 DO_NOT_TRACK 或 DISABLE_TELEMETRY,要知道這兩個變數在 env-vars 表裡都寫著會一併關掉 feature flag 的抓取(每個變數設成哪些值才會關,文件說看各自那一列)。env-vars 頁有一段專門列「抓不到 flag 就用不了」的功能,清單最後一項就是在終端閒置時、一小時快取過期前不久壓縮長對話。你沒有碰過任何 compaction 設定,它就已經不在了,畫面上也不會有任何提示。

還有一個跟版本有關的小坑。同一頁寫,安裝之後、或升級到新增某個功能的版本之後的第一個 session,靠 flag 開啟的功能可能缺席;那個 session 抓到 flag 存在本機之後,下一個 session 才會有。剛升級完當天下午就等著看它出現,可能會落空。

第五道的「電腦當下醒著」也值得多看一眼。筆電闔上去吃飯,到第 54 分鐘時機器在睡覺,條件就沒成立。

兩個開關,三條關掉的路

要關掉它,設定文件給的是一個布林鍵,Scope 寫 Any file,預設 true:

1
2
3
{
"idleCompaction": false
}

門檻用環境變數調。env-vars 表寫 CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS 只吃正整數,其他值一律忽略,低於 100000 的會被抬到 100000,那是最低門檻。設定文件的範例是放進 settings.json 的 env:

1
2
3
4
5
{
"env": {
"CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS": "150000"
}
}

這個範例旁邊,文件只附了一句理由:「At the default, a conversation on a 200K context window auto-compacts before it reaches 200,000 tokens. This example lowers the threshold to 150,000 so that those conversations qualify」。在預設值下,200K context window 的對話在到達 200,000 tokens 之前就已經先 auto-compact 了,這個範例把門檻降到 150,000,讓這類對話也符合條件。我沒有實測過這個門檻的效果,這句就照原文放著,不往下延伸。

真正要小心的是關掉它的路其實有三條,副作用不一樣:

做法 關掉 idle compaction 一起關掉 auto-compact 手動 /compact
"idleCompaction": false 是 否 照常可用
"autoCompactEnabled": false 是 是 照常可用
DISABLE_AUTO_COMPACT=1 是 是 照常可用

DISABLE_AUTO_COMPACT 在 env-vars 表裡還寫著會覆蓋 autoCompactEnabled 設定。如果你只是不想要閒置時被壓縮,用第一條;後兩條會把「context 快滿時自動壓縮」一起拿掉,那是另一個機制,8 月那篇〈壓縮完那條規則為什麼沒回來〉講的就是它。

舊版本這邊有一條文件寫明的死路:idleCompaction 這個鍵在 v2.1.290 以前會被直接忽略,寫了也沒用,文件給的替代方式是關掉 autoCompactEnabled,代價是 auto-compact 一起沒了。

它到底有沒有發生過

除了回來時那行 Compacted while idle, before the prompt cache expired,costs 頁的 /usage 也看得到痕跡。文件給的 Prompt cache 那一行範例長這樣:

1
Prompt cache (main):   14 requests · 91% of input tokens from cache · 2 misses (last 6m 10s ago, 310.2k tokens re-cached) · 1 expected rebuild (compaction or tool-result clearing) · warm (1h TTL, last activity 40s ago)

裡面的 expected rebuild 就是 Claude Code 自己剛重寫過對話(壓縮或清掉舊的 tool result)造成的那種快取未命中,文件說它會另外計成 expected rebuild。整條 Prompt cache 行需要 v2.1.251 以上,未命中的可能原因說明則要 v2.1.260 以上。行尾括號裡的 1h TTL,也看得出主對話現在用的是哪一種 TTL。

想確認主對話拿到哪種 TTL,prompt caching 頁另外給了一個方法:跑 claude -p "hello" --output-format json,看結果裡的 usage.cache_creation,一小時的快取寫入記在 ephemeral_1h_input_tokens,五分鐘的記在 ephemeral_5m_input_tokens。這個指令我沒有執行過,欄位名稱照文件抄。

其實這篇從頭到尾都只讀了文件。我沒讓任何對話真的閒置 54 分鐘,沒看過那行 Compacted while idle 的實際畫面,也沒量過門檻變數的效果;Claude Code 本身我只跑過 claude --version。

我會怎麼設

預設開著,不動它。它要的條件很窄,真的觸發時,省掉的正是最貴的那一次整段重算;要付的代價是回來面對一份摘要,而那份摘要留下什麼,我前面說了,還沒讀到原文。

對話很少長到 200,000 tokens 的人,它預設根本輪不到,這整篇知道就好。

回來後少掉的細節如果對你的工作很要命,例如一早上累積的除錯線索,就用 "idleCompaction": false 單獨關它,別動 autoCompactEnabled。

環境裡有 DO_NOT_TRACK 或 DISABLE_TELEMETRY 的話,先去 env-vars 頁看那一列,確認你設的值會不會關掉 flag 抓取。這件事比任何門檻調整都優先。

趁暖做重寫

拆完這個功能,我比較在意的是它背後那條規則:任何會改寫對話前綴的動作,成本都看快取當下是暖是冷。

手動 /compact 也是一樣。文件已經說了,session 中途、快取還暖時壓,只付一小部分;隔了一段比快取壽命還長的時間回來才壓,最貴。所以如果你知道自己要離開一陣子,又確定這段對話之後要壓縮,在離開前壓會比回來後壓便宜。idle compaction 只是把這件事自動化,而且只在那五道關卡全過時才替你做。

快取活多久、怎麼選、帳單怎麼算,8 月那篇〈prompt cache 到底存在哪、活多久?〉拆過;哪些動作會讓快取整段失效,在〈中途改的 CLAUDE.md 這個 session 不算〉;手動壓縮什麼時候該按,7 月那篇〈Claude Code 的 /compact〉。

原文來源:Claude Code Docs:Settings reference(idleCompaction、Change the idle compaction threshold、autoCompactEnabled)、Claude Code Docs:Environment variables(CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS、DISABLE_AUTO_COMPACT、Features that need feature-flag fetching)、Claude Code Docs:Prompt caching、Claude Code Docs:Costs,皆以 2026 年 10 月 16 日讀取的版本為準;Claude Code CHANGELOG(2.1.299 區塊);版本上架時間取自 npm view @anthropic-ai/claude-code time(2026 年 10 月 16 日查詢)。