Claude Code を CI / 自動化で回し始めて「夜間バッチで止め忘れて課金が膨らんだ」を一度でも経験した人向け
CI / cron / GitHub Actions などで Claude Code を無人で回すとき、暴走や止め忘れで課金が膨らむ事故を防ぎたい場面で使う。たとえば夜間バッチで記事下書きを量産する自動実行スクリプトに `--max-budget-usd 3.00` を足しておけば、1ジョブが $3 を超えた瞬間に Claude Code 側が勝手にジョブを終わらせるので、翌朝の請求が読めるようになる
Claude Code を CI に組み込んで夜間バッチを回し始めると、いつかは「止め忘れて朝起きたら請求額が跳ねていた」が来ます。--max-budget-usd は、その手の事故を起こさないための安全装置です。コマンドの後ろにドル単位の上限額を書き足しておくと、API 利用料がそこに達した時点で Claude Code 側が自分でジョブを終わらせます。
私の使い方で言うと、夜間に記事の下書きを5本生成させるバッチに --max-budget-usd 3.00 を付けています。1本あたり数十セントの想定なので、$3 を超えるのは「Claude が何かを延々と書き直している」異常時だけ。そこに達したらジョブが止まるので、翌朝のログを見れば事故か正常かが一目で分かります。
噛み砕くと
家のブレーカーをイメージすると分かりやすい。電気を使いすぎたらブレーカーが落ちて家電が止まる、あれの「ドル建て版」を Claude Code 自身が内蔵していると思えばいい。
違いは1つだけ。ブレーカーは電流に反応しますが、こちらが反応するのは API 呼び出しのコストです。Claude Code は内部で「今この呼び出しでいくら使ったか」を積み上げていて、その合計が指定額に達した瞬間にジョブを終わらせます。CI のジョブが勝手に止まるので、cron で回している間に「気付いたら破産」みたいなことが起きにくい。
これ正直、CI 派には必須の安全装置です。
大事な前提:このコマンドは print mode の時にだけ効く
公式ドキュメントには「(print mode only)」と明記されています。素の claude(対話セッション)で打っても効きません。claude -p か claude --print の系統、つまり「一発打ち切りモード」専用の安全装置です。
これは --max-turns(ターン数で止める指定)と同じ family の制限で、人間が画面の前にいないバッチ用途を前提に設計されています。インタラクティブで使うときは、人間が見ているのでブレーカーは要らないだろう、という公式の判断だと読めます。
「CIで記事下書きを夜間バッチ生成」を例に、実際の手順を見る
毎晩2時に、過去の記事から下書き候補を5本生成させる cron を組む想定でやってみます。題材は適当な料理ブログのバックログ消化スクリプト、くらいの規模感です。
ステップ1: まずは上限なしでコストを測る
いきなり上限を決めても根拠がないので、最初の1〜2回は手動で叩いて「1本あたりだいたい何ドル使うのか」を計測します。
$ claude -p "下書きを1本生成して draft-01.md に保存して" --output-format json
JSON 出力には実行時のコスト情報が含まれるので、それを見て「1本おおむね $0.4 前後」と当たりをつけます。5本回すなら $2.0、Claude が暴走した時のバッファを足して $3.0 が上限の目安、と決めます。
ステップ2: 安全装置を付けてバッチを書く
cron から叩く .sh スクリプトに --max-budget-usd 3.00 を足します。
#!/bin/bash
claude -p \
--max-budget-usd 3.00 \
--max-turns 30 \
"バックログから5本選んで下書きを生成、それぞれ drafts/ に保存"
ここで --max-turns も併用しているのがポイント。コスト側とターン数側、両方の安全装置を二重にかけておきます。片方だけだと、すり抜けるパターンがあるからです(後述の落とし穴で扱います)。
ステップ3: cron に登録する
crontab に毎晩2時起動を書きます。
0 2 * * * /home/myname/bin/nightly-drafts.sh >> ~/claude-logs/nightly.log 2>&1
ログを ~/claude-logs/nightly.log に追記モードで残しておけば、翌朝「いくら使ったか」「上限に達して止まったか」がそのまま見えます。
ステップ4: 翌朝、ログを見る
朝起きてログを開きます。3パターンに分かれます。
- 正常終了: 5本生成されてジョブが完了。コストは $2 前後。これが理想形
- 上限到達で停止: コスト合計が $3 に達してジョブが終了。何かおかしいので調査する。公式 docs には "before stopping"(停止前)としか書かれておらず、停止の瞬間までに書き出されたファイルが残るかどうかは明文化されていないので、ログとファイル両方を見て実際にどこまで進んだかを確認するのが安全
- ターン数オーバー: コストは余裕だったが
--max-turns 30側で止まった。「Claude が同じファイルを編集し直し続けている」みたいな迷走を疑う
ここで初心者がやりがちな勘違いを1つ。「上限到達で停止」を「失敗」と即断しがちですが、これは本来の役割を果たしている状態です。むしろ、上限がなかったら $10 や $20 まで走った可能性のあるジョブを、$3 で打ち切ってくれたわけで、ブレーカーが正しく落ちただけ。
ステップ5: 異常時の調査
上限到達が続くようなら、生成プロンプト側を見直します。指示が曖昧で Claude が何度も「これでいいですか?」と書き直しているのか、参照しているファイルが大きすぎてトークンを食い潰しているのか、原因を切り分けます。
調査が済んだら、上限を $3 → $4 に上げる前に、まずプロンプトと参照ファイルのスリム化を優先します。上限を上げるのは最後の手段、というのが私の運用ルール。
ステップ6: ログ目視ではなく grep で異常検知する
毎朝ログを目で見るのは続かないので、ログから「上限到達で止まったかどうか」を自動的に拾う仕組みを足します。Claude Code の出力には、コストや停止理由を示す文字列が含まれるので、cron の終わり際に grep で拾うのが手堅い方法です。
# nightly-drafts.sh の末尾に追記
LOG=~/claude-logs/nightly.log
if grep -qi "budget" "$LOG"; then
curl -X POST -d "nightly drafts: 予算上限に到達した可能性あり、$LOG を確認" $SLACK_WEBHOOK
fi
ポイントは exit code(コマンドの結果コード)に頼らないこと。--max-turns は公式 docs に「Exits with an error when the limit is reached」と明記されていますが、--max-budget-usd 側に同じ記述はありません。予算超過時の exit code がどうなるかは公式に書かれていないので、もし $? 分岐で組みたい場合は、自分の環境で --max-budget-usd 0.01 程度の極小値を渡して、実際にどんな code が返るかを事前に確認してから組むのが安全。私は確認の手間を省くためにログ grep に倒しています。
つまり --max-budget-usd は何をしてくれるのか
- やってくれる: 指定したドル額に API コスト合計が達したら、その時点でジョブを終了させる(公式 verbatim "before stopping")
- やってくれない: インタラクティブな対話セッションでのコスト制御。print mode 以外では効かない
- やってくれない: 為替換算。単位は USD なので、円ベースで管理したい場合は外側のスクリプトで吸収する
- 意味が薄い場面: 人間が画面を見ながら叩く対話セッション。そこは自分の目がブレーカー代わりになるので、わざわざ
-pに切り替えてまで付ける必要はない
使いどころ3シナリオ
シナリオ1: 夜間バッチで記事下書きを量産するとき
今回の例そのものです。cron で毎晩 claude -p を回して、過去ネタから下書きを5本生成。1本 $0.4 想定なら --max-budget-usd 3.00。Claude が暴走して同じファイルを何十回も書き直しても、$3 で必ず止まるので翌朝の請求がブレません。私の運用ではここが本命の使い方。
シナリオ2: GitHub Actions で PR の説明文を自動生成するとき
PR が立つたびに走るジョブで、Claude にコード差分を読ませて「この PR は何をしているか」を Markdown で書かせる用途。PR の数は読めないので、1 PR あたり --max-budget-usd 0.50 くらいに絞ります。月末に「先月の Actions だけで $200 使ってた」を防ぐ意味で、1ジョブ単位の上限と合わせて GitHub 側の利用量アラートも併用するのが安心です。
シナリオ3: 検証用のサンドボックスで挙動を試すとき
新しいプロンプトや MCP サーバーを試すとき、暴走して大量のトークンを食う可能性があります。claude -p --max-budget-usd 0.20 "..." のように上限を意図的に小さく設定して、「壊れても 20 セントで済む」状態で実験すると気が楽。検証フェーズでは、わざと安全側に振った値を入れておくのが私のやり方です。
初心者が踏みやすい落とし穴
- 対話セッションで叩いても効かない。素の
claudeで--max-budget-usd 3.00を書き足しても、公式 docs に「(print mode only)」と書かれている通り、print mode 系統以外では機能しません。CI 用の安全装置として割り切る - 単位は USD で、円換算は自分でやる。
3.00はドル建ての 3 ドルです。円で予算管理したい場合、cron 側で為替レートを掛けてからドルに変換した値を渡す形になります --max-turnsと二重がけが安全。コスト側だけだと、超低コストで延々と無意味なターンを刻むパターンを止めにくいことがあります。ターン数上限とコスト上限、両方の安全装置を併用するのが CI 運用の定石です- 「上限到達」を「失敗」と即断しない。ジョブが
--max-budget-usdで止まること自体は、設計通りの動作です。むしろ止まったおかげで暴走を捕まえられたわけで、ログを見て原因を切り分ければいい - 小数点は2桁に揃えるのが無難。公式の例は
5.00のみです。3.555のように小数3桁以上を渡したときの扱いは公式 docs に書かれていないので、素直に3.003.503.55の形に揃えておくのが安全です - 1ジョブ単位の上限と、月次の課金上限は別物。これは Claude Code が日次累計を見ているわけではなく、あくまで「この1回のジョブで使うコストの上限」です。月で締めたコスト管理は Anthropic 側の Console(請求ページ)や、組織側の利用量アラートと組み合わせる必要があります
- ログ保存先に書く時はホーム配下を使う。CI ジョブのログは
~/claude-logs/のようにユーザーのホーム配下に置くのが扱いやすい。システム直下に書こうとして権限で詰まる、というのが cron 初心者の典型的なつまずき
私はこれを入れてから、夜間バッチに対する心理的負担がかなり減りました。寝てる間に走るスクリプトに、ブレーカー1つ仕込めるかどうかは、CI に Claude を組み込む時の入口だと思っています。
書き方
claude -p --max-budget-usd <ドル額> "<質問文>"
やってみるとこうなる
入力
claude -p --max-budget-usd 5.00 "query"
出力例
API 呼び出しコストの合計が $5.00 に達した時点で、Claude Code がそのジョブを自動的に終了させる
このページに出てきた言葉
- print mode
- <code>claude -p</code> や <code>claude --print</code> で起動するモード。会話画面を開かず、質問を1回投げて答えを受け取ったら終わり、というワンショット動作。CI / cron / 自動実行スクリプトから呼び出すときに使う
- CI
- Continuous Integration の略。GitHub Actions や Jenkins のように、コードを更新したら自動でテストやビルドが走る仕組みのこと。広い意味では「人間が見ていない時に裏で走る自動処理」
- cron
- Mac / Linux で「毎晩2時に動かす」みたいな時刻指定で自動実行するための仕組み
- API 呼び出し
- Claude Code が裏で Anthropic のサーバーに問い合わせる通信1回ぶん。使ったトークン量に応じた料金がかかる
- USD
- アメリカドル。<code>--max-budget-usd 3.00</code> は「3 米ドル」の意味。日本円で予算管理したい場合は外側のスクリプトで換算する
- ターン
- Claude とのやり取り1往復ぶん。<code>--max-turns</code> はこの回数で上限を切る別の指定で、<code>--max-budget-usd</code> とは別の物差し
- Webhook
- Slack などに「何かが起きたら教えてくれ」と通知を投げ込むための、URL 形式の受け口