Claude Codeのcurrent_usageで直近リクエストの内訳を読む
Claude Code statuslineのcontext_window.current_usageで、直近APIレスポンスのトークン内訳とキャッシュ利用量を読み取り、拡張コンテキストウィンドウを見分ける方法をまとめます。
Claude Codeのstatuslineがstdinで受け取るJSONには、context_window.current_usageという、直近のAPIレスポンス1回分のトークン内訳を持つフィールドがあります。似た名前のtotal_input_tokensと何が違うのか、いつnullになるのか、そして拡張コンテキストウィンドウで動いているかをどう見分けるのかをまとめます。
current_usageとは何か
context_window.current_usageは、直近のAPIレスポンス1回分のトークン数を4つのカテゴリーに分けて持つオブジェクトです。
| フィールド | 内容 |
|---|---|
input_tokens | 内容キャッシュを経由しない、生の入力トークン |
output_tokens | 内容直近のレスポンスでモデルが生成した出力トークン |
cache_creation_input_tokens | 内容直近のリクエストでキャッシュに新規書き込みされたトークン |
cache_read_input_tokens | 内容直近のリクエストでキャッシュから読み込まれたトークン |
キャッシュの効き具合をライブで見る最も直接的な方法は、statuslineスクリプトでこのcurrent_usageオブジェクトを読むことです。used_percentageのような集計値だけでは、入力のうちどれだけがキャッシュ経由かまでは分かりません。内訳をそのまま出したいときは、この4フィールドを直接読みます。
/contextの内訳と混同しやすいので、軸の違いを先に分けておきます。
同じ「トークンの内訳」でも軸が違う
/context
システムプロンプトやCLAUDE.md、MCPツールなどのカテゴリごとに分けます。最後のレスポンス以降に増えたメッセージの推定分も足されるので、statuslineより大きく読めることがあります。
current_usage
発生源は区別しません。直近1回のレスポンスを、生の入力・キャッシュ書き込み・キャッシュ読み込み・出力に分けます。
total_input_tokensとの違い
紛らわしいのは、context_window.total_input_tokensという別フィールドの存在です。名前だけを見ると「セッション開始からの累計入力」に見えますが、実際は違います。total_input_tokensはinput_tokens・cache_creation_input_tokens・cache_read_input_tokensの3つを合算した値で、current_usageと同じ、直近のAPIレスポンス1回分を指します。累計ではありません。
つまり両者は同じ時点・同じリクエストの数値を、合算して見るか内訳で見るかの違いでしかありません。使い分けは単純です。
| 知りたいこと | 使うフィールド |
|---|---|
| いま文脈がどれだけ埋まっているか(進捗バー表示など) | 使うフィールドcontext_window.used_percentage または total_input_tokens |
| キャッシュ読み込みと新規入力の比率 | 使うフィールドcontext_window.current_usageの4フィールド |
| 直近レスポンスの出力トークン数だけ | 使うフィールドcurrent_usage.output_tokens(total_output_tokensも同じ値を指す) |
セッションを通じた累計コストを出したいなら、current_usageでもtotal_input_tokensでもなくcost.total_cost_usdを使います。この2つのフィールドは、あくまで「直近レスポンス時点のコンテキストウィンドウの中身」を映すスナップショットです。
完全なJSONスキーマの例では、current_usageがinput_tokens: 8500・cache_creation_input_tokens: 5000・cache_read_input_tokens: 2000のとき、total_input_tokensは15500になっています。8500+5000+2000の合計と一致し、output_tokensの1200はこの合計には含まれていません。この数値の対応関係を覚えておくと、自作のstatuslineで内訳から合計を計算し直したときに、値がずれていないかの検算に使えます。
nullになる2つのタイミング
current_usageは常に値が入っているわけではなく、セッションの途中で2回nullに戻ります。
current_usageがnullになる区間
- 起動〜最初の応答null
statuslineがまだAPIレスポンスを受け取っていない状態です。
total_input_tokensとtotal_output_tokensはこの間0です。 - 最初の応答の後値が入る
直近のレスポンスの内訳が入ります。以降はターンごとに上書きされます。
- /compact の完了直後再びnull
要約が終わってから次のAPIレスポンスが返るまで続きます。
/compactの完了はstatuslineの再実行トリガーの1つでもあるので、nullの状態でスクリプトが呼ばれます。
input=$(cat)
cache_read=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0')input_tokens・cache_creation_input_tokens・output_tokensも同じ形で// 0を付けます。
used_percentage・remaining_percentageもセッション序盤はnullになり得るので、同じフォールバックを付けます。
used_percentageが数えているのは入力トークンだけ
context_window.used_percentageは便利な計算済みフィールドですが、計算式を知らずに使うと解釈を誤ります。この値はinput_tokens + cache_creation_input_tokens + cache_read_input_tokensだけから算出され、output_tokensは含みません。
自分でcurrent_usageから同じ割合を再計算するときは、この入力トークンだけの式に合わせます。output_tokensを分子に含めると、used_percentageより高い値になります。長い応答を生成した直後ほど差が開きます。
cache_creationとcache_readの比率が示すもの
cache_creation_input_tokensは書き込みレート、cache_read_input_tokensは書き込みより安いキャッシュ読み取りレートで課金されます。read側が多いほど、同じ文脈でも費用は下がります。
read対creationの比率が高いのは、キャッシュがよく効いているサインです。creationがターンをまたいで高いままなら、会話の先頭側(プレフィックス)が変わっています。プレフィックスを変える主な操作は、/modelでのモデル切り替え、opusplanでのプランモードの切り替え、/compactです。モデルごとにキャッシュが別なので、切り替えた次のリクエストは履歴全体を読み直します。
セッション途中でeffortレベルを変えたときも、ほとんどのモデルでは同じ結果になります。Opus 5.5・Sonnet 5.5・Fable 5.1は、APIキーとサブスクリプションならキャッシュが保持されます。クラウドプロバイダー経由などでは対象外です。
CLAUDE.mdの編集は、原因の候補から外れます。プロジェクトルートとユーザーレベルのCLAUDE.mdはセッション開始時に1度だけ読み込まれ、編集してもキャッシュは崩れず、内容も次の/clear・/compact・再起動まで反映されません。
TTL(キャッシュの生存期間)も、creationの増え方を左右します。Claude Codeはサブスクリプションのプラン内使用量にいる間だけ、メイン会話に1時間TTLを要求します。使用量クレジットに入る、APIキーで使う、クラウドプロバイダー経由で使うといった場合は、メイン会話も5分TTLです。5分TTLでは、アイドルが5分を超えただけでもcreationが跳ねます。1時間TTLは長い中断をまたいでキャッシュを温存できる一方、書き込みレートが高く、5分以内の短い作業が続くだけなら割高になります。
どちらのTTLで書き込まれたかはcurrent_usageには出ません。claude -p "hello" --output-format jsonを実行し、結果のusage.cache_creationにあるephemeral_1h_input_tokensとephemeral_5m_input_tokensで確認します。
creationが高いターンの切り分け
- 1
直前に操作したかを思い出す
前述のプレフィックスを変える操作のいずれかなら、一度きりの再構築です。
/compact後の再構築はexpected_rebuildsに数えられ、missesには入りません。 - 2
`prompt_cache`のTTLを見る
ttlが"5m"で、前のターンから5分以上空いていたなら、期限切れが原因です。expires_atは、キャッシュが冷える時刻(エポック秒)です。 - 3
`/usage`で原因表示を見る
v2.1.251以降は、セッションのブロックに
Prompt cache (main)の行が出ます。v2.1.260以降は、直近のミスの推定原因(tools_changed・system_prompt_changed・ttl_expired_5mなど)も出ます。
セッション全体の累計比率はprompt_cache.hit_ratioが持ちます。メイン会話のレスポンスを通じた累計で、サブエージェントのリクエストは含みません。current_usageベースの比率は直近1回だけを見るので、両方を並べると、平均と直近の落ち込みの差が見えます。キャッシュがどの単位で共有・分離されるかはClaudeのプロンプトキャッシュの仕組みで扱っています。
context_window_sizeで拡張コンテキストウィンドウを見分ける
context_window.context_window_sizeは、そのモデルが持つコンテキストウィンドウの上限をトークン数で返します。既定は200000で、拡張コンテキストに対応するモデルでは1000000になります。
statuslineスクリプトの中でこのフィールドの値を見るだけで、いま拡張コンテキストウィンドウで動いているセッションかを判定できます。
input=$(cat)
size=$(echo "$input" | jq -r '.context_window.context_window_size // 200000')
if [ "$size" -eq 1000000 ]; then
echo "🔭 拡張コンテキスト"
fi似た名前のフィールドにexceeds_200k_tokensがありますが、これは別物です。直近レスポンスの合計トークン数(入力・キャッシュ・出力の合算)が200kを超えたかどうかを、実際のウィンドウサイズに関係なく固定のしきい値で判定するフラグです。拡張コンテキストウィンドウのモデルでcontext_window_sizeが1000000の状態でも、使用量が200kを超えていればexceeds_200k_tokensはtrueになります。「拡張コンテキストで動いているか」を知りたいときはcontext_window_size、「大量のトークンを使っているか」を知りたいときはexceeds_200k_tokensと分けて使います。対応モデルの一覧や換算目安、コスト設計はClaude 1Mコンテキストの実務活用にまとめています。この固定しきい値は、拡張コンテキストウィンドウのセッションで誤警告につながることがあります。詳しくはexceeds_200k_tokensとは — 拡張コンテキストウィンドウでも200kで判定される固定しきい値で扱っています。
直近リクエストのキャッシュ内訳を表示するstatusline
current_usageの4フィールドを組み合わせると、直近1回のリクエストがどれだけキャッシュに乗ったかを、その場でパーセント表示できます。
input=$(cat)
fresh=$(echo "$input" | jq -r '.context_window.current_usage.input_tokens // 0')
write=$(echo "$input" | jq -r '.context_window.current_usage.cache_creation_input_tokens // 0')
read=$(echo "$input" | jq -r '.context_window.current_usage.cache_read_input_tokens // 0')
total=$((fresh + write + read))
if [ "$total" -gt 0 ]; then
hit=$((read * 100 / total))
else
hit=0
fi
echo "💾 直近リクエストのキャッシュ命中率 ${hit}%"モックの入力で動かすと、次の出力になります。current_usageがフィールドの例どおり(入力8500・書き込み5000・読み込み2000)なら、2000÷15500で12%です。
echo '{"context_window":{"current_usage":{"input_tokens":8500,"output_tokens":1200,"cache_creation_input_tokens":5000,"cache_read_input_tokens":2000}}}' | bash statusline.sh
echo '{"context_window":{"current_usage":null}}' | bash statusline.sh💾 直近リクエストのキャッシュ命中率 12%
💾 直近リクエストのキャッシュ命中率 0%nullのときの0%は、キャッシュが効いていないのではなく、まだ数えるレスポンスが無いだけです。上のスクリプトは、キャッシュが崩れたターンの切り分けに向きます。
サブエージェントの行にcurrent_usage相当のフィールドはない
メインのstatusLineが受け取るcontext_window.current_usageは、メインセッションの直近リクエストだけを表します。並行して動くサブエージェントの行(subagentStatusLine)が受け取るtasks配列の要素には、contextWindowSize(そのモデルのコンテキストウィンドウ上限)とtokenCount(トークン数)があります。input_tokensやcache_read_input_tokensのようなキャッシュ内訳のフィールドは、フィールド一覧にありません。contextWindowSizeはv2.1.205以降です。
サブエージェントの文脈使用率はtokenCountをcontextWindowSizeで割れば出せます。メイン会話のキャッシュは、prompt_cacheのとおりサブエージェントのリクエストを数えないので、両者は別の数字です。statusLineとsubagentStatusLineは別の設定で、届くJSONも別です。
よくあるつまずき
// 0のフォールバックを忘れ、nullという文字列が[ -gt ]やprintf %dでエラーになる
まとめ
statuslineに何を出すかは、見たい時間軸で決まります。直近1回のキャッシュ状態ならcurrent_usage、セッション全体の傾向ならprompt_cacheか/usageです。
statuslineの組み立てはClaude Code statuslineの設定と表示項目の選び方、文脈の中身はClaude Codeのコンテキストウィンドウを可視化して中身を確認する方法で扱っています。