Claude Codeプラグインの依存バージョンを固定する
プラグインが他プラグインに依存するとき、semverレンジで対象バージョンを固定できます。書き方から複数制約の衝突解決、タグ付けとエラー対処までを扱います。
Claude Codeプラグインの依存バージョンを固定する
プラグインはplugin.jsonやマーケットプレイスのエントリで他プラグインへの依存を宣言できます。バージョンを書かない依存は、マーケットプレイスが出す最新版を追い続けます。依存関係の全体像はClaude Codeプラグインの依存関係にあり、この記事はバージョン制約とタグ付けに絞ります。
なぜバージョンを固定する必要があるのか
社内マーケットプレイスで2つのチームがプラグインを公開している場面を考えます。プラットフォームチームはシークレット管理をラップするMCPサーバーsecrets-vaultを、デプロイチームはデプロイ時にsecrets-vaultから認証情報を取得するdeploy-kitを維持しています。deploy-kitはsecrets-vaultのv2.1.0に対して動作確認済みです。
secrets-vaultがMCPツール名を変えたとき
制約なし
次の更新で全員のsecrets-vaultが新バージョンへ移ります。deploy-kitが呼んでいたツール名が消え、動かなくなります。
~2.1.0を付けた
deploy-kitを入れた人は2.1.xのパッチだけを受け取ります。新バージョンはデプロイチームが検証し、制約を広げたdeploy-kitを公開した時点で届きます。
依存の書き方とsemverレンジ
依存は.claude-plugin/plugin.jsonのdependencies配列に列挙します。要素は文字列かオブジェクトで、文字列は"audit-logger"のようにプラグイン名だけです。別のマーケットプレイスのプラグインは"audit-logger@your-shared-marketplace"と書けます。
{
"name": "deploy-kit",
"version": "3.1.0",
"dependencies": [
"audit-logger",
{ "name": "secrets-vault", "version": "~2.1.0" }
]
}バージョン制約を付けるにはオブジェクト形式を使います。使えるフィールドは3つです。
| フィールド | 説明 |
|---|---|
name | 説明依存先のプラグイン名。marketplaceを指定しなければ宣言元と同じマーケットプレイスで探される(必須) |
version | 説明~2.1.0 ^2.0 >=1.4 =2.1.0のようなsemverレンジ。条件を満たす最も高いgitタグで依存先が入る |
marketplace | 説明依存先を別マーケットプレイスで解決したいときに指定する |
レンジの記法はnode-semverに準拠します。意図と違う範囲を固定しがちなので、代表的な記法を並べます。
| 記法 | 意味 | 2.1.5は含むか |
|---|---|---|
~2.1.0 | 意味2.1.xのパッチ更新のみ許容 | 2.1.5は含むか含む |
^2.1.0 | 意味2.xのマイナー・パッチ更新を許容(メジャーは固定) | 2.1.5は含むか含む |
>=2.1.0 | 意味指定バージョン以上をすべて許容 | 2.1.5は含むか含む |
=2.1.0 | 意味そのバージョンのみに固定 | 2.1.5は含むか含まない(2.1.0のみ) |
2.0.0-beta.1のようなプレリリース版は、^2.0.0-0のようにレンジ側でプレリリースを許容しない限り対象外です。
複数の制約がぶつかったときの解決順序
同じ依存先を複数のプラグインが制約している場合、Claude Codeはすべてのレンジを満たす最も高いバージョンに解決します。
| プラグインAの要求 | プラグインBの要求 | 結果 |
|---|---|---|
^2.0 | プラグインBの要求>=2.1 | 結果2.1.0以上の2.x系で最も高いタグに1本化。両プラグインとも読み込まれる |
~2.1 | プラグインBの要求~3.0 | 結果プラグインBのインストールがhas conflicting version requirementsで失敗。プラグインAと依存先は元のまま |
=2.1.0 | プラグインBの要求指定なし | 結果依存先は2.1.0に固定。プラグインAが入っている間、自動更新は新しいバージョンをスキップする |
自動更新は、依存先を「マーケットプレイスの最新版」ではなく「インストール済み全プラグインのレンジを満たす最も高いgitタグ」で取得します。ここで2つの分かれ道があります。
- レンジが重ならない: 依存先は今のバージョンのまま。
/pluginのErrorsタブに、制約しているプラグイン名つきの項目が出ます - レンジは重なるがタグが無い: マーケットプレイスの現行コピーを取得し、そのコピーの
versionがいずれかのレンジの外なら更新を見送ります
ある依存を制約している最後のプラグインをアンインストールすると、依存先はマーケットプレイスのエントリを追う状態に戻ります。
別マーケットプレイスの依存とバンドルでのレンジ
依存先が別のマーケットプレイスにあるときは、許可が要ります。入れる側のルートのマーケットプレイスのmarketplace.jsonに、allowCrossMarketplaceDependenciesOnで書きます。同じスコープで利用者がその依存先をすでに有効にしている場合だけは、許可なしで通ります。許可リストに無い場合の挙動は、依存をどこに宣言したかで分かれます。エントリに書いていれば、インストール自体がis in marketplace "...", which is not in the allowlistで拒否されます。plugin.jsonに書いていれば、依存だけが入らないままインストールが完了します。
nameとdependenciesだけのマニフェストも有効なプラグインで、インストールすると依存がすべて入ります。チーム標準セットの組み方は依存関係の記事にあります。バージョンに関わるのは、{ "name": "db-migrate", "version": "^3.0" }のようにセット内の依存へレンジを付けられる点です。セットに依存を足すときはbackend-standardの新バージョンを公開します。自動更新が無効なら、利用者がclaude plugin update backend-standardと/reload-pluginsを実行します。不要になった自動インストールの依存は、claude plugin pruneで取り除けます。
タグ付けとバージョン解決の対応
バージョン制約はgitタグを基準に解決されます。タグを打つリポジトリは、プラグインのソースの種類で決まります。github / url / git-subdirなら依存先自身のリポジトリ、./plugins/secrets-vaultのような相対パスならマーケットプレイスのリポジトリです。
依存される側のリリース手順
- 1
versionを上げる
plugin.jsonのversionを更新します。マーケットプレイスのエントリにもversionがあるなら同じ値にそろえます。 - 2
コミットする
タグはコミットに付くので、変更はコミットしておきます。
- 3
タグを打ってpushする
プラグインのディレクトリで
claude plugin tag --pushを実行すると、{plugin-name}--v{version}のタグが作られ、originへ送られます。 - 4
依存する側で解決される
~2.1.0のようなレンジは、そのリポジトリのsecrets-vault--v*タグのうちレンジを満たす最も高いものに解決されます。
claude plugin tagは、タグを作る前にプラグインを検証し、マーケットプレイスのチェックアウト内にあるときはplugin.jsonとエントリのバージョンの一致も調べます。--pushを省略すると実行すべきgit pushコマンドを表示するだけで、--remoteでorigin以外も指定できます。pushに失敗してもタグはローカルに残り、コマンドは終了コード1で終わります。git tagで直接打つこともできますが、その場合はplugin.jsonとエントリのversionをそろえる作業が自分に戻ります。
Claude Code v2.1.287で、一時ディレクトリのgitリポジトリにsecrets-vault(versionは2.1.0)を置いて試した出力です。--dry-runは、作るタグ名と実行されるgitコマンドを表示します。
claude plugin tag --dry-run .Plugin: secrets-vault
Version: 2.1.0 (from plugin.json)
Tag: secrets-vault--v2.1.0
✔ Dry run — would create tag secrets-vault--v2.1.0 at HEAD in /path/to/secrets-vault
git -C /path/to/secrets-vault tag -a secrets-vault--v2.1.0 -m "secrets-vault 2.1.0"
git -C /path/to/secrets-vault push origin refs/tags/secrets-vault--v2.1.0タグは注釈付き(-a)で作られ、メッセージの既定は<name> <version>です。同じコマンドをタグ作成後にもう一度実行すると、次のように拒否されます。
✘ Tag "secrets-vault--v2.1.0" already exists locally. Bump the version in plugin.json, or re-run with --force to move the tag.plugin.jsonを書き換えてコミットしないままタグを打とうとすると、未コミットの変更があるため止まります。
✘ Uncommitted changes affecting this release — commit them first so the tag points at the version you intend to release (or use --force): .claude-plugin/plugin.json同じ環境で、dependenciesに"version": "not-a-range"という不正なレンジを書いたマニフェストをclaude plugin validateにかけると、Validation passed with warningsで通りました。警告はdescriptionとauthorの未設定だけです。レンジの書式ミスは検証では見つからず、解決時にhas an invalid version requirementのようなエラーとして表れます。
タグを打った後は、依存元でclaude plugin listを実行すると解決先を確認できます。タグから解決された依存は、2.1.0-8713c5b11005のようにコミットSHAの先頭12文字が付いたバージョンで表示されます。
制約のチェックは、plugin.jsonのversionではなくタグ側のバージョンに対して行われます。そのコミットのplugin.jsonが古いままでも、タグが新しければ新しいバージョンとして照合されます。既存のタグをforce-moveして別のコミットを指すように付け替えた場合は、次のインストールで新しいコミットの内容が取得され、古いキャッシュは使われません。
ローカル開発時とバージョンチェックの扱い
依存先を--plugin-dirで同時に開発している場合は、両方を読み込みます。
claude --plugin-dir ./my-dependency --plugin-dir ./my-pluginローカルコピーは、依存エントリがマーケットプレイス名を指定していても依存を満たし、バージョン制約はチェックされません。そのためローカルのplugin.jsonにversionを書く必要はありません。この一致はv2.1.242以降のものです。v2.1.242より前は、マーケットプレイス名つきの依存エントリがローカルコピーと一致せず、--plugin-dirで同時に読み込んでも解決されませんでした。changelogでは、2.1.243の項にこの修正が載っています。
両方のプラグインが同じ親フォルダにあるなら、その親フォルダを--plugin-dirに1回渡せば足ります。親フォルダ自体がプラグインでない場合、.claude-plugin/plugin.jsonを持つ子フォルダがそれぞれ読み込まれます。この書き方はv2.1.265以降です。
ローカルコピーが無効または不在になると、マーケットプレイスから依存をインストールするまで、プラグインは読み込まれません。メッセージは2通りです。
- ローカルコピーを無効にした: 次のプラグイン読み込みで、末尾が
is disabled — enable it or remove the dependencyのエラーが出ます。依存先が<name>@inlineと表示されたら、それは--plugin-dirのコピーです - 依存先の
--plugin-dirを付けずにセッションを始めた: 依存先が未インストールとして報告されます
versionキーの3つの居場所
versionという語は、プラグインの設定に3か所で登場し、それぞれ役割が違います。
versionの3つの役割
plugin.jsonのトップレベル
そのプラグイン自身のバージョンです。
dependenciesの中
依存先への制約です。
~2.1.0のようなレンジで、自身のバージョンとは無関係です。マーケットプレイスのエントリ
マーケットプレイス側に書く、自身のバージョンです。
ソースを指定して追加したマーケットプレイスでは、commandソース以外の自身のバージョンは次の順で決まります。claude.aiでホストされるマーケットプレイスでは、claude.aiが記録したバージョンが使われます。
| 順位 | 決まり方 | 該当するもの |
|---|---|---|
| 1 | 決まり方plugin.jsonのversion | 該当するものすべて |
| 2 | 決まり方マーケットプレイスエントリのversion | 該当するものすべて |
| 3 | 決まり方コミットSHAの先頭12文字(git-subdirはサブディレクトリのパスのハッシュも付く) | 該当するものgithub / url / git-subdir |
| 3 | 決まり方コミットSHA | 該当するものgit管理されたマーケットプレイスの相対パス |
| 3 | 決まり方SHA-256ダイジェストの先頭12文字 | 該当するものarchive |
| 3 | 決まり方unknown | 該当するものnpmと、git管理外のローカルディレクトリ |
plugin.jsonに"version": "1.0.0"を固定すると、何コミット重ねても、作者が文字列を変えるまで利用者はキャッシュ済みのコピーのままです。コミットごとに追わせたいなら、plugin.jsonとエントリの両方でversionを省きます。commandソースは別で、コマンドが出力した内容から導いた12文字のハッシュ(plugin.jsonにversionがあれば<version>-<hash>)が使われ、エントリのversionは無視されます。
gitソース以外の依存に制約を付ける
タグによる解決は、gitを使うソースにしか働きません。npm / archive / commandソースの依存では、取得するバージョンをレンジが決めることはなく、プラグインの読み込み時にチェックだけが走ります。インストール済みのバージョンがレンジを満たさなければ、依存元のプラグインは無効になります。
このとき照合されるのは依存先のplugin.jsonのversionです。バージョンを書いていないplugin.jsonはどのレンジも満たさないので、制約を付ける前に依存先へversionを入れておく必要があります。ハッシュベースで追跡されるarchiveソースのエラーは、archive integrity checkエラーの対処にまとめています。
commandソースの依存はClaude Codeが自分ではインストールしません。マーケットプレイスエントリにheadersHelperがある依存先も、依存元より先に利用者が単体でインストールします。次の操作も不足している依存を入れ、同じ制限を受けます。
/reload-plugins(使い方はこちら)- 依存元プラグインのマーケットプレイスの自動更新
- 依存元に対する
claude plugin installの再実行 claude plugin marketplace add
エラーが出たときの対処
バージョン制約の問題は、インストール時にエラーメッセージとして返るか、読み込み時にclaude plugin listと/pluginのErrorsタブへ出ます。後者では該当プラグインが無効のままになります。
| メッセージ | 意味 | 対処 |
|---|---|---|
Requires "<dep>" <range>, installed <version> | 意味インストール済みの依存先が制約範囲外 | 対処範囲内のバージョンへ更新する |
... has conflicting version requirements | 意味全レンジを満たすバージョンが無い(レンジも列挙される) | 対処衝突しているプラグインの片方をアンインストールまたは更新する。上流の作者にレンジを広げてもらう手もある |
... has version requirements too complex to intersect / has an invalid version requirement | 意味レンジの書式が不正、または複雑で積集合を取れない | 対処書式を直す。||の長い連結は単純にする |
... has no git tag satisfying <range> | 意味依存先のリポジトリにレンジ内の<name>--v*タグが無い | 対処上流がこの規則でタグ付けしているか調べる。レンジを緩める選択肢もある |
相対パスで参照されたプラグインは、レンジを満たすタグが無くてもエラーにならず、マーケットプレイスの現行コピーが入ります。そのコピーがレンジの外なら、依存元は無効のままで、claude plugin listにRequires "secrets-vault@your-marketplace" ~2.1.0, installed 3.0.0のように出ます。ローカルフォルダをマーケットプレイスとして追加した場合も、そのフォルダがgitリポジトリなら(v2.1.196以降)タグから解決されます。gitリポジトリでなければ、現在の内容がそのまま使われます。
claude plugin list --jsonでは、問題のあるプラグインにerrorsと、種別を持つerrorDetailsが付きます。表のRequiresの行はdependency-version-unsatisfiedで、未インストールや無効の依存はdependency-unsatisfiedです。
まとめ
依存される側はタグを打つところまでがリリース作業で、依存する側のレンジはそのタグの上に成り立ちます。~のパッチ範囲から始め、依存先を検証できた段階で^へ広げる進め方もあります。
Claude Codeのマーケットプレイス全体の仕組みはClaude Codeプラグイン完全ガイドにあります。