Claude Codeセルフホストのgit fetchが巨大リポジトリで切れる原因と設定
巨大リポジトリでRunnerのgit fetchが途中で切れるときの調整先は、CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MSです。既定値・0とoffの意味・丸め範囲・切り分け手順をまとめます。
Claude Codeのセルフホスト環境で、巨大リポジトリのセッションだけが起動前に失敗するなら、疑う先はRunnerのgit fetchです。調整用の環境変数が CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MS です。既定は600000ミリ秒(10分)で、Claude Code v2.1.295以降で効きます。
CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MSは何を延ばす設定か
この変数は、Runnerがgit fetchを1回試みるあいだ、最初のデータが届くまで待てる時間の上限です。対象は限られています。gitサーバーが自分の進捗の数字を出し続けているのに、データはまだ1バイトも来ていない状態です。巨大なリポジトリでは、サーバーが転送するパックを組み立てるあいだ、この状態が長く続くことがあります。
つまり、ネットワークが細いときの転送時間を延ばす設定ではありません。効くのは「サーバーが準備中で、まだ送り始めていない」区間だけです。
CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MSの数字
既定値
600000
10分
丸めの下限
120000
2分
丸めの上限
1800000
30分
この変数に対応するCLIフラグはなく、Runnerの環境変数でだけ指定します。変数の説明には、Claude Code v2.1.295以降が必要とあります。
以前のRunnerで何が切れていたのか
v2.1.295の変更履歴には、サーバーがまだ進捗を報告している最中の巨大リポジトリで、git fetchが打ち切られていた不具合の修正が載っています。同じ項目に、待ち時間をこの変数で調整でき、無効にもできるとあります。
セルフホスト環境の運用ガイドは、Runnerのgit操作の制限をこう説明しています。1回の操作を、進捗が2分ないと止める見張りと、30分の上限で縛る方式です。固定の時間切れではないので、転送中に進捗を報告し続ける遅いクローンは最後まで完走します。
修正前に切れていたのは、サーバーが進捗を報告している最中の巨大リポジトリです。最初のデータ前のこの区間だけを別枠で待てるようにするのが、今回の変数です。
| 区間 | 打ち切りの条件 |
|---|---|
| パック作成中(最初のデータ前) | 打ち切りの条件変数の値まで待つ。既定は10分 |
| データ転送中 | 打ち切りの条件2分間進捗がないと止まる |
| 1回の操作の全体 | 打ち切りの条件30分が上限 |
表の1行目が今回の変数の領分で、2行目と3行目は運用ガイドの記述です。この変数の上限も30分です。
0とoffと範囲外の値はどう扱われるか
指定値の扱いは3通りです。
- 未設定: 600000ミリ秒が使われます
0またはoff: パック作成中の特別な待ちを無効にします。最初のデータまで待たず、データが来ない状態が2分続くと打ち切られます- それ以外の整数: 120000以上1800000以下に丸められます。たとえば60000を渡すと120000に、3600000を渡すと1800000になります
誤読しやすいのは 0 です。多くの設定では0が「無制限」を意味しますが、この変数の 0 は「待たない」で、短い方向に戻る指定です。たとえば 0 を入れて待ち時間が伸びたつもりになると、逆に挙動が厳しくなります。
また、短くする使い道は丸めの下限までです。2分より短い待ちは作れず、無効にした場合の2分が下限になります。
設定例
Runnerプロセスの環境に渡します。次はシェルで起動する例で、20分に伸ばしています。
CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MS=1200000 \
claude self-hosted-runnerKubernetesでは、Runnerコンテナの env に入れます。次の形が一例です。
containers:
- name: runner
env:
- name: CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MS
value: "1200000"value は文字列で渡す必要があるため、数字を引用符で囲みます。Docker Composeの environment でも同じ名前と値で指定できます。
値は分ではなくミリ秒で渡します。分から換算するときは、分数に60000を掛けます。15分なら900000、20分なら1200000、30分なら1800000です。桁を1つ間違えて120000のつもりで12000000と書くと、上限に丸められて30分になります。逆に桁が足りないと、下限の2分に丸められます。どちらも範囲内へ丸められる扱いなので、書いた値と効いている値がずれやすい点に注意が必要です。
この待ちは試行ごとに数えられます。fetchが失敗して再試行された場合、再試行の側でもあらためて最大の時間まで待てるため、セッションが起動するまでの総時間は設定値より長くなりえます。
待ち時間を延ばす前に確かめる3つのこと
延ばす前に、症状がこの変数の領分かを切り分けます。運用ガイドのトラブルシューティングには「セッションの起動や再開に数分かかる」という項目があり、原因の筆頭が新規クローンです。空のディスクで起動するRunnerは、Claude Codeを起動する前にセッションのリポジトリをクローンし、空のディスクで再開したセッションも同じクローンをもう一度待ちます。
1. 切れるのはクローンか、起動後か
--startup-timeout-min は別の時計です。こちらは、クローンが終わったあとで子プロセスが初期化されないとき、セッションの枠を解放するまでの待ちで、既定は15分です。git fetchの打ち切りとは、数える開始点が違います。
2. 事前クローンを使えているか
巨大リポジトリで最も効くのは、待ちを延ばすことより、待たなくて済む構成です。ランナーがキープする標準の置き場所に、あらかじめクローンを置いておけます。--capacity 1 では、Runnerは要求されたrefをfetchして、HEADを切り離し、ハードリセットします。変更が少なければほぼ一瞬です。
置き場所は <base-dir>/<repo-owner>/<repo> です。事前クローンを使うなら、--depth を付けずに作ります。浅いクローンだと、その位置より前に分岐したブランチのセッションで、足りない履歴を毎回ダウンロードします。
3. 浅いクローンで済む用途か
CLAUDE_RUNNER_FETCH_DEPTH は新規クローンの深さで、既定は50コミットです。full または 0 なら完全取得になります。浅くするほどサーバーが組み立てるパックは小さくなります。なお、origin を持つ既存クローンへfetchするときは、この変数を設定しても --depth は渡されません。
症状から対処を選ぶ
| 症状 | 見る場所 | 動かす設定 |
|---|---|---|
| パック作成中に2分ほどで切れる | 見る場所v2.1.295以降か | 動かす設定CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MS を延ばす |
| 待っても30分で終わらない | 見る場所事前クローンの有無 | 動かす設定事前クローンを置く |
| 毎回のセッション起動が遅い | 見る場所claude_code_self_hosted_runner_session_init_duration_seconds | 動かす設定事前クローン、または CLAUDE_RUNNER_FETCH_DEPTH を下げる |
| クローン後に枠が解放される | 見る場所--startup-timeout-min | 動かす設定15分の既定を見直す |
| 以前の切れ方に戻したい | 見る場所この変数 | 動かす設定0 または off |
起動時間の長さは、claude_code_self_hosted_runner_session_init_duration_seconds の値でも追えます。クローンが支配的かどうかは、この数字で見分けます。メトリクスの一覧はCLIフラグ・メトリクスリファレンスにあり、本番運用の全体像はセルフホスト環境の本番運用にまとめています。
事前クローンが使われているかをログで確かめる
事前クローンを置いたのに起動が遅いままなら、Runnerがそのクローンを見つけていない可能性があります。Runnerを --log-level debug で起動し、対象のリポジトリでセッションを始めます。
claude self-hosted-runner --log-level debug見つけたときは Prefetched repo found at とクローンのパスがログに出ます。見つからないと、代わりに No prefetched repo, fresh init at が出ます。この場合は、その行のパスにクローンがあるか、Runnerのユーザーが所有しているか、リモート名が origin かを順に見ます。
クローンが見つかっているのに遅いなら、次に疑うのは浅いクローンです。前述のとおり、浅いクローンは分岐位置によって履歴を毎回取りにいきます。
もうひとつ見落としやすいのが、--capacity を2以上にした構成です。このときRunnerはクローンへfetchしたうえで、セッションごとに別のワークツリーをチェックアウトします。事前クローンで省けるのはダウンロードだけで、チェックアウトの時間は残ります。巨大リポジトリで --capacity を上げると、起動の体感がクローンの有無ほど変わらない理由はここにあります。
--use-anthropic-git-proxy を使うRunnerでは事情が変わります。セッションごとに .git/ が整えられ、インデックスが消されるため、毎回ワーキングツリー全体のチェックアウトが走ります。fetch自体は既存クローンへ行われ、クローンし直すことはありません。
延ばすか、事前クローンに寄せるか
この変数は、巨大リポジトリで待ちが10分を超えたときの保険です。待ち時間は最大でも30分までで、それ以上は伸ばせません。常に待たされるリポジトリなら、事前クローンで毎回のコストを消すほうが安定します。
一方で、事前クローンを置けない構成があります。使い捨てコンテナで毎回空のディスクから始める環境や、フリートに載るリポジトリが多すぎる環境です。そこでは、この変数で10分から20分程度に伸ばし、CLAUDE_RUNNER_FETCH_DEPTH を下げる組み合わせが現実的な落としどころになります。
オンデマンドRunner構成でRunnerを都度起動している場合の組み方は、オンデマンドRunnerの起動にあります。
まとめ
切れていたのは、サーバーがパックを組み立てている最初のデータ前の区間です。v2.1.295以降は CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MS で待ちを10分から30分まで調整でき、0 や off で2分の打ち切りに戻せます。
変数で救えるのは準備待ちだけです。転送が止まる場合や、毎回のクローンが重い場合は、事前クローンと浅い深さで待ちそのものを減らす構成が先になります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。