Claude Media
Claude Codeプラグインのコマンドソースでマーケットプレイスを動的生成する

Claude Codeプラグインのコマンドソースでマーケットプレイスを動的生成する

プラグインのコマンドソースはローカルツールが出力するディレクトリをそのままインストールする仕組みです。設定方法とcopy/linkモードの違い、承認フローの注意点をまとめます。

Claude Codeプラグインのコマンドソースでマーケットプレイスを動的生成する

marketplace.jsonのプラグインエントリにはcommandというsource種別があり、ローカルにインストール済みのツールが吐き出すディレクトリを、そのままプラグインとして取り込めます。IDEが選択中のツールチェーンに応じてプラグイン内容を生成するような、固定の配布物を持たないケース向けの仕組みです。対応はClaude Code v2.1.229以降で、それより前のバージョンでは動作が異なります。

コマンドソースとは何か

github / url / git-subdir / npm / ローカルパスといった通常のsource種別は、いずれも「どこかに固定された配布物」を指します。Claude Codeはそこからファイル一式を取得し、キャッシュへコピーするだけです。commandはこの前提が違います。指定するのは配布物の場所ではなく、配布物をその場で作り出すコマンドです。このコマンドはユーザーのホームディレクトリをカレントディレクトリとして実行されるため、相対パスを渡すとその場所が意図通りに解決されない点に注意が必要です。

{
  "name": "my-plugin",
  "source": {
    "source": "command",
    "command": "my-tool claude-plugin-path"
  }
}

このコマンドはインストール時にプラットフォームのシェル(macOS/Linuxはsh、Windowsはcmd.exe)経由で実行され、標準出力にちょうど1行、プラグインの中身が入った絶対パスを出力して終了コード0で終わる必要があります。出力されるパスは実行のたびに変わってもかまいません。

各source種別の性格を並べると、コマンドソースの立ち位置がはっきりします。

source種別中身の決まり方更新のきっかけ向くケース
github / url / git-subdir中身の決まり方リポジトリの特定コミット更新のきっかけref更新やタグの新規push向くケース固定の配布物を公開する一般的なプラグイン
npm中身の決まり方パッケージの特定バージョン更新のきっかけregistryへの新規publish向くケースnpmで配布したい既存資産の流用
archive中身の決まり方zipファイルの内容(SHA-256で追跡)更新のきっかけzipの差し替え向くケース静的サーバーやアーティファクトリポジトリでの配布
command中身の決まり方コマンド実行のたびに再生成更新のきっかけローカルツールの状態そのもの向くケースIDE連携などツールの出力を都度反映したいケース

設定できるフィールド

commandのsourceオブジェクトが受け付けるフィールドは3つだけです。

フィールド説明
commandstring説明必須。実行可能なASCII文字のみ、500文字以内、4スペース以上の連続なしという制約がある(利用者が承認前に全文を読めるようにするため)
timeoutnumber説明省略可。コマンドの待機秒数(既定60秒、上限600秒)
modestring説明省略可。"copy"(既定)または"link"

commandの文字数・空白制約は、承認ダイアログでコマンド全文をひと目で確認できるようにするための設計です。長すぎたり空白で読みにくいコマンドは、その場でラッパースクリプトに置き換える必要があります。

インストールが拒否される条件

コマンドが正常に終了しても、出力されたパスの中身次第でインストール・更新は失敗します。実行がtimeout秒(既定60秒、上限600秒)を超えた場合はその時点で打ち切られ、失敗として扱われます。加えて、出力されたディレクトリが次のいずれかに当てはまる場合も拒否されます。

  • トップレベルに.claude-plugin/ディレクトリも、skills/commands/agents/hooks/のいずれのディレクトリも無く、プラグインの中身と呼べる要素が見当たらない
  • 出力されたディレクトリが、Claude Codeを起動したディレクトリ、またはその親ディレクトリと同じ
  • Windows環境で、パスがUNCパス(\\server\share形式)になっている

