statuslineでspend_limitを表示する — Claude apps gatewayの支出上限を確認
Claude apps gateway経由の支出上限を、rate_limits.spend_limitでstatuslineに出すスクリプトと、ドル金額が入るバージョン条件、five_hour/seven_dayとの見分け方です。
Claude Codeのstatuslineには、rate_limitsオブジェクトの中にspend_limitという項目が入ることがあります。個人のPro/Maxプランが使うfive_hour・seven_dayとは別物で、Claude apps gatewayを経由し、かつ管理者がその開発者向けに支出上限を設定しているときだけ現れます。v2.1.251以降は消化率とリセット時刻、v2.1.284以降はドル金額と期間も入ります。
rate_limits.spend_limitが運ぶ情報
spend_limitが運ぶキーは5つあり、届くタイミングが2グループに分かれます。
| キー | 中身 | 届くタイミング |
|---|---|---|
used_percentage | 中身上限に対する消化率。上限を超えると100を上回る | 届くタイミング毎回のレスポンス |
resets_at | 中身期間がリセットされるUnixエポック秒 | 届くタイミング毎回のレスポンス |
used_usd | 中身見積もりの支出額(ドル) | 届くタイミング別リクエストで約5分ごと |
limit_usd | 中身上限額(ドル) | 届くタイミング同上 |
period | 中身daily・weekly・monthlyのいずれか | 届くタイミング同上 |
used_usdはgatewayがトークン数から計算した見積もりで、請求額そのものではありません。used_percentageより最大5分ほど古いことがあり、2つの数字が一時的にずれて見えるのは仕様どおりです。
five_hour・seven_dayとは形が似ているものの、指す対象が違います。five_hour・seven_dayはClaude.aiのサブスクリプションが持つレート制限で、spend_limitはgatewayの運用者が管理APIで設定した金額ベースの上限です。「spend limit」という呼び方はClaude Codeまわりで複数の仕組みに使われています。個人のPro/Max向けの支出上限や組織のAdmin settings側の支出上限とは別の概念です。呼び分けの全体像は「Could not update spend limit」の対処の一覧が詳しく、本記事が扱うのはgateway経由の1系統だけです。
どのバージョンで何が入るか
表示面ごとに、手元のClaude Codeとgatewayサーバーの最低バージョンが違います。
spend_limit まわりの対応バージョン
- v2.1.22575%・95%の自動警告
手元のClaude Codeとgatewayサーバーの両方がv2.1.225以降なら、最も消費が多い上限が75%と95%を超えた時点で警告が出ます。
- v2.1.251`/usage`のバーと`spend_limit`
手元のClaude Codeがv2.1.251以降なら、
/usageに「Spend limit」バーが出て、statuslineの入力にused_percentageとresets_atが入ります。サーバーはv2.1.225のままで足ります。 - v2.1.284ドル金額と期間
手元のClaude Codeとgatewayサーバーの両方がv2.1.284以降なら、
/usageのバーに「$271.40 / $500.00 spent this month」のような金額が出ます。statuslineの入力にもused_usd・limit_usd・periodが入ります。
ドル金額は取得に別リクエストを使うため、CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICを設定した環境ではそのリクエスト自体が省かれ、バーもstatuslineもパーセンテージだけになります。gatewayサーバーがv2.1.284より古い場合も同じです。この環境変数は、gatewayの導入手順でコンプライアンス上の設定として挙げられているものなので、組織によっては最初から設定済みです。
表示までに満たす前提条件
spend_limitが出るには、次の3つが同時に必要です。ひとつでも欠けるとフィールドごと現れません。
- Claude apps gatewayを経由してリクエストを送っていること
- 管理者がgatewayの管理APIで、あなた個人・あなたが属するIdPグループ・組織のいずれかに支出上限を設定していること。グループや組織の上限は各メンバーに個別に適用されるため、個人の上限が未設定でも出ます。三者とも未設定ならフィールドは出ません。設定手順はClaude apps gatewayで開発者ごとの支出上限を設定するにあります
- 手元のClaude Codeがv2.1.251以降であること
3つ目で上げるのは手元のClaude Codeで、gatewayサーバーはv2.1.225以降なら足ります。バージョンを混同すると「サーバーは新しいのにフィールドが出ない」という状態になります。手元のバージョンはclaude --versionで確認できます。
claude --versionrate_limitsオブジェクト自体、セッション内で最初のAPIレスポンスが返るまでは現れません。起動直後のstatuslineに何も出なくても、故障ではなくこの仕様どおりの挙動です。自分でgatewayへ切り替えた覚えがなくても、spend_limitが出るかどうかで、そのセッションがgateway経由かどうかを判別する手がかりになります。
spend_limitを含むstatuslineスクリプトを書く
statuslineはsettings.jsonのstatusLineで設定します。公式ドキュメントのサンプルスクリプトは、five_hour・seven_dayに加えてspend_limitも扱っています。ドル金額があれば金額を、なければパーセンテージを出す作りです。次のスクリプトはそこへ、しきい値に応じた色付けと期間の表示を足したものです。
#!/bin/bash
input=$(cat)
MODEL=$(echo "$input" | jq -r '.model.display_name')
FIVE_H=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
WEEK=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
SPEND=$(echo "$input" | jq -r '.rate_limits.spend_limit.used_percentage // empty')
USD=$(echo "$input" | jq -r '.rate_limits.spend_limit | select(.used_usd != null) | "$\(.used_usd) / $\(.limit_usd) \(.period)"')
LIMITS=""
[ -n "$FIVE_H" ] && LIMITS="5h: $(printf '%.0f' "$FIVE_H")%"
[ -n "$WEEK" ] && LIMITS="${LIMITS:+$LIMITS }7d: $(printf '%.0f' "$WEEK")%"
if [ -n "$SPEND" ]; then
SPEND_INT=$(printf '%.0f' "$SPEND")
RESET='\033[0m'
if [ "$SPEND_INT" -ge 95 ]; then COLOR='\033[31m'
elif [ "$SPEND_INT" -ge 75 ]; then COLOR='\033[33m'
else COLOR=''
fi
LIMITS="${LIMITS:+$LIMITS }${COLOR}spend: ${USD:-${SPEND_INT}%}${RESET}"
fi
[ -n "$LIMITS" ] && echo -e "[$MODEL] | $LIMITS" || echo "[$MODEL]"75%・95%というしきい値は、Claude Codeがgatewayの上限接近時に出す警告と同じ基準です。揃えておくと、statuslineの色とCLIの警告メッセージが同じタイミングで切り替わります。printf '%.0f'で整数化しているのは、小数のまま-geに渡すとbashが整数として扱えずエラーになるためです。used_percentageは62.8のような小数で届きます。
このスクリプトに擬似JSONを標準入力から流すと、入力ごとに次の表示になります(色はANSIエスケープで付きます)。
入力による表示の違い
ドル金額なし
入力にused_percentage: 62.8だけがあると、[Opus] | spend: 63%と出ます。used_percentage: 142.3ならspend: 142%が赤で出ます。
ドル金額あり
used_usd: 314.12・limit_usd: 500・period: "monthly"が揃うと、[Opus] | spend: $314.12 / $500 monthlyと出ます。パーセンテージは表示に使いません。
five_hour・seven_dayと混在させるときの注意
rate_limitsの3つのウィンドウ(five_hour・seven_day・spend_limit)は、それぞれ独立に不在になり得ます。公式ドキュメントも、各ウィンドウが個別に欠けうると明記しています。Pro/Maxで直接ログインしているセッションでは、gatewayを経由しない限りspend_limitは出ません。rate_limitsが存在するからといって、3つとも揃うとは限りません。
もうひとつ見落としやすい挙動があります。Claude Codeは各ウィンドウのresets_atが過ぎると、そのウィンドウを表示から落とします。しばらく前まで出ていたspendの数値が消えたときは、期間のリセット時刻を過ぎたことで落とされた可能性があります。スクリプト側は// emptyで不在を吸収する書き方を徹底し、特定のウィンドウが常に存在する前提でパースしないことが安定運用の分かれ目です。
resets_atを読める時刻に変換する
resets_atはUnixエポック秒のままでは読みにくいので、dateコマンドで人間が読める形式に変換します。Linuxのdate -dとmacOSのdate -rは書式が違います。両対応にするなら、片方が失敗したらもう片方を試す形にします。
resets_at=$(echo "$input" | jq -r '.rate_limits.spend_limit.resets_at // empty')
if [ -n "$resets_at" ]; then
reset_str=$(date -d "@$resets_at" '+%m/%d %H:%M' 2>/dev/null || date -r "$resets_at" '+%m/%d %H:%M' 2>/dev/null)
echo "spend resets: $reset_str"
figatewayのキャップはUTCの暦境界でリセットされます。日次は毎日00:00 UTC、週次は月曜、月次は1日です。v2.1.284以降ならperiodフィールドが期間を直接教えてくれるので、リセット時刻から周期を逆算する必要はありません。v2.1.251からv2.1.283の間、またはCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICを設定している環境ではperiodが届かないため、変換した時刻が翌日の00:00 UTCなら日次、次の月曜なら週次、翌月1日なら月次と読めます。
gatewayが拒否したときは、spend limit reached (daily; resets 2026-08-08 00:00 UTC)のように期間とリセット時刻を含むメッセージが429で返ります。このメッセージ形式はgatewayサーバーがv2.1.225以降の場合で、それ以前はspend limit reachedだけでした。
自動警告・/usage・statuslineの使い分け
gatewayの支出上限は、Claude Codeの中で3つの面に出ます。どれか1つだけを見ていると、気づくタイミングがずれます。
自動警告はしきい値を跨いだ瞬間にしか出ないため、普段の消化ペースをつかむ用途には向きません。/usageは、狙ったタイミングで開いて確かめる用途に向きます。見方はClaude Codeの/usageコマンドで見る使用量の内訳にあります。statuslineは常時表示できる代わりに、実装と保守の手間が読者側に残ります。
ペースをこまめに把握したい場合はstatusline、しきい値超過だけ知れれば十分な場合は自動警告、という住み分けになります。
spend_limitが出ないときの落とし穴
前提条件の3つを満たしていても、スクリプト側の書き方で空になることがあります。
もうひとつ、jqのクエリを.rate_limits.spend_limit.used_percentageではなく.rate_limits.used_percentageのように1階層省略すると、常にnullになり、スクリプトは空文字を返し続けます。rate_limitsは3つの子オブジェクトを持つ構造なので、階層を飛ばさずに指定します。
スクリプトではused_usdなどを必ず// emptyかselect(.used_usd != null)で受け、無いときはパーセンテージへ落とします。
spend_limitは条件が揃わないと出現しないため、gateway環境を持たない開発者はスクリプトを実機で確認できません。標準入力にJSONを直接流し込めば、gateway無しでも検証できます。
echo '{"model":{"display_name":"Opus"},"rate_limits":{"spend_limit":{"used_percentage":62.8,"resets_at":1740787200}}}' | ~/.claude/statusline.shrate_limitsを含まない入力({"model":{"display_name":"Opus"}})を流すと、[Opus]だけが出ます。起動直後や非gateway環境の表示がこの形になるので、先に試しておくと安心です。
まとめ
statuslineにspendが出ていれば、そのセッションはgatewayの支出上限の対象です。上限への距離を常に目に入れておきたいならstatusline、しきい値を跨いだ時点で気づければ足りるなら自動警告と/usageで済みます。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。