Claude Codeプラグインの依存バージョンを固定する
プラグインが他プラグインに依存するとき、semverレンジで対象バージョンを固定できます。書き方から複数制約の衝突解決、タグ付けとエラー対処までを扱います。
Claude Codeプラグインの依存バージョンを固定する
プラグインはplugin.jsonやマーケットプレイスのエントリで他プラグインへの依存を宣言でき、既定では依存先の最新バージョンを常に追いかけます。ここにsemverレンジで範囲を指定すると、依存先が動いても自分のプラグインは検証済みの範囲内に留められます。書き方と、複数の制約が衝突したときの解決順序、タグ付けの運用までをまとめます。
なぜバージョンを固定する必要があるのか
社内マーケットプレイスで2つのチームがプラグインを公開している場面を考えます。プラットフォームチームはシークレット管理をラップするMCPサーバーsecrets-vaultを、デプロイチームはデプロイ時にsecrets-vaultから認証情報を取得するdeploy-kitを維持しています。deploy-kitはsecrets-vaultのv2.1.0に対して動作確認済みです。
バージョン指定がない状態だと、プラットフォームチームがMCPツール名を変更するリリースをタグ付けした瞬間、自動更新で全エンジニアのsecrets-vaultが新バージョンへ移り、deploy-kitは動かなくなります。バージョン制約を付けておけば、deploy-kitを入れているエンジニアは2.1.x系列の最新パッチに留まり、デプロイチームは自分たちのタイミングで制約を緩めた新バージョンを公開できます。
依存の書き方とsemverレンジ
依存は.claude-plugin/plugin.jsonのdependencies配列に列挙します。バージョン指定のない依存は文字列だけで書け、細かく制御したい依存はオブジェクトで書きます。
{
"name": "deploy-kit",
"version": "3.1.0",
"dependencies": [
"audit-logger",
{ "name": "secrets-vault", "version": "~2.1.0" }
]
}オブジェクト形式で使えるフィールドは3つです。
| フィールド | 説明 |
|---|---|
name | 説明依存先のプラグイン名。宣言元と同じマーケットプレイス内で解決される(必須) |
version | 説明~2.1.0 ^2.0 >=1.4 =2.1.0のようなsemverレンジ。条件を満たす最も高いタグ付きバージョンが取得される |
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のみ) |
チームで新機能を積極的に取り込みたい依存には^、破壊的変更が怖い依存には~や=を選ぶのが典型的な使い分けです。とはいえ=で固定したままにすると、依存先が重大な修正をリリースしても自動更新の対象から外れ続けます。固定した理由をREADMEなど別のドキュメントに書き残し、定期的に見直す運用を組み合わせるのも一案です(descriptionはプラグイン自体の説明用フィールドなので、運用メモの置き場としては本来の用途ではありません)。
2.0.0-beta.1のようなプレリリース版は、レンジ側で^2.0.0-0のようにプレリリースを許容する形にしない限り対象外です。プラグインをインストールすると、宣言済みの依存はClaude Codeが自動で解決・導入します。ただし依存先のマーケットプレイスエントリがcommandソースやheadersHelperを使っている場合だけは例外で、そちらはユーザー自身が先に単体でインストールする必要があります。
複数の制約がぶつかったときの解決順序
同じ依存先を複数のプラグインが制約している場合、Claude Codeはそれぞれのレンジの積集合を取り、すべてを満たす最も高いバージョンに解決します。組み合わせのパターンは次の3通りです。
| プラグインAの要求 | プラグインBの要求 | 結果 |
|---|---|---|
^2.0 | プラグインBの要求>=2.1 | 結果2.1.0以上2.x系の最高タグに1本化。両プラグインとも読み込まれる |
~2.1 | プラグインBの要求~3.0 | 結果プラグインBのインストールがrange-conflictで失敗。プラグインAと依存先は元のまま |
=2.1.0 | プラグインBの要求指定なし | 結果依存先は2.1.0に固定。プラグインAが入っている間、自動更新は新しいバージョンをスキップする |
自動更新は、依存先を「マーケットプレイスの最新版」ではなく「インストール済み全プラグインの制約をすべて満たす最も高いgitタグ」で更新します。すべてのレンジを満たすタグが無くなると、自動更新はその依存の更新を見送り、/pluginのErrorsタブに制約元のプラグイン名とともにスキップの旨が表示されます。ある依存を制約している最後のプラグインをアンインストールすると、その依存はマーケットプレイスの最新版を追いかける状態に戻ります。
タグ付けとバージョン解決の対応
バージョン制約はgitタグを基準に解決されます。対象はgithub/url/git-subdirソースなら依存先自身のリポジトリ、相対パスで参照されている場合はマーケットプレイスのリポジトリです。タグが無いと、制約付きの依存は解決できません。
タグの命名は{plugin-name}--v{version}という規則で、{version}はそのコミット時点のplugin.jsonのversionフィールドと一致させます。プラグインのディレクトリから次を実行すると、この規則に沿ったタグを自動で作成できます。
claude plugin tag --pushclaude plugin tagは実行前にプラグインの内容を検証します。plugin.jsonとマーケットプレイスエントリのバージョンが一致しているかを確認し、プラグインディレクトリ配下の作業ツリーがクリーンであることを求めます。そのうえで、同名タグが既にあれば拒否します。--pushを付けるとoriginリモートへ実際にpushし、省略すると実行すべきgit pushコマンドを表示するだけに留まります。origin以外のリモートへpushしたい場合は--remoteでリモート名を指定できます。pushに失敗した場合でも、タグ自体はローカルには作成された状態で残ります。--dry-runはタグ付けの内容を確認するだけで何も作成しません。
1つのマーケットプレイスリポジトリで複数のプラグインを管理していても、プラグイン名のプレフィックスによってバージョン系列は独立します。npm・archive・commandソースの依存には、この仕組みが適用されません。制約のチェック自体はロード時に行われますが、対象バージョンの取得はタグに依存しないためです。
タグ付けで解決されたバージョンは、plugin.jsonのversionとは別に記録されます。制約のチェックは実際に取得したタグのバージョンに対して行われるため、plugin.json側の値を更新し忘れていても、タグが新しければ新しいバージョンとして制約と照合されます。また、既存のタグをforce-moveして別のコミットを指すよう付け替えると、次回そのプラグインをインストールしたときのキャッシュディレクトリは新しく作られます(末尾に12文字のコミットSHAが付くディレクトリ名のため、指す先が変わればディレクトリ自体が変わります)。
ローカル開発時とバージョンチェックの扱い
依存先のプラグインを--plugin-dirで同時にローカル開発している場合は、次のように両方を読み込みます。
claude --plugin-dir ./my-dependency --plugin-dir ./my-pluginローカルコピーは、依存エントリがマーケットプレイス名を指定していても依存を満たしたことになり、バージョン制約自体はチェックされません。そのためローカルのplugin.jsonにversionを書く必要はありません。v2.1.242より前では、マーケットプレイス名を指定した依存エントリはローカルコピーと一致せず、プラグインが無効化される挙動でした。
マーケットプレイスからその依存をインストールしていない状態でローカルコピーを消すと、次回以降プラグインが読み込まれなくなります。ローカルコピーを無効化した場合と、--plugin-dirを付けずにセッションを開始した場合とでエラーメッセージが変わるため、/pluginやコマンドラインの表示をよく確認してください。
自分のバージョンと依存の制約は別物
plugin.jsonにはversionというキーが2つの違う役割で登場するため、混同しやすいポイントがあります。トップレベルのversionはそのプラグイン自身のバージョンで、Claude Codeが更新の有無を判定するキャッシュキーです。一方、dependencies配列の中に書くversionは依存先に対する制約で、意味がまったく異なります。同じ単語でも、どの階層に書くかで役割が入れ替わる点は覚えておく価値があります。
自身のバージョンは、次の優先順で解決されます。①plugin.jsonにversionが明示されていればそのフィールドがそのまま使われます。②未指定でも、マーケットプレイスのエントリ側にversionが書かれていればそちらが採用されます。③どちらにも無い場合、github/url/git-subdirソースならgitのコミットSHAが使われます(相対パスで参照されている、git管理下のマーケットプレイスのソースも対象です)。④archiveソースではファイルのSHA-256ダイジェストの先頭12文字が使われます。⑤npmソースやgit管理外のローカルディレクトリではunknownが採用されます。依存の制約として書く~2.1.0のようなレンジは、この自身のバージョンが解決された後に「その値がレンジを満たすか」を照合する仕組みなので、依存先がunknownのまま運用されていると制約自体が機能しません。
npm・archive・commandソースの依存には、タグベースのバージョン解決は適用されません。archiveソースはマーケットプレイスエントリのsha256ピンで追跡され、commandソースはplugin.jsonのバージョン文字列をそのまま見てコンテンツハッシュの接尾辞を無視します。commandソースの依存先がplugin.jsonにバージョンを書いていない場合、その依存はどんな制約も満たさない扱いになるため、制約を付けたいなら先にバージョンを明示しておく必要があります。
エラーが出たときの対処
依存関係のエラーはclaude plugin listや/pluginに説明的なメッセージとして表示されます。代表的なものは次の4つです。
| エラー | 意味 | 対処 |
|---|---|---|
dependency-unsatisfied | 意味宣言済みの依存が未インストール、または無効化されている | 対処エラーメッセージに表示されるclaude plugin installを実行する。マーケットプレイス未設定ならclaude plugin marketplace addで追加する |
range-conflict | 意味複数の制約を組み合わせられない | 対処競合しているプラグインの片方をアンインストールまたは更新する。versionの書式ミスや||の複雑すぎるチェーンも見直す |
dependency-version-unsatisfied | 意味インストール済みの依存先バージョンが制約範囲外 | 対処claude plugin install <依存先>@<マーケットプレイス>で現在の制約に合わせて再解決する |
no-matching-tag | 意味依存先のリポジトリに条件を満たす{name}--v*タグが無い | 対処依存先がタグ付け規則に従っているか確認する。レンジを緩める選択肢もある |
claude plugin list --jsonを使うと、問題のあるプラグインのerrorsフィールドを機械的に検出できます。読み込みに成功したプラグインにはこのフィールド自体が付きません。
よくある質問
バージョン指定を省略した依存はどう扱われますか
文字列だけの依存宣言("audit-logger"など)は、その時点でマーケットプレイスが提供している最新バージョンを常に追いかけます。テスト済みの範囲に留めたい依存にだけ、オブジェクト形式でレンジを付ける使い分けが基本です。
プレリリース版を依存の対象にできますか
既定では対象外です。2.0.0-beta.1のようなバージョンを含めたい場合は、レンジ側を^2.0.0-0のようにプレリリースを許容する書き方にする必要があります。
/reload-pluginsは依存の再解決にも影響しますか
します。/reload-pluginsのほか、依存元プラグインのマーケットプレイス自動更新、依存元へのclaude plugin installの再実行、claude plugin marketplace addのいずれも、未解決の依存を同じルールで解決し直すタイミングになります。
タグを付け忘れるとどうなりますか
依存先のリポジトリに{name}--v*形式のタグが1つも無いと、バージョン制約付きの依存は解決できずno-matching-tagエラーになります。相対パスで参照しているプラグインに限っては、一致するタグが無い場合マーケットプレイスの現在のコピーがそのままインストールされ、制約はロード時にチェックされます。ローカルフォルダをマーケットプレイスとして追加している場合も、そのフォルダがgitリポジトリであればタグから解決されますが、v2.1.196より前のバージョンやgit管理外のフォルダでは、この解決方法自体が使えず現在のコピーがそのまま使われます。
まとめ
依存バージョンの固定は、plugin.jsonのdependencies配列にsemverレンジを書くだけで始められますが、実際に効かせるにはgitタグの命名規則を守ることと、複数プラグインの制約が衝突したときの解決順序を理解しておくことが欠かせません。--plugin-dirによるローカル開発では制約チェック自体が働かない点も、実運用でつまずきやすいポイントです。マーケットプレイス全体の仕組みはClaude Codeプラグイン完全ガイド、更新を反映するタイミングの制御は/reload-pluginsの使い方、ハッシュベースでバージョンを追跡する配布形態についてはarchive integrity checkエラーの対処も参考になります。