Max Nardit
← 記事
12 mindev

Claude Code のアイドル時コンパクション:今の安い要約か、後でキャッシュを丸ごと書き直すか

アイドル時コンパクションが動くかどうかは5つの条件で決まり、デフォルトではそのうち2つが、API キーのセッションと、200K ウィンドウのセッションの大半を対象外にします。実際に対象になるのは誰か、このトレードオフがキャッシュトークンでいくらになるか、調整や無効化の方法をまとめます。

目次

10月14日にリリースされた Claude Code 2.1.299 には、自分では呼び出さない機能が加わりました。大きな会話をターミナルで約54分放置すると、1時間のプロンプトキャッシュが切れる数分前に、Claude Code が自動でコンパクションします。設定リファレンスによると、戻ってきたときの会話には次の通知が表示されます。

Compacted while idle, before the prompt cache expired

リリースノートは、再処理を省ける機能として紹介しています。それは事実ですが、同時に自分の代わりに下される判断でもあり、そのコストは測れても、失うものは測れません。奇妙なのは、誰が対象になるかです。デフォルトでこの機能が動くのは、プランの利用枠内にいるサブスクリプション利用者で、彼らが払うのはクォータです。その換算レートを Anthropic は公表していません。節約をドルで実感できるはずの API キー利用者は、キャッシュ書き込みのたびに2倍払わない限り対象外です。そして節約がいくらであれ、履歴を置き換える要約は、誰も見ていないあいだに書かれるようになりました。

アイドル時の挙動そのものはドキュメントで確認したもので、実際に観察したわけではありません。自分で実行したのは、下で紹介する 2.1.300 での TTL チェックだけです。

Claude Code のアイドル時コンパクションは実際に何をするのか

通常のコンパクションを、キャッシュがまだ温かいうちに前倒しで実行します。コンパクションは、会話全体に要約の指示を付けて1つのリクエストとして送ります。54分の時点ではそのプレフィックスはまだキャッシュに残っているので、リクエストはプレフィックスをキャッシュ読み取りの料金で読み込みます。61分ではもう残っておらず、次に何を送っても履歴全体が再処理されます。

プロンプトキャッシュのページははっきり書いています。キャッシュの有効期間より長い休憩のあと、要約リクエストは「reprocesses the full history as uncached input」(履歴全体をキャッシュなしの入力として再処理する)。アイドル時コンパクションは、この要約を最後の安いタイミングに移すものです。

Claude Code のアイドル時コンパクションはいつ動くのか

設定リファレンスにある5つの条件がすべてそろったときだけです。まず、セッションが対話型のターミナルセッションであること。claude -p の実行や Agent SDK のセッションには適用されません。次に、会話がプロンプトキャッシュの TTL 1時間で動いていること。ほとんどの人はこの条件で外れます。3つ目に、Claude Code が Anthropic からフィーチャーフラグを取得できること。DISABLE_GROWTHBOOK=1 や CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC でこれを止めると、アイドル時コンパクションも一緒に止まります。4つ目に、コンテキストがしきい値に達していること。デフォルトは 200,000 トークンです。最後に、最後のリクエストから約54分が過ぎ、その時点でマシンが起きていること。54分の時点でスリープしているノート PC では、コンパクションは起きません。

自分のエージェントは Max サブスクリプションで、tmux 上の対話型 Claude Code セッションとして動いているので、1つ目の条件は満たしていますし、プランの利用枠内にいる限り2つ目も満たします。条件が選び出しているのは、まさにこういう使い方です。API キーでヘッドレスのジョブを回すチームには、まったく関係ありません。

Claude Code のどのセッションが TTL 1時間のキャッシュを使うのか

デフォルトでは、Claude サブスクリプションでプランに含まれる利用枠内にいるメインの会話だけです。プロンプトキャッシュのページに区分が載っています。サブスクリプションではメインの会話が1時間、API キー、利用クレジット、クラウドプロバイダーでは5分です。サブエージェント、ワークフロー、コンパクション自体はどちらの場合も5分で、Anthropic がサーバー側で1時間に設定している一部の補助リクエストだけが例外です。サブスクリプションがプランの上限を超えて利用クレジットを使い始めると、Claude Code はデフォルトでメインの会話を5分に下げ、TTL を自分で固定していない限り、アイドル時コンパクションは適用されなくなります。

どの TTL が使われているかは、1時間待たなくても確認できます。ドキュメントは単発の実行を勧めています。

shell
claude -p "Reply with the single word: ok" --output-format json

サブスクリプションの 2.1.300 では、usage ブロックのキャッシュ書き込みがすべて1時間の有効期間で返ってきました。

json
"cache_creation": {
  "ephemeral_1h_input_tokens": 34503,
  "ephemeral_5m_input_tokens": 0
}

-p の実行は、対話型のターンと同じメイン会話の区分に入るので、自分の課金にどのデフォルトが適用されるかがわかります。書き込みが ephemeral_5m_input_tokens に入るなら、TTL を変えるまで対話型セッションも対象になりません。API キーで有効にするには、メインの会話を1時間に設定します。