いずれも「実在するディレクトリを渡しているのに失敗する」ように見えるため、コマンドの標準出力が正しいパスを返しているかだけでなく、そのパスが指す中身とディレクトリの位置関係、そしてコマンド自体が制限時間内に終わっているかまで確認するのがトラブルシューティングの近道です。

copyモードとlinkモードの違い

既定のcopyモードでは、出力されたディレクトリをバージョン管理されたプラグインキャッシュへコピーし、ディレクトリの中身のハッシュからバージョンを算出します。ツール側は出力後にディレクトリを削除・書き換えしてかまいません。同じ内容を出力すれば「最新のまま」として扱われます。ただしコピー対象は256MiB以下・2万エントリ以下という上限があります。

linkモードは、SDKのレンダリング結果のようにコピーしたくない大きなディレクトリ向けです。中身をハッシュ化せず、トップレベルの各エントリへのリンクをキャッシュに作るだけなので、サイズ上限も適用されません。バージョンの決まり方もcopyモードとは違います。ハッシュの対象は出力されたディレクトリの実パスとトップレベルのエントリ一覧であり、中身のファイル内容そのものではありません。同じパスに新しい内容を出力しても実パスとトップレベル構成が変わらなければ新バージョンとして検知されないため、更新を反映したいときは別のパスを出力する必要があります。

出力元のディレクトリはプラグインが有効な間ずっと存在させておく必要があります。起動のたびにそのリンク経由で読み込まれるためです。トップレベルのエントリが出力ディレクトリの外を指すシンボリックリンクだと、インストールは失敗します。linkモードにはほかにも制限があり、Node.jsパッケージの依存関係インストールはスキップされるため、出力ディレクトリにnode_modulesを同梱しておく必要があります。また出力ディレクトリの内部またはその配下でセッションを開始した場合、そのプラグインは読み込まれません。加えてWindowsではlinkモード自体が使えません。

観点copyモードlinkモード
コピーの有無copyモードキャッシュへ複製linkモード複製せずリンクのみ
バージョンの決まり方copyモードディレクトリの中身のハッシュlinkモード実パス+トップレベルエントリのハッシュ
サイズ上限copyモード256MiB / 2万エントリlinkモード上限なし
出力ディレクトリの扱いcopyモード実行後は消してよいlinkモード有効な間は残しておく必要がある
Windows対応copyモード対応linkモード非対応

いつコマンドが再実行されるか

出力ディレクトリはツールのその時点の状態を反映したものなので、Claude Codeは何度もコマンドを実行し直します。再実行が起きるのは次の3つの場面です。

  • ユーザーがプラグインをインストール・更新するたび
  • 有効化されている各コマンドソースプラグインについて、セッション開始直後にバックグラウンドで1回(マーケットプレイスの自動更新設定とは無関係に動く)
  • 起動時または/reload-plugins実行時、キャッシュに該当バージョンが見当たらないとき

出力のハッシュが変わっていれば新バージョンとしてインストールされ、実行中のセッションにもその場で反映されます。ただし反映によってプロンプトキャッシュが無効化される場合は、代わりに/reload-pluginsの実行を促す通知が出ます。CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICを設定していると、この2つのバックグラウンド実行はスキップされます。明示的なインストール・更新の実行はこの変数の影響を受けません。

承認とセキュリティの扱い

コマンドソースはユーザーのマシン上で任意のコマンドを実行するため、実行のたびに明示的な承認が絡みます。/pluginの詳細画面や対話シェルでのclaude plugin install/claude plugin updateでは、コマンド全文が表示され、承認したコマンドがそのインストールに記録されます。非対話シェルでは--yesを付けて承認したことにできます。

コマンドソース側のcommandmodeを後から変更しても、既にインストール済みのユーザーは自動では追随しません。バージョンはそのまま維持され、/pluginのErrorsタブに新しいコマンドの内容が表示されて、ユーザーがclaude plugin update <plugin>@<marketplace>で改めて承認するまで待たされます。

複数プラグインの一括インストールや、他のプラグインの依存関係としての導入では、コマンドソースのプラグインだけは決して自動導入されません。ユーザーが先に単体でインストールしておく必要があり、それを依存として要求する側のプラグインは、依存先が入るまでインストールに失敗します。組織側で一律に塞ぎたい場合は、managed settingsのdisableCommandPluginSourcesでコマンドソース自体を無効化でき、allowManagedHooksOnlyを有効にした組織では既定でコマンドソースがブロックされます。

