Claude Codeプラグインをコンテナへ事前展開する手順
CI・コンテナ環境でマーケットプレイスやプラグインをランタイムでクローンせず起動する、CLAUDE_CODE_PLUGIN_SEED_DIRの設定手順とふるまいをまとめます。
コンテナ起動のたびにクローンしたくない理由
CI環境やコンテナイメージでClaude Codeを動かすとき、起動のたびにマーケットプレイスをgit cloneし、プラグインをインストールするのは無駄が多い作業です。同じリポジトリをジョブごとに毎回取得し直すことになり、ビルド時間が伸びます。ネットワークが制限された環境やエアギャップ環境なら、話はさらに悪くなります。ランタイム側でのクローンが、そもそも失敗の原因になるからです。
そこでClaude Codeは、この初期化をビルド時に済ませる仕組みを用意しています。ランタイムでは何もクローンせずに起動できる仕組みです。環境変数 CLAUDE_CODE_PLUGIN_SEED_DIR に、あらかじめ用意したディレクトリを指定するだけで済みます。
前提として必要なのは2つだけです。Dockerなどでイメージをビルドできる環境と、ビルド時に一度Claude Codeを実行できることです。特別なプランや追加インストールは不要です。
手順1: シードディレクトリの構造を理解する
シードディレクトリは ~/.claude/plugins の構造をそのまま再現したものです。
$CLAUDE_CODE_PLUGIN_SEED_DIR/
known_marketplaces.json
marketplaces/<name>/...
cache/<marketplace>/<plugin>/<version>/...known_marketplaces.json に登録済みマーケットプレイスの情報が入り、marketplaces/ に各マーケットプレイスの実体、cache/ にインストール済みプラグインのバージョン別コピーが入ります。cache/ の下は、マーケットプレイス名・プラグイン名・バージョンの3階層です。これは通常運用の ~/.claude/plugins/cache と同じ構造で、同じプラグインの複数バージョンを衝突なく共存させる狙いがあります。
複数のシードディレクトリを重ねることもできます。Unixなら :、Windowsなら ; でパスを区切って並べるだけです。Claude Codeは指定順にディレクトリを探索し、該当するマーケットプレイスやプラグインキャッシュを最初に見つけたシードを使います。共通のベースイメージにチーム共通のシードを焼き込み、その上のレイヤーでチーム固有のシードを重ねる、という2段構成にも応用できるでしょう。
手順2: ビルド時にシードを作る
シードディレクトリを作る方法は2通りあります。
1つ目は、一度Claude Codeを起動して必要なプラグインをインストールし、できあがった ~/.claude/plugins をそのままイメージにコピーする方法です。素直な流れですが、コピー元とコピー先の2箇所が発生します。Dockerfileで書くなら、RUN claude plugin marketplace add ... && claude plugin install ... のあとに RUN cp -r ~/.claude/plugins /opt/claude-seed のような1行を足す形です。既存のインストール手順に手を加えず、最後にコピーを足すだけで済むのが利点でしょう。
2つ目は、CLAUDE_CODE_PLUGIN_CACHE_DIR をビルド時の目的地に直接向け、コピーの手間そのものを省く方法です。インストール先を最初から /opt/claude-seed に向けるため、ビルドの中間生成物としての ~/.claude/plugins は生まれません。レイヤー数を1つ減らせますし、意図しないファイルを巻き込む心配もありません。コピー方式よりわずかに扱いやすい構成です。
CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin marketplace add your-org/plugins
CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin install my-tool@your-pluginsこのコマンドを実行すると、マーケットプレイスの追加とプラグインのインストールが /opt/claude-seed に直接書き込まれます。Dockerfileの RUN ステップに組み込めば、コピー処理を挟まずにシードを完成させられます。
名前から「キャッシュだけを移す変数」だと誤解しやすいのですが、CLAUDE_CODE_PLUGIN_CACHE_DIR が実際に上書きするのはプラグイン関連ディレクトリ全体のルートです。既定では ~/.claude/plugins がこのルートに当たり、その配下に marketplaces/ と cache/ が展開されます。つまりこの変数へ指定した先には、キャッシュ単体ではなく、シードディレクトリと同じ2つのサブディレクトリがまとめて作られることになります。
手順3: ランタイムでシードを読ませる
イメージが完成したら、コンテナの実行時環境で環境変数を設定します。
export CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seed
claude起動時、Claude Codeはシードの known_marketplaces.json に登録されているマーケットプレイスをプライマリ設定へ登録し、cache/ にあるプラグインキャッシュをそのまま使います。再クローンは一切発生しません。対話モードでも、-p フラグを使った非対話モードでも同じです。
Dockerfileの中でビルドとランタイムの設定をまとめて書くと、次のような形になります。
# ビルドステージ: シードを直接作る
ENV CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed
RUN claude plugin marketplace add your-org/plugins && \
claude plugin install my-tool@your-plugins
# ランタイムステージ: シードを読ませる
ENV CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seedマルチステージビルドを使っている場合は、ビルドステージで作った /opt/claude-seed を最終イメージへ COPY --from=builder するだけで、ランタイムイメージ自体にはClaude Codeのインストール処理を含めずに済みます。
事前展開の挙動で押さえておくべき5点
シードディレクトリには、通常のプラグイン運用と異なる独自のルールがいくつかあります。先に押さえておきましょう。動かしてから戸惑うより、事前に確認したほうが早いはずです。
| 挙動 | 内容 |
|---|---|
| 読み取り専用 | 内容シードディレクトリへは一切書き込まれません。読み取り専用ファイルシステムで git pull が失敗しないよう、シード由来のマーケットプレイスは自動更新も無効になっています |
| シード優先 | 内容シードで宣言されたマーケットプレイスは、起動のたびにユーザー設定側の同名エントリを上書きします。シード側のプラグインを使いたくない場合は、マーケットプレイスを消すのではなく /plugin disable で個別に無効化してください |
| パス解決はプローブ方式 | 内容Claude Codeはシード内のJSONに記録されたパスを信用せず、実行時に $CLAUDE_CODE_PLUGIN_SEED_DIR/marketplaces/<name>/ を探索して見つけます。ビルド時と異なるパスにマウントしても、正しく動く理由はここにあります |
| 変更操作はブロックされる | 内容シード管理下のマーケットプレイスに対して /plugin marketplace remove や /plugin marketplace update を実行すると失敗します。管理者にシードイメージの更新を依頼するよう案内が出ます |
| 既存設定と合成される | 内容extraKnownMarketplaces や enabledPlugins で宣言されたマーケットプレイスがシード内に既にある場合は、クローンせずシード側のコピーがそのまま使われます |
「読み取り専用」と「シード優先」は、セットで理解しておくと運用の見通しが良くなります。シードは書き換えられません。その代わり、シード側で宣言済みのマーケットプレイスは起動のたびに確実にユーザー設定側の同名エントリへ反映されるため、コンテナを再作成しても同じ構成に揃います。設定を恒久的に変えたいなら、コンテナ側を直接いじるのは筋が悪いやり方です。シードイメージのビルド手順を直してビルドし直す、という原則を徹底しておけば、チームの誰が触っても同じ結論にたどり着けるでしょう。
「変更操作はブロックされる」という制約も、単なる制限ではなく安全装置です。仮に /plugin marketplace remove がシード管理下のマーケットプレイスに対しても素直に成功してしまうと、コンテナを起動するたびにシードが復元と削除を繰り返す不安定な状態になりかねません。エラーで止めて管理者への確認を促す設計は、この種の想定外の往復を防ぐためのものと読めます。
よくあるつまずき
シードを使い始めたチームが最初につまずくのは、「更新できない」ことを不具合だと誤解するケースです。シード管理下のマーケットプレイスは意図的に変更操作をブロックしています。壊れたわけではありません。/plugin marketplace update が失敗したら、ビルドパイプラインを再実行して新しいシードイメージを作り直すのが正しい対処です。
次に多いのが、探索順序の誤解です。複数のシードディレクトリを重ねている場合、どのシードが優先されているか分からなくなることがあります。: や ; で並べた順に探索されるという原則さえ覚えておけば十分です。優先させたいシードを先頭に置くだけで、意図通りの構成にできます。
シードの中身が古いまま気づかれないケースも起こりがちです。シードは読み取り専用で、自動更新も無効になっています。「動いているから最新のはず」という思い込みは通用しません。プラグインのバージョンを上げたら、シードイメージのビルドパイプラインも一緒に回して作り直す運用をセットで決めておきましょう。この食い違いはそれで防げます。
最後に、パスのマウント先を気にしすぎるという落とし穴もあります。シードはビルド時のパスをJSONに埋め込んで信用するのではなく、実行時に marketplaces/<name>/ を探すプローブ方式で動きます。ビルド環境とランタイム環境でマウントパスが違っていても、心配は無用です。
よくある質問
オフライン・エアギャップ環境でも動きますか
問題なく動きます。シードに含まれるマーケットプレイスとプラグインは、起動時に一切クローンや取得をせずそのまま使われるのが仕組みの前提だからです。ネットワーク接続が無い、あるいは制限されたCI環境向けに設計された機能です。
非対話モード(-p フラグ)でも使えますか
はい、そのまま使えます。対話セッションと -p を使った非対話実行のどちらでも、同じようにシードから読み込まれるとドキュメントに案内されています。バッチジョブやCIパイプラインの中でClaude Codeを呼び出す構成にも組み込めるでしょう。
一部のマーケットプレイスだけシードに含めることはできますか
含められます。シードは全てのマーケットプレイスを含める必要はなく、頻繁に使うものだけを事前展開し、それ以外は extraKnownMarketplaces などの通常の設定で登録する構成も想定できます。宣言したマーケットプレイスがシード内にも存在する場合は、クローンせずシード側のコピーが優先されます。
シードの中身を更新したいときはどうすればよいですか
シード自体は読み取り専用なので、稼働中のコンテナに入って書き換えることはできません。プラグインのバージョンを上げたい、あるいはマーケットプレイスの内容を変えたいときは、ビルドパイプラインを再実行して新しいシードを作り直し、イメージを差し替えるのが唯一の正しい手順です。/plugin marketplace update のような対話的な更新コマンドは、シード管理下のマーケットプレイスに対しては失敗するよう作られています。
CIとローカル開発で構成を変える
CI専用のシードイメージと、開発者が手元で使うローカル環境を同じ設定にする必要はありません。CI側は「決まったプラグイン一式だけを固定して高速に起動する」ことが目的なので、シードには本当に必要なマーケットプレイスだけを絞り込んで含めるのが合理的です。逆にローカル開発では、シードを使わずに通常の /plugin marketplace add を使い、都度最新の状態を試せるようにしておいたほうが、新しいプラグインを試す小回りが利きます。
同じ marketplace.json をCIとローカルの両方で参照する構成にしておけば、シードの有無による差はビルド速度とオフライン耐性だけに留まり、プラグインの中身自体はどちらの環境でも同じものを使えます。CLAUDE_CODE_PLUGIN_SEED_DIR を設定するかどうかは環境変数1つの違いなので、CI用のDockerfileとローカル用の起動スクリプトを条件分岐で出し分けるだけで両立できます。
まとめ
CLAUDE_CODE_PLUGIN_SEED_DIR を使えば、CIやコンテナイメージのビルド時にマーケットプレイスとプラグインを用意しておき、ランタイムでは一切クローンせずに起動できます。コピー処理を省きたい場合は CLAUDE_CODE_PLUGIN_CACHE_DIR をビルド時の目的地に直接向けるのが最短です。シードは読み取り専用で、変更したい場合は必ずビルドパイプライン側を更新します。
マーケットプレイス自体の作り方や配布方法はClaude Codeプラグイン完全ガイド、シードに焼き込む前の検証はマーケットプレイスのstrict modeとvalidateで確認してから、イメージのビルドに進むと手戻りが減ります。