CLAUDE_CODE_PLUGIN_PREFER_HTTPSでCIのプラグインclone失敗を直す
CIでプラグインのcloneが失敗したとき、SSHを外すPREFER_HTTPSと待ち時間を延ばすGIT_TIMEOUT_MSのどちらが効くかを、エラー文言から切り分けます。
CIでプラグインのcloneが落ちたら、まずエラー文言を見ます。SSHまわりの認証や接続の失敗ならCLAUDE_CODE_PLUGIN_PREFER_HTTPS=1、Git clone timed out after 120sならCLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MSが効く場所です。2つは別の失敗に効く別の変数で、片方を入れてももう片方の失敗は直りません。
この記事では、2つの変数が何を変えるか、GitHub Actionsのようなランナーにどう入れるか、入れても直らない失敗はどれかを順に説明します。症状別の一覧はmarketplace addが失敗する原因の記事にあります。ここではCIで設定を設計する側に絞ります。
2つの変数は、別々の失敗に効く
CLAUDE_CODE_PLUGIN_PREFER_HTTPSは、GitHubのowner/repo略記で書いたソースを、SSHではなくHTTPSでcloneさせる変数です。1を設定すると有効になります。対象はプラグインのインストールと更新、/plugin marketplace addとupdateです。SSH鍵を用意していないCIランナーやコンテナ向けの設定として、env-varsのページが用途として挙げています。
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MSは、プラグインのマーケットプレイスをcloneまたはrefreshするときの待ち時間です。単位はミリ秒で、既定は120000(120秒)です。
2つの変数が変えるもの
PREFER_HTTPS
SSHかHTTPSかの選び方を変えます。1で略記のcloneは常にHTTPSになります。
GIT_TIMEOUT_MS
cloneやrefreshを打ち切るまでの時間を変えます。既定の120秒を、大きなリポジトリや遅い回線向けに延ばします。
PREFER_HTTPSが外すのは「SSHを試す判定」
変数を入れない場合の動きが、CIで落ちる理由を決めます。GitHubのowner/repo略記では、Claude Codeはgithub.com向けのSSH鍵が設定されていそうかを確かめます。認証が通ればSSHで、通らなければHTTPSでcloneします。SSHのcloneが失敗したときは、HTTPSへ戻ります。
つまり、鍵の無いランナーでも最終的にHTTPSへ落ちる設計です。それでも変数を入れる意味は、この判定そのものを省くことにあります。PREFER_HTTPS=1は判定を飛ばして最初からHTTPSにします。
次の場面では、入れておくと経路が固定されます。
- SSH鍵を持たないCIランナーやコンテナ
known_hostsにgithub.comが無い使い捨て環境- 設定ファイルに略記で書いたマーケットプレイスを、ジョブごとに取り直す構成
SSH経由のcloneには、鍵がパスフレーズ付きだと進めない、known_hostsに無いホストへは接続しない、という条件があります。どちらもCIでは対話で解消できません。Claude Codeはgitを対話プロンプトなしで動かすためです。
略記以外のソースには効かない
この変数が対象にするのはGitHubのowner/repo略記です。git@host:path形式のSSH URLをソースに書いた場合の扱いは、env-varsの説明に載っていません。このURL形式自体は、マーケットプレイス追加の有効な指定です。ただしSSHで書くと、この変数の対象から外れて、鍵のパスフレーズやknown_hostsの条件がそのまま残ります。鍵を置けないCIでは、ホストがGitHub以外でも、フルのHTTPS URLで書くのが確実です。
/plugin marketplace add https://gitlab.example.com/your-group/your-marketplace.githttps://を付けずにホスト名から書くと、略記として読まれて拒否されます。URLには必ずスキームを付けます。
GIT_TIMEOUT_MSは「打ち切り」にだけ効く
Git clone timed out after 120sと出たら、待ち時間の問題です。メッセージの後ろには、この変数を設定する案内が付きます。マーケットプレイスのclone、およびupdateのための再cloneに、既定で120秒が与えられています。
CIでの延ばし方は、シェルならexportです。値はミリ秒なので、5分なら次のとおりです。
export CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS=300000
claude plugin marketplace add your-org/your-marketplace数字を大きくすれば何でも通る、とは限りません。待ち時間が足りないのではなく、接続そのものが張れていないときは、延ばしても失敗が遅れて出るだけです。次の2つを先に確かめると、無駄な待ちが減ります。
- ランナーからgitホストへ到達できるか。プロキシや許可リストの内側にいるときは、
git ls-remote <url>が通るかを先に見る(下の例) - リポジトリが大きすぎないか。モノレポなら
--sparse <paths>で、指定したディレクトリだけをチェックアウトできる
git ls-remote https://github.com/your-org/your-marketplace.git一覧が返れば到達できていて、認証も通っています。止まる、または認証エラーで終わるなら、待ち時間の問題ではありません。
--sparseの使い方はmarketplace addの3フラグ解説にまとめています。リポジトリを小さくできるなら、待ち時間を延ばすより先に試す価値があります。
GitHub Actionsに入れるときの設定例
2つの変数は、ジョブ全体のenvに置くと、そのジョブの各ステップに引き継がれます。次は、私設マーケットプレイスを使う場合の最小構成の一例です(公式のサンプルではなく、変数の置き場所を示すための形です)。
jobs:
claude:
runs-on: ubuntu-latest
env:
CLAUDE_CODE_PLUGIN_PREFER_HTTPS: "1"
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS: "300000"
CLAUDE_CODE_SYNC_PLUGIN_INSTALL: "1"
GH_TOKEN: ${{ secrets.MARKETPLACE_READ_TOKEN }}
steps:
- uses: actions/checkout@v4
- run: gh auth setup-git
- run: claude -p "変更をレビューして"各行の役割は次のとおりです。
| 変数・コマンド | 役割 |
|---|---|
CLAUDE_CODE_PLUGIN_PREFER_HTTPS | 役割略記のcloneをHTTPSに固定する |
CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS | 役割cloneとrefreshの待ち時間を延ばす |
CLAUDE_CODE_SYNC_PLUGIN_INSTALL | 役割-p実行で、最初の質問の前にプラグインのinstall完了を待つ |
GH_TOKEN + gh auth setup-git | 役割gitにHTTPSの資格情報を渡す |
最後の2行は、変数とは別の話です。HTTPSにしても、認証が自動で付くわけではありません。
HTTPSにしても認証は別に要る
公開リポジトリのマーケットプレイスなら、HTTPSで認証なしにcloneできます。プライベートの場合は、gitの資格情報ヘルパーに有効なトークンが入っている必要があります。Claude Codeは対話プロンプトを抑止してgitを動かすため、パスワードを聞かれる状況は失敗として終わります。
組織向けのページにはGitHub Actionsでの手順があります。読み取り権限のあるトークンをGH_TOKENとして渡し、gh auth setup-gitを実行します。既定のワークフロートークンが触れるのはそのワークフロー自身のリポジトリだけです。別リポジトリにあるプライベートのマーケットプレイスには、個人アクセストークンかアプリのトークンを使います。
-pではプラグインが最初のターンに間に合わない
claude -pのようなCI実行では、マーケットプレイスとプラグインのinstallがバックグラウンドで進みます。何も指定しないと、最初のターンにプラグインが揃っていないことがあります。CLAUDE_CODE_SYNC_PLUGIN_INSTALL=1を設定すると、最初の質問の前にinstallの完了を待ちます。
待ちの上限はCLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MSで決めます。この変数に既定値はなく、未設定だとinstallが終わるまで待ち続けます。上限を超えるとプラグインなしで進み、エラーが記録されます。gitの打ち切りとは別の仕組みなので、cloneの待ち時間を延ばしても、この待ちの上限は変わりません。
シェルのexportでなく、settings.jsonのenvに置く手もある
2つの変数は、settings.jsonのenvキーにも書けます。この場合はclaudeをどう起動したかに関係なく、ファイルから直接読まれます。
{
"env": {
"CLAUDE_CODE_PLUGIN_PREFER_HTTPS": "1",
"CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS": "300000"
}
}.claude/settings.jsonに書けば、リポジトリにチェックインされて、そのプロジェクトで作業する全員に適用されます。手元でも同じ略記cloneの経路になるので、CIだけ違う挙動になる食い違いを減らせます。個人の環境だけで試すなら、gitignore対象の.claude/settings.local.jsonが向きます。
値はそのまま環境にコピーされ、シェルは通りません。数値の300000も文字列で書きます。組織の管理設定に置くと、プロジェクト側の同名の指定より優先されます。
入れても直らない失敗の見分け方
エラー文言ごとの対処を表にします。
| エラー文言(一部) | 効く手 |
|---|---|
SSH authentication failed | 効く手PREFER_HTTPS=1でHTTPSに固定し、資格情報を用意する |
HTTPS authentication failed | 効く手GH_TOKENとgh auth setup-git。PREFER_HTTPSでは直らない |
SSH host key is not in your known_hosts file | 効く手HTTPS URLに切り替えるか、ssh -T git@github.comで鍵を登録する |
Git clone timed out after 120s | 効く手GIT_TIMEOUT_MSを延ばす。モノレポは--sparse |
terminal prompts disabled | 効く手資格情報が非対話で通る状態にする |
SSH host key is not in your known_hosts fileは、未接続のホストへSSHで繋いだときに出ます。Claude Codeはホスト鍵を自動では受け入れない設定でcloneするため、CIでは対話で承認できません。ジョブの先頭でssh -T git@github.comを一度通して鍵を登録するか、公開リポジトリならhttps://のURLで追加してSSHを避けます。ホスト鍵が変わったときはSSH host key has changedという別の文言になり、ssh-keygen -R <host>で古い鍵を消します。
terminal prompts disabled(Cannot prompt because user interactivity has been disabled)は、gitがパスワードや鍵のパスフレーズを聞こうとして止まった印です。CIにはそれに答える人がいないので、パスフレーズ無しの鍵か、資格情報ヘルパーに入れたトークンのように、聞かれずに通る認証を用意します。
HTTPS authentication failedの行が分かれ目です。すでにHTTPSで動いているので、PREFER_HTTPSを足しても何も変わりません。リポジトリ名の綴り、存在、アクセス権も同じ文言で終わるため、git ls-remote <url>を端末で通してから疑う先を決めます。
clone自体をやめる選択肢
ランナーが毎回cloneを繰り返す構成なら、cloneを省く手もあります。CLAUDE_CODE_PLUGIN_SEED_DIRにビルド時に作った読み取り専用のプラグインディレクトリを指すと、起動時にcloneせずにマーケットプレイスとキャッシュ済みプラグインを使えます。手順はコンテナへのプラグイン事前展開で扱っています。
オフライン環境で毎回の更新確認が失敗し続けるときは、CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1で再cloneを省き、既存のチェックアウトを使い続けられます。ただし対象は.claude-plugin/marketplace.jsonを含む既存のチェックアウトに限られます。一度もcloneできていないマーケットプレイスは、この設定でも取りに行きます。
ジョブごとに実行環境が使い捨てなら、シードが最も安定します。キャッシュのあるセルフホストランナーなら、2つの変数だけで足りる場合が多いです。claude-code-actionでのプラグイン指定も、使い捨てランナーでの組み方の参考になります。
まとめ
エラー文言の先頭を見て、SSH系ならPREFER_HTTPS=1、timed out after 120sならGIT_TIMEOUT_MSを足します。HTTPSにしたら、プライベートなマーケットプレイスにはGH_TOKENとgh auth setup-gitも要ります。それでも毎回落ちるなら、シードで事前展開に切り替える段階です。