向く場面・向かない場面

固定の配布物を扱う他のsource種別と比べると、コマンドソースが本領を発揮する場面はかなり狭くなります。

用途向くか理由
IDEが選択中のツールチェーンに応じてプラグインを生成する向くか向く理由ツール側の状態が変わるたびに、再インストールなしで反映できる
SDKのビルド成果物をそのままプラグインとして使う向くか向く(linkモード)理由サイズが大きく毎回コピーするのは非効率な出力を、リンクだけで済ませられる
一般公開するOSSプラグインの配布向くか向かない理由利用者ごとにローカルツールの実行環境を要求するのは負担が大きく、githubソースで十分
他プラグインからの依存として組み込む向くか向かない理由コマンドソースは依存として自動導入されない仕様のため、バンドル構成に混ぜると導入が止まる

向かないケースで無理に使うと、承認のたびにコマンド内容を確認させられる分だけ利用者の手間が増えます。配布物が固定できるなら、通常のsource種別を選ぶほうが素直です。

よくあるつまずき

  • バージョン要件を満たしていない: v2.1.120〜v2.1.228ではインストール自体が「バージョンが未対応」というエラーで失敗し、それより前のバージョンではマーケットプレイス全体の読み込みが失敗します。組織で古いバージョンが混在している場合は、事前にバージョンを揃えるかコマンドソース以外の配布手段を用意しておきます。
  • 出力先ディレクトリの位置を誤る: 出力パスがClaude Codeを起動したディレクトリ、またはその親ディレクトリと一致すると、インストールは拒否されます。プラグイン専用の作業ディレクトリを別途用意するのが安全です。
  • linkモードで出力元を消してしまう: linkモードはコピーしないため、出力元のディレクトリを片付けてしまうと次回起動時に読み込めなくなります。copyモードとの違いを忘れがちなので、運用手順に明記しておきます。
  • 依存関係として組み込もうとする: コマンドソースのプラグインは他プラグインの依存として自動インストールされないため、バンドルの中に混ぜると導入フローが途中で止まります。バンドル構成にコマンドソースを含めないのが無難です。

よくある質問

コマンドソースはマーケットプレイスを追加した時点で動きますか

動きません。マーケットプレイスの追加自体ではコマンドは実行されず、対象プラグインを単体でインストールまたは更新するときに初めてコマンド全文が表示され、承認して初めて実行されます。

出力先のパスを毎回変えても問題ありませんか

copyモードなら問題ありません。パスは実行のたびに変わってよく、Claude Codeはディレクトリの中身のハッシュだけを見て新しいバージョンかどうかを判断します。linkモードでは、パスの実体そのものが有効な間ずっと残っている必要があります。

依存関係としてバンドルに組み込めますか

組み込めません。コマンドソースのプラグインは他プラグインの依存として自動インストールされない仕様になっています。依存として要求する側は、ユーザーがコマンドソース側を単体で先にインストールするまでエラーになります。

組織全体でコマンドソースを禁止できますか

できます。managed settingsのdisableCommandPluginSourcestrueにすると全体で無効化され、allowManagedHooksOnlyを有効にしている組織では明示的にfalseにしない限り既定でブロックされます。

まとめ

コマンドソースは、配布物を固定せずローカルツールの出力をそのままプラグイン化する手段です。copy/linkの2モードで用途を切り分け、セッション開始時のバックグラウンド再実行によってツール側の変更を自動で拾います。一方で承認は毎回ユーザー自身が行う設計になっており、依存関係の自動導入や一括インストールの対象外という制約も押さえておく必要があります。マーケットプレイス全体の仕組みはClaude Codeプラグイン完全ガイド、組織側でコマンドソースを制御する設定はClaude Code組織管理ガイド、反映のタイミングを手動で制御したいときは/reload-pluginsの使い方を参照してください。

この記事を共有:XはてブLinkedIn