Claude Codeの使用量上限待ちをretry watchdogで打ち切る設定
CLAUDE_CODE_RETRY_WATCHDOG_MAX_USAGE_LIMIT_WAIT_MSは、無人セッションが使用量上限のリセットを待ち続けず、遠いリセットなら終わらせるための環境変数です。効く場面と値の決め方を書きます。
CLAUDE_CODE_RETRY_WATCHDOG_MAX_USAGE_LIMIT_WAIT_MSは、CLAUDE_CODE_RETRY_WATCHDOGを設定した無人セッションが、使用量上限のリセットがずっと先にあるときに待たず、そのリクエストを終わらせるための環境変数です。Claude Code v2.1.301で加わりました。
CIや定期ジョブで使うclaude -pが、週次上限に当たったまま何日も眠り続ける事態を避ける出口にあたります。
watchdogは使用量上限に当たるとどう動くのか
CLAUDE_CODE_RETRY_WATCHDOG=1は、評価ハーネスやCI、リモートワーカーのような無人セッション向けの設定です。429と529のキャパシティエラーを、CLAUDE_CODE_MAX_RETRIESの回数で諦めずに繰り返し再試行します。
使用量上限との関係で押さえる点は2つです。
- 支出上限や使用クレジット切れを報告する
429は、待たずにすぐ失敗する(標準速度のリクエストの場合。v2.1.239以降) - サブスクリプションの枠が尽きた場合は別で、バックオフは最大5分、レスポンスにレート制限のリセット時刻があればそこまで待つ。環境変数の説明には「使用量上限に当たったセッションは残りのウィンドウを待ち切る」とある
つまりwatchdogは、枠が尽きても「リセットまで眠って続きから進める」側に倒れています。リセットが数十分後なら都合のよい挙動です。リセットが数日先なら、ジョブは動かないまま実行時間だけが過ぎます。
エラー画面に出るリセット時刻の例を見ると、距離感がつかめます。
You've hit your session limit · resets 3:45pm
You've hit your weekly limit · resets Mon 12:00amセッション枠は同じ日のうちに戻りますが、週次枠は曜日をまたぎます。金曜の22時に週次上限へ当たった無人ジョブは、月曜0時まで50時間待つことになります。その間ランナーは占有され続け、時間課金の環境なら待つだけで費用がかかります。使用量はセッション枠と週次枠の両方に同時に数えられるため、大きな並列実行は、セッション枠が戻る前に週次枠を使い切ることがあります。この「待つには遠すぎる」ケースを切り落とすのが、今回の変数です。
v2.1.301で何が足されたか
変更履歴の記述は1行です。無人リトライモード(CLAUDE_CODE_RETRY_WATCHDOG)が、リセットが遠すぎる使用量上限に当たったとき、待たずにそのリクエストを終わらせる、という内容です。
仕様ページを見ると、いくつか書かれていない点があります。環境変数の一覧表にこの変数の行はなく、値の形式や「遠い」の判定条件は変更履歴の1行だけが根拠になります。
| 論点 | 状況 |
|---|---|
| 値の単位 | 状況名前の末尾が_MSで、隣のMAX_WAIT_MSがミリ秒の正の整数なので同じ読み方が自然。仕様ページには行がない |
| 判定の方法 | 状況「リセットが遠すぎる」としか書かれていない。リセットまでの残り時間と値を比べるのか、待った累計で数えるのかは記載がない |
| 打ち切り後の表示 | 状況エラー文言も終了コードも記載がない |
| 未設定のとき | 状況待機に上限を置かない従来の挙動のはず。変更履歴は追加としか書いていない |
判定の方法は設計を左右します。変更履歴の「リセットが遠すぎる使用量上限で、待たずに終わらせる」という書き方からは、残り時間が値を超えるなら待ち始めずに終わる読み方が自然です。ただし確定ではないため、運用に入れる前に、値を小さくして実際の挙動を確かめておくのが確実です。
429・529の上限とは別の変数
同じwatchdogには、v2.1.295で加わったCLAUDE_CODE_RETRY_WATCHDOG_MAX_WAIT_MSがあります。こちらは429と529を待ち続ける時間をリクエスト単位で区切る変数で、詳しくはMAX_WAIT_MSの決め方にまとめています。
名前の違いと対象を並べるとこうなります。
| 変数 | 狙い | 導入 |
|---|---|---|
CLAUDE_CODE_RETRY_WATCHDOG_MAX_WAIT_MS | 狙い429・529の待機時間に天井を置く | 導入v2.1.295 |
CLAUDE_CODE_RETRY_WATCHDOG_MAX_USAGE_LIMIT_WAIT_MS | 狙いリセットが遠い使用量上限で待たずに終える | 導入v2.1.301 |
後者が別の変数として用意された点が手がかりになります。使用量上限の待ちは、キャパシティエラーの待機とは時間の桁が違います。数分から数十分の混雑待ちと、数時間から数日のリセット待ちを1つの値で束ねると、片方に合わせた値がもう片方を壊します。MAX_WAIT_MSを30分にして混雑を切りたいジョブでも、使用量上限のリセットは2時間待ちたい、といった組み合わせが成り立ちます。
なお、MAX_WAIT_MSの説明は「429と529の待機」で、使用量上限の待ちがそこに含まれるかは仕様ページに書かれていません。使用量上限の天井を確実に置くなら、この変数を明示的に設定します。
値はどう決めるか
決め方の軸は、「待って再開した場合に、ジョブの成果が保たれるか」です。
- 次の実行で取り返せる定期ジョブ(夜間レビューなど): 短めの値にして、リセットが遠いときは早く失敗させる。翌日の実行に任せるほうが状況を追いやすい
- 一度始めたら続きが欲しい長い作業: セッション枠のリセットまでは待てる値にする。ただし週次上限まで待たせるかは、ジョブの期限とCIの課金時間で決める
- 実行時間に課金される環境(クラウドのランナーなど): 待機そのものがコストになるので、短い値に倒す
換算はMAX_WAIT_MSと同じ要領です。ミリ秒で書くので、桁を数えてください。
| 待機の上限 | 値 |
|---|---|
| 30分 | 値1800000 |
| 1時間 | 値3600000 |
| 3時間 | 値10800000 |
| 6時間 | 値21600000 |
ここで挙げた時間は換算の例であり、公式が推奨する値ではありません。
ジョブへの置き方
GitHub Actionsなら、ジョブのenvにwatchdogと2つの上限を並べます。ジョブ全体はtimeout-minutesでも守ります。
jobs:
nightly-review:
runs-on: ubuntu-latest
timeout-minutes: 120
env:
CLAUDE_CODE_RETRY_WATCHDOG: "1"
CLAUDE_CODE_RETRY_WATCHDOG_MAX_WAIT_MS: "1800000"
CLAUDE_CODE_RETRY_WATCHDOG_MAX_USAGE_LIMIT_WAIT_MS: "3600000"
steps:
- uses: actions/checkout@v4
- run: claude -p "直近のコミットをレビューして要点を書き出して"この例は、混雑の待機は1リクエスト30分、使用量上限の待機は1時間までという構成です。外側のジョブは2時間で止まります。連携の全体像はGitHub Actions連携の解説にあります。
シェルから起動するならexportで足ります。
export CLAUDE_CODE_RETRY_WATCHDOG=1
export CLAUDE_CODE_RETRY_WATCHDOG_MAX_USAGE_LIMIT_WAIT_MS=3600000
claude -p "テストを実行して失敗を直して"claude -pの使い方は非対話モードの解説で扱っています。
打ち切りの挙動を本番の前に確かめる
仕様に書かれていない部分が多いので、手元で小さく確かめる手順を決めておくと安全です。使用量上限に実際に当てるのは現実的ではないため、確認の主眼は次の2点に置きます。
- 環境変数が
claudeのプロセスまで届いているか: ジョブの先頭でenv | grep CLAUDE_CODE_RETRY_WATCHDOGを出し、3つの変数がログに残るようにする - 失敗したときの終了コード: 実際に上限へ当たったジョブのログと終了コードを一度控え、後続のステップがその値で分岐するようにする
env | grep CLAUDE_CODE_RETRY_WATCHDOG
claude -p "テストを実行して失敗を直して"
echo "exit=$?"終了コードの値は仕様に記載がないため、決め打ちで1と書かないでください。0以外で終わったかどうかだけを見る形が、仕様の変更にも強くなります。
打ち切ったあとの受け皿を用意する
待たずに終わる設計にした以上、終わったあとに何をするかを決めておく必要があります。選択肢は主に3つです。
| 受け皿 | 向くケース | 注意点 |
|---|---|---|
| 次回のスケジュール実行に任せる | 向くケース毎晩回るレビューや集計 | 注意点取りこぼしを次回が拾う設計にしておく |
| ジョブを失敗として通知する | 向くケース人が判断したい作業 | 注意点上限切れと他の失敗を、ログの内容で見分けられるようにする |
| 別のモデルで再実行する | 向くケース特定のモデル系統の上限だけ尽きた場合 | 注意点下記の条件を確認する |
モデル別の上限は、エラーメッセージの種類で見分けます。You've hit your Opus limitやYou've hit your Sonnet limitは、そのモデル系統にだけ効く上限で、対象外のモデルに/modelで切り替えれば作業を続けられると案内されています。一方、セッション上限と週次上限は全モデル共通で、モデルを替えても戻りません。
無人ジョブで別モデル再実行に頼るなら、打ち切られた理由がどの上限だったかを、ログから読み取れる必要があります。エラー文言の扱いは前述のとおり記載がないため、ここは実際のログを見て判定条件を決めてください。
対話セッションの自動再開とは別の仕組み
サブスクリプションで対話的に使っている場合、使用量上限に当たると、開いたセッションのままリセットを待って続きから再開する仕組みがあります(v2.1.234以降)。こちらは/configの設定や/rate-limit-optionsで操作するもので、watchdogの変数とは関係がありません。
| 仕組み | 想定する場面 | 操作 |
|---|---|---|
| 自動継続(Continue automatically at usage limit) | 想定する場面人が使うclaude.aiサブスクのセッション | 操作/config、/rate-limit-options |
RETRY_WATCHDOG系の変数 | 想定する場面人がいないCI・ワーカー | 操作環境変数 |
対話側の挙動と止め方は使用量上限リセット後の自動再開、/rate-limit-optionsの選択肢はコマンドの解説にあります。無人ジョブの出口を決めたいときは、この記事の変数を使います。
使用量上限まわりのwatchdogの変遷
watchdogが使用量上限をどう扱うかは、バージョンごとに変わってきました。固定バージョンのランナーでは、どのバージョンで何が変わったかが挙動の差になります。
| バージョン | 変更 |
|---|---|
| v2.1.186 | 変更無人セッションはCLAUDE_CODE_RETRY_WATCHDOGを使う形になった |
| v2.1.239 | 変更支出上限や使用クレジット切れの429は、待たずにすぐ失敗するようになった |
| v2.1.271 | 変更高速モードで使用クレジットの上限に当たると、ターンが失敗する不具合が直り、標準速度へ戻る形になった |
| v2.1.295 | 変更429・529の待機にリクエスト単位の上限を置くMAX_WAIT_MSが加わった |
| v2.1.301 | 変更リセットが遠い使用量上限で、待たずに終わらせる変数が加わった |
流れとしては、待たなくてよい失敗を早く切る方向から、待つべき失敗にも天井を置く方向へ進んでいます。v2.1.301では、使用量上限の待ちにだけ使う変数が別に用意されました。MAX_WAIT_MSが使用量上限の待ちにも効くかは書かれていないため、使用量上限の天井はこの変数で明示的に置く形になります。このバージョンの全体像はv2.1.301のリリースノートにあります。
この変数が止めないもの
効く対象は「リセットが遠い使用量上限」だけです。次のものは別の仕組みで動きます。
- 支出上限や使用クレジット切れの
429: そもそも待たず、すぐ失敗する 529の混雑待ち:MAX_WAIT_MSの担当- サーバーエラー・タイムアウト・接続断: watchdogの下では既定300回、バックオフにしておよそ3時間分まで再試行する
最後の項目は意外に見落とされます。使用量上限の待ちを切っても、別の原因で数時間粘るジョブは残ります。そのため、ジョブ全体の長さはtimeout-minutesの外枠で縛る前提で組むのが無難です。再試行の使い切りを検知する手順はretry exhaustionの検知にまとめています。
よくあるつまずき
- 秒で書いてしまう:
3600と書くと3.6秒相当の値になる。末尾の_MSを見て、桁を数える - watchdogを入れずにこの変数だけ置く: 変更履歴は「無人リトライモードが」と書いているので、
CLAUDE_CODE_RETRY_WATCHDOGと組で設定する。単独の動作は記載がない - v2.1.301より前のランナーに設定する: そのバージョンにはまだ変数がない。固定バージョンのランナーでは更新が先になる
- 打ち切り後の文字列で分岐する: エラー文言は記載がないので、ジョブの終了コードとログを実際に確かめてから判定条件を決める
- 週次上限を想定しない: 値をセッション枠の長さに合わせても、週次上限は曜日をまたぐので別の判断が要る
まとめ
watchdogの「リセットまで眠る」挙動に、使用量上限専用の出口が付きました。リセットが数日先の無人ジョブに効く変数で、混雑待ちを区切るMAX_WAIT_MSとは対象が違います。
値の単位と判定条件は変更履歴の1行にしか書かれていないので、本番のジョブに入れる前に、小さな値で実際の打ち切り方と終了コードを確かめておくと安心です。