--max-budget-usd 0.01 を渡した実行が、total_cost_usd: 0.0390724 で終わりました。指定額の3.9倍。エラー自体は正しく出ていて、止まるべきところで止まっています。
このフラグは「使いすぎたら止める」ためのもので、「指定額を超えない」ことは保証しません。どこで超過が生まれるのかを、Claude Code v2.1.224 で実測して分解しました。
--max-budget-usd はprintモード専用の停止装置
公式ドキュメントの定義
CLI reference の --max-budget-usd の項には、こう書かれています。
Maximum dollar amount to spend on API calls before stopping (print mode only). Spend from subagents counts toward the cap. Once spend reaches the cap, spawning another subagent fails with Budget limit reached, and Claude Code stops background subagents that are still running; the cap-enforcement behaviors require Claude Code v2.1.217 or later
print モード(-p)でしか効かないこと。サブエージェントの消費も合算されること。cap 到達時の停止挙動には v2.1.217 以降が要ること。
手元のバージョンで確認する
claude --version
claude --help | grep -A1 "max-budget-usd"
実行結果:
2.1.224 (Claude Code)
--max-budget-usd <amount> Maximum dollar amount to spend on API
calls (only works with --print)
ヘルプの文言は「only works with --print」とだけ。対話セッションで渡しても無視されます。無人実行やCIジョブ専用のフラグです。
0.01ドル指定で0.039ドル使った
実行したコマンド
ツールを使わない純粋な文章生成タスクに、上限 $0.01 をかけました。モデルは単価の低い Haiku 4.5 です。
claude -p "Write a 1500 word essay explaining the history of the Go programming language. Output plain prose only, do not use any tools." \
--max-budget-usd 0.01 \
--output-format json \
--model claude-haiku-4-5-20251001
返ってきた result イベント
--output-format json の出力は複数イベントの配列で、最後の type: "result" が集計です。関係する部分を抜き出します。
{
"type": "result",
"subtype": "error_max_budget_usd",
"is_error": true,
"terminal_reason": "budget_exhausted",
"errors": ["Reached maximum budget ($0.01)"],
"num_turns": 1,
"total_cost_usd": 0.0390724,
"duration_ms": 29302
}
終了コードは 1。エラーメッセージは指定額を正しく反映しています。
num_turns が 1 であること
num_turns は 1。ターンを重ねて少しずつ超過したのではなく、最初の1ターンで既に上限の3.9倍に達していました。
予算チェックは各APIコールが完了した後に走ります。実行前に見積もって止めるのではなく、支払いが確定してから判定する仕組み。だから「1コール分」は必ず超過しうる、というのが公式の説明です。ただ今回はその1コールが上限の4倍近い。理由は内訳にあります。
コストの79%はキャッシュ書き込みだった
modelUsage を開く
同じ result イベントの modelUsage に、トークンの内訳が入っています。
{
"claude-haiku-4-5-20251001": {
"inputTokens": 539,
"outputTokens": 2666,
"cacheReadInputTokens": 17734,
"cacheCreationInputTokens": 11715,
"costUSD": 0.0390724
}
}
プロンプトは英文1行、つまり inputTokens は539。それに対してキャッシュ書き込みが11,715トークン、キャッシュ読み込みが17,734トークン。合計29,449トークンのコンテキストが、こちらの1行の裏側に載っています。
単価をかけて突き合わせる
Haiku 4.5 の単価は入力 $1.00 / 出力 $5.00 per MTok。キャッシュ読み込みは入力の0.1倍、書き込みはTTLで変わり、5分なら1.25倍、1時間なら2倍です。今回の cache_creation は ephemeral_1h_input_tokens: 11715 だったので、2倍単価が当たります。
| 項目 | トークン数 | 単価 (per MTok) | 金額 |
|---|---|---|---|
| 入力 | 539 | $1.00 | $0.000539 |
| 出力 | 2,666 | $5.00 | $0.013330 |
| キャッシュ読み込み | 17,734 | $0.10 | $0.001773 |
| キャッシュ書き込み(1時間TTL) | 11,715 | $2.00 | $0.023430 |
| 合計 | $0.039072 |
報告された total_cost_usd: 0.0390724 と小数第6位まで一致します。最大の費目は出力でもプロンプトでもなく、キャッシュ書き込みの $0.02343。全体の60%です。
セッション起動時、Claude Code はシステムプロンプト、CLAUDE.md、スキル定義、MCPサーバーのツール定義をまとめてコンテキストに積みます。これが初回リクエストでキャッシュに書き込まれる。公式ドキュメント「Manage costs effectively」の “Why usage climbs in a long session” セクションが挙げる “Long context” と “Cache misses” が、そのまま初回コストに現れた形です。
--max-budget-usd に渡す額は、タスクの重さではなく環境の初期コンテキスト量と比較すべき数字になります。
1語だけ返す実行の下限
どこまで安くできるのか。「OK」とだけ返すタスクに、余裕のある上限 $1.00 をかけて最小コストを測りました。MCPサーバーも切っています。
echo '{"mcpServers":{}}' > /tmp/nomcp.json
claude -p "Reply with exactly: OK" \
--max-budget-usd 1.00 \
--output-format json \
--model claude-haiku-4-5-20251001 \
--strict-mcp-config --mcp-config /tmp/nomcp.json
実行結果:
{
"subtype": "success",
"is_error": false,
"terminal_reason": "completed",
"num_turns": 1,
"total_cost_usd": 0.014333,
"result": "OK"
}
出力トークンは51、金額にして $0.00026。にもかかわらず総額は $0.014333。うちキャッシュ書き込みが $0.01137 で、総額の79%を占めます。
この環境の --max-budget-usd 0.01 は、1文字も出力しない実行ですら達成できない上限でした。指定額が下限を割っているので、何を投げても超過して終わります。上限を決める前に、空回しのコストを一度測る。
MCPサーバーを切ると書き込みが半減する
同じエッセイ生成タスクを、MCPサーバーを無効化して再実行しました。--strict-mcp-config と空の設定ファイルの組み合わせで、既存のMCP設定をすべて無視させます。
claude -p "Write a 1500 word essay explaining the history of the Go programming language. Output plain prose only, do not use any tools." \
--max-budget-usd 0.01 \
--output-format json \
--model claude-haiku-4-5-20251001 \
--strict-mcp-config --mcp-config /tmp/nomcp.json
| MCP有効 | --strict-mcp-config で無効 | |
|---|---|---|
| キャッシュ書き込み | 11,715 | 5,712 |
| キャッシュ読み込み | 17,734 | 21,920 |
| 出力 | 2,666 | 3,147 |
| total_cost_usd | $0.0390724 | $0.02989 |
キャッシュ書き込みが11,715から5,712トークンへ、51%減。総額は23%下がりました。出力トークンはむしろ増えているので、差分はまるごと初期コンテキストの分です。
公式ドキュメントの “Reduce MCP server overhead” は、MCPツール定義が既定で遅延読み込みになる点を挙げています。それでもサーバー名とツール名の一覧はコンテキストに入る。接続数が増えるほど初回の書き込みは膨らみます。無人実行のジョブでMCPを使わないなら、切っておくとそのまま単価に効く。トークン単位の削減幅はClaude Code MCP tool search—実測7万トークン削減の設定判断にまとめました。
サブエージェントの消費も同じ財布から出る
cap はメインのセッションだけを見ているわけではありません。公式の記述どおり、サブエージェントの支出が合算されます。上限に達した状態で新しいサブエージェントを起動しようとすると Budget limit reached で失敗し、実行中のバックグラウンドサブエージェントも停止されます。
この停止まで含めた挙動が入ったのが v2.1.217。それ以前のバージョンでは、走り続けるサブエージェントが cap を無視して消費を続けます。ネスト構成の上限設定はClaude Codeサブエージェントのネスト—3階層の設定と累計200の上限にまとめてあります。
CIでは終了コードだけで判定しない
終了コード1は予算超過を意味しない
予算超過は終了コード 1 を返します。ただし権限拒否も、APIエラーも、プロンプト不正も同じ 1。この書き方では区別がつきません。
# 何で落ちたのか分からない
claude -p "$PROMPT" --max-budget-usd 5.00 --output-format json > out.json
if [ $? -ne 0 ]; then
echo "失敗"
exit 1
fi
subtype で分岐する
result イベントの subtype が error_max_budget_usd のときだけ予算超過です。あわせて terminal_reason: "budget_exhausted" と errors 配列が付きます。実支出は total_cost_usd で取れるので、超過幅もそのままログに残せます。
claude -p "$PROMPT" --max-budget-usd 5.00 --output-format json > out.json
python3 - <<'PY'
import json, sys
events = json.load(open("out.json"))
r = next(e for e in events if e["type"] == "result")
if r["subtype"] == "error_max_budget_usd":
print(f"予算超過: {r['errors'][0]} / 実支出 ${r['total_cost_usd']:.4f}")
sys.exit(2) # 予算超過だけ別コードに逃がす
if r["is_error"]:
print(f"その他の失敗: {r.get('terminal_reason')}")
sys.exit(1)
print(f"完了 ${r['total_cost_usd']:.4f} / {r['num_turns']} turns")
PY
上限 $0.01 の実行に当てた結果:
予算超過: Reached maximum budget ($0.01) / 実支出 $0.0391
終了コード2で抜けるので、ワークフロー側で「予算を上げて再実行」と「プロンプトを直して再実行」を出し分けられます。成功時は subtype: "success" と terminal_reason: "completed"。errors キー自体が存在しないため、r["errors"] を無条件に読むと KeyError になります。.get() で受けるか、上の順序どおり subtype を先に見てください。
--max-turns との使い分け
止める軸が違います。CLI reference の --max-turns の説明は「Limit the number of agentic turns (print mode only). Exits with an error when the limit is reached. No limit by default」。
| --max-budget-usd | --max-turns | |
|---|---|---|
| 止める単位 | ドル | エージェントのターン数 |
| 判定タイミング | APIコール完了後 | ターン終了時 |
| サブエージェント | 消費が合算される | 合算されない |
| 既定値 | なし | なし(無制限) |
| 効く場面 | モデル混在・サブエージェント並列 | ツール呼び出しの空回り |
ターン数が少なくても長文コンテキストなら金額は膨らみ、逆に短い応答を何十回繰り返しても金額は伸びません。無人実行では両方かけるのが安全側です。定期実行の構成はClaude Code Routinesでcronを置き換える—クラウド無人実行の設定を参照。
まとめ
--max-budget-usdは-pのprintモード専用。対話セッションでは効かない- 予算チェックはAPIコールの完了後。最低1コール分は必ず超過しうる
- 実測では $0.01 指定で $0.0390724(3.9倍)。
num_turnsは1 - 超過の主因はタスクの重さではなく初期コンテキスト。キャッシュ書き込みが総額の60〜79%
- 「OK」1語を返すだけでも $0.014333。上限はこの下限より上に置く
--strict-mcp-configでMCPを切ると書き込みが11,715→5,712トークン、総額23%減- サブエージェントの支出も合算され、cap到達で
Budget limit reached。停止挙動は v2.1.217 以降 - CIでは終了コードでなく
subtype: "error_max_budget_usd"で判定する
セッション単位の消費内訳は /usage で確認できます。スキルやMCPサーバーごとの割合まで出るので、上限額を決める前の実測に使えます。詳しくはClaude Code /usage—使用量と制限の内訳をスキル単位で確認するで扱いました。