json
{
  "promptCacheTtl": "1h"
}

これは無料ではありません。1時間のキャッシュ書き込みは基本入力価格の2倍、5分の書き込みは1.25倍で課金されます。ドキュメントも、5分以上アイドルにならない短い作業の繰り返しでは、長い TTL は損になると注意しています。

Claude Code の 200K しきい値はコンテキストウィンドウに合っているか

合うのは 1M トークンのウィンドウだけで、200K ウィンドウではデフォルトのままだとほぼ動きません。200K ウィンドウの自動コンパクションは会話が 200,000 トークンに達する前に走るので、会話が条件を満たすほど大きくなることはまれです。設定リファレンスは、そうしたセッションではしきい値を 150,000 に下げるよう勧めています。ネイティブで 1M ウィンドウを持つモデル(Opus 5.5、Sonnet 5 以降、Haiku 5.5、Fable の各モデル)は約 967K になってから自動コンパクションするので、200K のデフォルトが効いてきます。自分の TTL チェックでは、Opus 5.5 について contextWindow: 1000000 が返りました。

しきい値は設定ファイルの env ブロックで指定します。100,000 未満の値は下限の 100,000 に引き上げられます。

json
{
  "env": {
    "CLAUDE_CODE_IDLE_COMPACT_MIN_TOKENS": "150000"
  }
}

リリースノートには、この変数と設定には 2.1.290 以降が必要とありますが、機能自体が入ったのは 2.1.299 で、その差についての説明はありません。claude --version を実行し、実際の最低バージョンは 2.1.299 だと考えておくのが無難です。

Claude Code のアイドル時コンパクションは、冷えた状態で戻るのと比べていくらかかるのか

古いプレフィックスだけで見れば、温かいうちの要約は冷えた状態での書き直しよりおよそ40倍安くなりますが、それで全部ではありません。Opus 5.5 で 200K トークンの会話を例に、Anthropic が公表している倍率を使って基本入力価格の単位で数えます。

経路200K のプレフィックスに起きること単位
54分時点のアイドル時コンパクション基本価格の0.05倍でキャッシュから読み取り(Opus 5.5 と Sonnet 5.5。ほかの多くのモデルでは0.1)約 10K
70分時点で戻る、コンパクションなし1時間の料金(基本価格の2倍)で書き直し約 400K

10K は読み取りだけです。アイドル時コンパクションでは要約の出力トークンも払いますし、次のターンでは短くなったコンテキストを組み直します。その中身は、要約に加えて、Claude Code がコンパクションのたびに復元する指示、メモリ、ファイル、スキルです。その一部は既存のシステムプロンプトのキャッシュに当たり、残りは新たに書き込まれます。つまり実際の節約は40倍より小さく、どこまで小さくなるかは復元される量しだいです。

注意点がもう2つあります。プランの利用枠内のサブスクリプションでは、どれもドルでは課金されません。消費されるのはクォータで、そのクォータがキャッシュの読み取りと書き込みをどう重み付けしているかを Anthropic は公表していません。そして安い経路が得になるのは、戻ってきた場合だけです。ちょうど1時間でタイマーに終了させられるセッションや、放置したセッションは、誰も読まない要約に払うことになります。

Claude Code のコンパクション要約で失われるもの

モデルの作業コンテキストから、会話の原文が消えます。ディスク上のセッション記録は残り、変わるのは次のターンで Claude が見る内容です。コンテキストウィンドウのドキュメントによると、要約に残るのは、依頼と意図、主要な技術的概念、読んだり変更したりしたファイルと重要な抜粋、エラーとその修正、未完了のタスク、現在の作業です。ツール出力の全文と途中の推論はコンテキストから落ちます。

基本の指示と出力スタイルは、コンパクション後も適用されたままです。Claude Code は、プロジェクトルートの CLAUDE.md、パス指定のないルール、自動メモリをディスクから読み直し、Claude が触った最近変更されたファイルを最大5つ読み直し(5,000 トークンを超えるファイルはパスだけが戻ります)、呼び出したスキルの本文を再注入し(1つあたり 5,000 トークン、合計 25,000 トークンが上限で、古いものから外れます)、ソース compact に一致する SessionStart フックの出力を加えます。paths: フロントマターを持つルールと、ネストした CLAUDE.md ファイルは、履歴と一緒に要約されて消え、Claude が該当するファイルにまた触れたときにだけ読み込まれます。

ですから、アイドルかどうかに関係なく、コンパクションを越えて残す必要があるものは、パス指定のないルール、プロジェクトルートの CLAUDE.md、または compact 向けの SessionStart フックに置きます。チャットで口にしただけの決定こそ、要約が言い換えてしまうものです。以前、戻ってくる要約は慎重に扱うべき入力であってセーブデータではない、と書きました。アイドル時コンパクションでは、その要約が書かれる場面に立ち会うことすらできません。

ドキュメントが答えていないケースが1つあります。アイドル時間は最後のリクエストから測られ、バックグラウンドのコマンドはコンパクションをまたいで動き続けます。ただ、実行中のバックグラウンドコマンドや予約済みのウェイクアップがアイドルタイマーを止めるのかどうかは、どこにも書かれていません。長いビルドの間セッションを待たせておくなら、タイマーが止まる、止まらないのどちらを前提にするにしても、その前に試しておく価値があります。

