CLAUDE_CODE_PLUGIN_DIRSで複数プラグインをセッション単位で読み込む
環境変数CLAUDE_CODE_PLUGIN_DIRSに複数のパスを並べると、--plugin-dirと同じ読み込み方で複数プラグインをそのセッションだけ有効にできます。区切り文字・パスの書き方・優先順位・管理者による無効化を解説します。
CLAUDE_CODE_PLUGIN_DIRSは、そのセッションだけ読み込むプラグインのディレクトリを環境変数で列挙するための変数です。--plugin-dirフラグと同じ読み込み方をするので、コマンドラインに引数を足せない起動経路でも、複数のプラグインを開発中のまま試せます。Claude Code v2.1.280以降で使えます。
CLAUDE_CODE_PLUGIN_DIRSは何をする変数か
公式のenv-varsリファレンスは、この変数を「セッション中に読み込むプラグインディレクトリの一覧。各パスは--plugin-dirフラグと同じ方法で読み込まれる」と説明しています。読み込んだプラグインは、そのセッションだけ有効です。設定ファイルには何も書き込まれません。
仕様は次の5点に収まります。
| 項目 | 内容 |
|---|---|
| 区切り文字 | 内容Unixは:、Windowsは; |
| パスの書き方 | 内容絶対パス、または~で始まるパス |
| 相対パス | 内容Claude Codeが読み飛ばす |
| 他の読み込み経路との関係 | 内容--plugin-dirで渡したプラグインに加えて読み込まれる |
| 必要なバージョン | 内容v2.1.280以降 |
「読み飛ばす」という表現に注意してください。相対パスがエラーになるとはどこにも書かれていません。書き間違えても起動は通るので、プラグインが出てこない原因として真っ先に疑う箇所です。
複数のパスを並べる書き方
Unix系(macOSとLinux)では、:でパスをつなぎます。
export CLAUDE_CODE_PLUGIN_DIRS="$HOME/dev/review-plugin:$HOME/dev/deploy-plugin"
claude~始まりでも書けます。~の展開を確実にしたいときは、$HOMEを使ってシェル側で絶対パスにしてから渡す書き方が安全です。許可されているのは絶対パスか~始まりの2形式だけなので、./my-pluginのような相対指定は使えません。
Windowsのpowershellでは区切りが;になります。次は書き方の一例です。
$env:CLAUDE_CODE_PLUGIN_DIRS = "C:\dev\review-plugin;C:\dev\deploy-plugin"
claude1回だけ有効にしたいなら、変数を前置きして起動する形が手軽です。
CLAUDE_CODE_PLUGIN_DIRS="$HOME/dev/review-plugin:$HOME/dev/deploy-plugin" claude指すのは、プラグインのルートディレクトリ(.claude-plugin/plugin.jsonとskills/などが入ったフォルダ)です。配布形式ごとの違いはClaude Codeプラグインソースの使い分けに、zipでの一時ロードはプラグインのzip配布にあります。
--plugin-dirとの違いと使い分け
環境変数と--plugin-dirは同じ読み込み方ですが、渡し方が違います。
| 比較点 | --plugin-dir | CLAUDE_CODE_PLUGIN_DIRS |
|---|---|---|
| 渡し方 | --plugin-dir起動時のフラグ | CLAUDE_CODE_PLUGIN_DIRS環境変数 |
| 複数指定 | --plugin-dirフラグを繰り返す(1フラグ1パス) | CLAUDE_CODE_PLUGIN_DIRS区切り文字でつなぐ |
| 併用 | --plugin-dir可 | CLAUDE_CODE_PLUGIN_DIRS可(フラグ分に追加して読み込まれる) |
| 設定ファイルのenvブロック | --plugin-dir該当なし | CLAUDE_CODE_PLUGIN_DIRSproject / localの設定では指定できない |
| 管理者による無効化 | --plugin-dir可 | CLAUDE_CODE_PLUGIN_DIRS可 |
向き不向きは、起動経路で決まります。ラッパースクリプトやコンテナのエントリポイント、CIのジョブ定義のように、環境変数は渡せるがコマンドラインの引数は組み立てにくい場面では変数が扱いやすくなります。逆に、手でclaudeを叩いて一度だけ試すなら、フラグのほうが短く済みます。
変数の用途として挙げられているのは「フラグを足せないセッションで読み込むとき」です。フラグと変数を同時に使っても衝突せず、両方のプラグインが有効になります。
環境変数を渡す場所と、渡せない場所
「プロジェクト設定とローカル設定ではこの変数を設定できない」と明記されています。リポジトリにコミットされる.claude/settings.jsonや.claude/settings.local.jsonのenvブロックに書いても、プラグインの読み込み元にはなりません。任意のディレクトリのコードを、チェックアウトしたリポジトリの都合で読み込ませないための制限と読めます。
公式がこの変数について書いている制限は、project / localの設定で指定できないという1点です。ユーザー設定のenvブロックについては、この変数を除外する記述は見当たりません。ただ、プラグインのパスを設定ファイルに固定すると「そのセッションだけ」という性格が薄れます。現実的な置き場所は、次のとおりです。
- シェルの起動ファイル(bashなら
~/.bashrc、zshなら~/.zshrc)にexportを書く。全セッションに効かせる方法としてenv-varsページが案内している形です - 起動用のラッパースクリプト
- コンテナのenv指定やCIジョブの環境変数
シェルで渡した変数は、claudeの起動時に1回読まれます。値を変えたら、次の起動から反映されます。変数を設定した端末でだけ有効になるので、端末を閉じれば読み込みも終わります。
設定ファイルのenvブロックとシェルのexportが同じ変数を持つと、設定ファイル側の値が勝つのが一般ルールです。この変数をシェルで渡しているのに反映されないときは、ユーザー設定やmanaged settingsのenvに別の値が入っていないかを疑います。
たとえば、チームで共有するプラグイン群を開発用ラッパーから読み込む構成は、次のような形になります(例示であり、推奨構成ではありません)。
#!/usr/bin/env bash
# dev-claude.sh: 開発中のプラグインを2つ読み込んで起動する
PLUGINS_ROOT="$HOME/dev/plugins"
export CLAUDE_CODE_PLUGIN_DIRS="$PLUGINS_ROOT/review:$PLUGINS_ROOT/deploy"
exec claude "$@""$@"を渡しているので、--modelなど他のフラグはそのまま使えます。
同名のプラグインが入っているとどうなるか
インストール済みのプラグインと、環境変数で読み込んだプラグインの名前(manifestのname)が同じ場合は、公式のプラグイン読み込みリファレンスの優先順位で決まります。要点は次のとおりです。
- managed settingsの
enabledPluginsに載っているプラグインが最優先。ここに載った名前は、--plugin-dir側の同名コピーが読み込まれません - その次が、有効な
--plugin-dir・--plugin-url・CLAUDE_CODE_PLUGIN_DIRSのプラグイン。同名のインストール済みマーケットプレイスプラグインとスキルディレクトリのプラグインを置き換えます - その次が、インストール済みのマーケットプレイスプラグイン
マーケットプレイスからインストール済みのプラグインを置き換える場合、claude plugin listのマーケットプレイス側の行は有効のままです。表示は設定を反映しているだけで、実際に読み込まれるのは環境変数側のコピーです。切り替わったことを確かめるには、--debug付きで起動して~/.claude/debug/のログを見ます。ログにはPlugin "<name>" from --plugin-dir overrides installed versionという形の記録が出ると公式に書かれています。
自作プラグインを直しながら、配布済みの同名版と入れ替えて試せるのが、この仕組みの実用面です。アンインストールは要りません。
管理者がセッション単位の読み込みを止める設定
組織のmanaged settingsでdisableSideloadFlagsをtrueにすると、--plugin-dir・--plugin-url・--agents・--mcp-configが起動時に拒否されます。strictKnownMarketplacesで許可リストを作っても、これらのフラグで1回限りの読み込みを許してしまうと迂回できるためです。
{
"disableSideloadFlags": true
}この検査は、CLAUDE_CODE_PLUGIN_DIRSにも及びます。変数がプラグインのフォルダを指していると、フラグのときと同じエラーで終了し、エラー文には変数を外すよう案内が出ます。「変数なら通る」という抜け道にはなりません。
社内配布のプラグインしか使わせない環境では、この設定が入っている可能性があります。起動できないときは、まずエラー文に変数名が出ていないかを見てください。disableSideloadFlagsは、プラグインの中身ではなく読み込み経路そのものを閉じるスイッチです。プラグイン同士の依存を扱う話はプラグインの依存関係にあります。
読み込みを確認する手順と、つまずきやすい点
まず、起動前に同じシェルで変数の中身を出力し、区切りとパスが意図どおりか目で確かめます。代入の行は成功しても何も表示しないので、この確認が欠かせません。
echo "$CLAUDE_CODE_PLUGIN_DIRS"読み込めたかどうかは、セッション内で/pluginを開くか、--debugのログで確認します。フラグ経由のプラグインについて、claude plugin listが<name>@inlineという名前でスコープsessionとして表示すると説明し、フラグをサブコマンドの前に置く必要があるとも書いています(例: claude --plugin-dir ./my-plugin plugin list)。環境変数で読み込んだプラグインが同じ表示になるかは、公式のページに記述がありません。表示が出ないときは、/pluginのErrorsタブと--debugログで確かめるのが確実です。プラグインのファイルを編集した後は、/reload-pluginsで変更を読み直します。手順は/reload-pluginsで再起動なしにプラグインを反映するにまとまっています。
つまずきは、次の4つに集約されます。
- 相対パスを書いている: 読み飛ばすと明記されている。
./plugins/fooではなく$HOME/...や~/...にします - 区切り文字を間違えている: Unixは
:、Windowsは;。WindowsのパスはC:\のようにドライブ文字のコロンを含むので、Unix用の:でつなぐと壊れます - バージョンが古い: v2.1.280より前のバージョンでは、この変数は読まれません。
claude --versionで確認します - マーケットプレイスのルートを指している:
--plugin-dir側の説明で、公式はマーケットプレイスのルートを指してもmarketplace.jsonは読まれず、plugins/配下のプラグインはエラーなしで読み込まれないと書いています。変数も「同じ読み込み方」なので、指すのは1つのプラグインのフォルダにします
フォルダを渡して中の複数プラグインをまとめて読み込む機能は、--plugin-dir側の仕様です。.claude-plugin/も最上位のコンポーネントも持たないフォルダは「プラグインのフォルダ」として扱われ、直下の各サブフォルダのうち.claude-plugin/plugin.jsonを持つものが別々のプラグインとして読み込まれます(v2.1.265以降)。marketplace.jsonを併置したフォルダも、plugin.jsonが無ければ読み込める仕様が、v2.1.281以降で追加されています。環境変数に複数の:区切りを並べる代わりに、束ねたフォルダを1つ渡す形も選べます。
まとめ
CLAUDE_CODE_PLUGIN_DIRSは、--plugin-dirと同じ読み込みを環境変数から行う入口です。区切りは:と;、パスは絶対か~始まり、相対パスは黙って無視されます。project / localの設定ファイルには書けず、managed settingsのdisableSideloadFlagsが有効な環境では使えません。フラグを足せない起動経路で、複数の自作プラグインをセッション限りで試したい場面に向いています。
同名の配布版との入れ替えも、この変数で足ります。優先順位と、claude plugin listの表示が実際の読み込みと一致しない点だけ押さえておけば、日々の開発ではほとんど迷いません。