Claude Code のアイドル時コンパクションを無効にする方法

どの設定ファイルでも "idleCompaction": false を書けば、アイドル時コンパクションだけが無効になります(2.1.290 以降。それより古いバージョンでは代わりに autoCompactEnabled を無効にします)。DISABLE_AUTO_COMPACT=1 は、アイドル時コンパクションと通常の自動コンパクションをまとめて無効にし、手動の /compact だけが残ります。idleCompaction はどの設定ファイルにも書けるので、1つのプロジェクトだけ .claude/settings.local.json で無効にして、ほかでは有効のままにできます。

json
{
  "idleCompaction": false
}

計測したわけではない私見ですが、作業の中身がファイルにある場合、たとえばコーディングや保守では有効のままにしておきます。要約と読み直したファイルで、大事なものはほぼ運べるからです。逆に価値が会話の流れそのものにある場合、たとえば長い議論や、文の途中から再開するつもりの設計の話し合いでは、無効にするかしきい値を上げます。そこでは、言い換えられた決定に比べれば入力の節約は小さなものです。

Claude Code のアイドル時コンパクションを OpenTelemetry で計測する方法

OpenTelemetry のエクスポーターを有効にして、claude_code.api_request イベントを読みます。手元で一番手早いのは、コンソールに出力する設定です。

shell
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=console
export OTEL_METRICS_EXPORTER=console

必要な属性は3つです。query_source はリクエストを送ったサブシステムを示し、compact はアイドルかどうかに関係なくコンパクションの呼び出しを表すので、前のリクエストからの経過時間とトランスクリプトの通知と組み合わせて見ます。その呼び出しの cache_read_tokens で、温かいうちに読んだかどうかがわかります。さらに 2.1.300 で cache_creation_5m_tokens と cache_creation_1h_tokens が加わり、キャッシュ書き込みを有効期間ごとに分けられるようになりました。この分割は 2.1.300 のリリースノートに載っているもので、モニタリングのリファレンスには合算の cache_creation_tokens しかありません。温かいうちのアイドル時コンパクションは、キャッシュ読み取りの大きい compact リクエストのあとに、ずっと小さいコンパクション後のコンテキストを書き込むターンが続く形で見えます。戻って最初のメッセージで1時間の書き込みが大きければ、タイミングを逃した可能性があります。ただ、モデルの切り替えやプレフィックスの変更でも同じ形になるので、時間のせいにする前にその2つを確認してください。

OpenTelemetry がなくても、/usage に Prompt cache (main) の行があり、セッションのヒット率、ミスの回数、キャッシュが今温かいかどうかが表示されます(2.1.251 以降)。2.1.260 以降では、直近のミスの原因と思われるものも表示されます。API 側では、キャッシュ診断を使えば、プロンプトが変わったのか、変わっていないのにキャッシュのエントリが消えていただけなのかを見分けられます。

Claude Code のアイドル時コンパクションで最初に確認すべきこと

まず単発の TTL チェックを実行します。書き込みが5分なら、この機能は役に立たず、残る問題は1時間の書き込みに払う価値があるかどうかだけです。1時間なら、コンテキストウィンドウを確認します。200K なら、しきい値を下げるか、めったに動かないと割り切ります。そのうえで、会話の流れとファイルのどちらを失うと困るかを、プロジェクトごとに決めます。54分の時点で書かれる要約は安いものですが、同時に、セッションが先へ進む前に誰も目を通していない唯一のコンテキストでもあります。

01 / ディスカッション

コメント欄はありません。議論は X で行っています。

Max Nardit@mnardit

02 / ほかの記事

  1. Gemini 4 Argon が一般公開:Google が初日に報告した利用例と、12月1日に2倍になる価格

    Google が Argon について報告している利用例を7つ、出どころの記事とあわせて並べます。レビューの記録まで公開しているのは1つだけで、提案6件のうち採用は2件でした。残りは、発表が触れずドキュメントに任せた請求の話です。まず、long decode が入力をどう数えるかから始めます。

  2. Claude Managed Agents の dynamic workflows:ファンアウトはエージェントが書く、だから予算を先に決める

    新しい multiagent タイプではスイッチが最初からオンで、ラン開始を承認する仕組みはなく、唯一の金額上限はセッション作成時にしか付けられません。ドキュメントをもとにした設定ガイドです。最初のメッセージを送る前に決めておく 3 つの設定を扱います。

  3. Codex CLI のマネージド Git worktree: 始め方は 3 通り、モデルが呼ぶツールだけはリモートのデフォルトブランチから始まります

    Codex CLI 0.162.1 を使い捨てのリポジトリで実際に動かした記録です。チェックアウトがどこに作られるか、入口ごとにどのコミットから始まるか、.env と未コミットの編集がなぜ元の場所に残るか、作業をどうマージして戻すか、後片付けでディスクに何が残るかを確かめました。