Claude Media
claude plugin list --jsonで導入済みプラグインを棚卸しする

claude plugin list --jsonで導入済みプラグインを棚卸しする

claude plugin list --jsonは導入済みプラグインを1件ずつのオブジェクトで返します。--available、--data-size、dataDirSize、keptDataの関係と、jqで棚卸しする手順をまとめます。

claude plugin list --json は、導入済みプラグインを1件1オブジェクトの配列で返します。--available で未導入の候補、--data-size で保存データの容量も同じ出力に載せられます。ただし後ろの2つは --json が無いと何も起きません。この記事では、フラグの組み合わせ方、返ってくるフィールド、jq で棚卸しする型、アンインストール後に残るデータの見分け方を扱います。

claude plugin listの出力は--jsonで別物になる

引数なしの claude plugin list は、人が読む一覧です。読み込み方ごとに Installed plugins: / Session-only plugins (--plugin-dir / --plugin-url): / Skills-directory plugins (.claude/skills/*): / Synced from claude.ai の見出しに分かれ、どれも空なら次の1行だけが出ます。

No plugins installed. Use `claude plugin install` to install a plugin.

--json を付けると、スクリプトで読むための配列になります。1つの導入(インストール)につき1オブジェクトです。同じプラグインを user と project の両方に入れていれば、2件に分かれて出ます。

フラグの関係は「--jsonが土台」

フラグ追加されるもの--json なし
--json追加されるもの配列(導入1件につき1オブジェクト)--json なし(これが土台)
--available追加されるもの未導入の候補。出力が installed / available の2キーを持つ1オブジェクトに変わる--json なし効果なし
--data-size [plugin]追加されるもの保存データの容量(dataDirSize)。v2.1.285以降--json なし効果なし

空の設定ディレクトリ(CLAUDE_CONFIG_DIR に空のフォルダーを指定)で、v2.1.296のまま確かめた結果が次です。

export CLAUDE_CONFIG_DIR=/tmp/empty-claude-config
claude plugin list --available
claude plugin list --json
claude plugin list --json --data-size foo@bar

1行目は --json が無いため、--available を付けても No plugins installed. の1行だけでした。2行目は空配列 [] です。3行目は導入記録の無い名前を渡したので、一覧ではなく次のエラーになりました。

✘ --data-size names a plugin that is not installed

--data-size に渡す名前は name@marketplace の形です。導入記録が無いとこのエラーで止まり、終了コードは1になります。名前を付けずに --data-size だけ指定すれば、導入済みの全プラグインを測ります。

導入済みオブジェクトのフィールドを読む

常に入っているのは id / version / scope / enabled / installPath の5つです。それ以外は該当するときだけ現れます。棚卸しで使う場面別に並べ直すと次のとおりです。

知りたいことフィールド補足
何がどこから入っているかフィールドid補足name@marketplace。セッション限りは name@inline、スキルディレクトリは name@skills-dir、claude.ai同期は name@synced
どのスコープかフィールドscope補足user / project / local / managed(導入分)。ほかに session / synced
今効いているかフィールドenabled補足マージ後の設定で有効かどうか
チームの共有設定で有効かフィールドprojectEnabled補足プロジェクトの .claude/settings.json が有効にしているか。マーケットプレイス導入のみ。v2.1.285以降
設定項目を持つかフィールドhasUserConfig補足userConfig を宣言し、読み込みに成功したとき true。保存済みの値は出力に含まれない。v2.1.285以降
壊れていないかフィールドerrors / notes補足読み込みエラーと、エラーではない警告
いつ入れたかフィールドinstalledAt / lastUpdated補足ISOタイムスタンプ。マーケットプレイス導入のみ
どのプロジェクトのものかフィールドprojectPath補足project と local のスコープのみ

errors と notes には、診断の種類と関係する名前をまとめた errorDetails / noteDetails が対で付きます。v2.1.268以降です。readFromFolder と folderVersion は、マーケットプレイスのフォルダーからその場で読み込まれるプラグイン向けで、v2.1.289以降に出ます。

version の意味は導入元で変わります。マーケットプレイス導入では導入時にClaude Codeが算出したバージョン文字列、セッション限り・スキルディレクトリ・同期のプラグインではマニフェストの version(無ければ unknown)です。

マーケットプレイスのフォルダーから直接読むプラグイン

ローカルのパスから追加したマーケットプレイスの相対パスのプラグインは、キャッシュへコピーされず、フォルダー内のソースからその場で読み込まれます。ソースを編集すると、次のセッション開始か /reload-plugins で反映され、バージョンを上げる必要はありません。

こうしたプラグインでは、installPath が実際の読み込み元を指しません。代わりに readFromFolder がフォルダー内のソースのディレクトリを示し、folderVersion がそこから読んだ version を示します。folderVersion は導入時に算出した version と食い違うことがあります。手元で開発中のプラグインを棚卸しから分けたいときは、この2つの有無が目印です。

claude plugin list --json \
  | jq -r '.[] | select(.readFromFolder) | [.id, .version, .folderVersion, .readFromFolder] | @tsv'

jqで棚卸しする

フィールド名どおりに絞り込むだけで、日常の点検は足ります。下は読み取り専用の例です。

# 無効化されているプラグイン
claude plugin list --json | jq -r '.[] | select(.enabled | not) | .id'
 
# 読み込みエラーを出しているプラグインとその内容
claude plugin list --json \
  | jq -r '.[] | select(.errors) | [.id, (.errors | join("; "))] | @tsv'
 
# 自分の環境では有効だが、プロジェクトの共有設定では有効になっていないもの
claude plugin list --json \
  | jq -r '.[] | select(.enabled and .projectEnabled == false) | .id'

3つ目は projectEnabled を使う型です。自分のユーザースコープで入れたプラグインに依存したままチームのリポジトリを動かしていないか、という点検になります。projectEnabled はマーケットプレイス導入にしか付かないので、== false と明示して「項目が無い」ものを拾わないようにしています。

--availableで未導入の候補を並べる

--json --available にすると、出力は配列ではなく1つのオブジェクトになります。キーは2つです。

  • installed: 上で見た導入済みオブジェクトの配列
  • available: 未導入のマーケットプレイス掲載プラグイン

available の各要素は pluginId / name / marketplaceName / source を持ち、description / version / installCount は該当するときだけ付きます。source は相対パスなら文字列、それ以外ならオブジェクトです。

空の設定ディレクトリでv2.1.296を動かしたところ、available は3,000件を超えました。返ってきた要素のキーは pluginId / name / marketplaceName / source / description / version で、installCount は含まれていませんでした。件数の多い出力なので、そのまま目で読まずに絞り込みます。

claude plugin list --json --available \
  | jq -r '.available[] | select(.name | test("review")) | .pluginId'

installed 側と available 側は id と pluginId で名前が違う点に注意が要ります。installed から取り出す処理をそのまま available に流用すると、キーが合わずに空振りします。

--data-sizeで容量を測り、keptDataで後始末を判断する

プラグインは、${CLAUDE_PLUGIN_DATA} として公開される永続ディレクトリ ~/.claude/plugins/data/<plugin-id>/ を持てます。更新しても残る場所で、${CLAUDE_PLUGIN_ROOT} のようにバージョンごとに変わるパスとは別です。キャッシュ、取り込み済みの依存、状態ファイルを置くプラグインでは、これが膨らみます。

--data-size を付けると、導入済みオブジェクトに次の2つのどちらかが加わります。いずれもマーケットプレイス導入のみで、v2.1.285以降です。

  • dataDirSize: bytes と human を持つオブジェクト。ディレクトリが無い・空のときは項目ごと出ない
  • dataDirUnreadable: ディレクトリはあるが測れなかったとき true
claude plugin list --json --data-size \
  | jq -r '.[] | select(.dataDirSize) | [.id, .dataDirSize.human] | @tsv'

1つだけ見たいなら --data-size formatter@my-marketplace のようにIDを渡します(formatter@my-marketplace は例です)。

測っているのは data/<plugin-id>/ の中身です。同じ ~/.claude/plugins/ の下には、バージョンごとにコピーされる cache/<marketplace>/<plugin>/<version>/ もあります。こちらは ${CLAUDE_PLUGIN_ROOT} が指す場所で、更新のたびに別のディレクトリができます。dataDirSize が小さいのにディスクが埋まっているときは、プラグインが自分で保存したデータとは別に、キャッシュ側のバージョンが積み重なっていないかも見る対象になります。

アンインストールでデータはどうなるか

最後のスコープからプラグインをアンインストールすると、保存済みのオプション・シークレットとデータディレクトリも消えます。残るのは次の3つのときです。

  1. claude plugin uninstall --keep-data を付けた
  2. 同じフォルダーを別のプラグインが使っている(IDが大文字小文字だけ違う場合など)
  3. 別スコープに残っているかもしれないのに、導入記録の読み戻しに失敗した

3つ目はアンインストール自体は成功し、データだけが残ります。--json の結果にはこのときだけ savedKept: "install_records_unreadable" が入ります。

uninstall --json の結果では、keptData がディレクトリが残ったかどうかを示します。--keep-data なしでディレクトリが残ったケースの報告はv2.1.281以降、savedKept はv2.1.282以降です。対話画面の /plugin でも、残ったプラグインには · data preserved と表示されます。経緯はv2.1.281とv2.1.282のリリースノートにもあります。

孤立データを探す手順

--data-size が測るのは導入済みプラグインのデータです。アンインストールで残ったディレクトリを探すときは、uninstall --json の結果を記録しておくのが確実です。

claude plugin uninstall formatter@my-marketplace --scope project --json \
  | tail -n 1 | jq '{outcome, keptData, savedKept}'

--json の結果はstdoutの最終行に1オブジェクトで出ます。マーケットプレイスが宣言したコマンドが先に出力されることがあるため、tail -n 1 で最終行だけを取ります。--prune とは併用できません。

失敗するアンインストールと確認プロンプト

導入記録の無いスコープを指定すると、Failed to uninstall plugin "formatter@my-marketplace": で始まる行が出て、終了コード1で止まります。もう一つ、棚卸しの後始末で踏みやすい失敗があります。

失敗行が "formatter" was not uninstalled: と続き、設定ファイルの名前が出る場合です。そのスコープの設定がまだプラグインを有効にしているかどうかをClaude Codeが確かめきれず、プラグインは保存した設定値とデータごと残ります。--json を付けていると、結果には failureCode: "settings_still_on" が入ります。この確認はv2.1.282以降です。表示された設定ファイルを開き、有効化の記述が残っていないかを見てから、もう一度実行する流れになります。

--prune で自動導入された依存まで片付ける場合、確認プロンプトが出ます。-y / --yes はこの確認を省くフラグで、標準入出力がTTYでない環境(CIやスクリプト)では --prune に必須です。--json とは併用できないので、スクリプトから --prune を使うときは結果をJSONで受け取れません。

スコープと状況ごとの早見表

どのスコープから外し、どのオプションを付けたかで、データの行き先が変わります。

状況データディレクトリ見分け方
最後のスコープから通常どおり外したデータディレクトリ設定値・シークレットごと消える見分け方keptData が立たない
他のスコープにも導入が残っているデータディレクトリ最後のスコープではないので消えない見分け方claude plugin list --json で id が残っている
--keep-data を付けたデータディレクトリ残る見分け方keptData、/plugin の · data preserved
別のプラグインが同じフォルダーを使っているデータディレクトリ残る見分け方keptData(--keep-data なしで残った報告はv2.1.281以降)
導入記録の読み戻しに失敗したデータディレクトリ設定値・シークレット・データのすべてが残る見分け方savedKept: "install_records_unreadable"(v2.1.282以降)
設定がまだ有効で確かめきれないデータディレクトリアンインストール自体が失敗し、すべて残る見分け方failureCode: "settings_still_on"(v2.1.282以降)

棚卸しで詰まりやすい点

  • --available や --data-size が効かない: --json を付け忘れています。エラーにもならず、人向けの一覧が出るだけです
  • jq が配列として読めない: --available を付けた出力はオブジェクトです。.[] ではなく .installed[] と .available[] で読みます
  • dataDirSize が出ない: ディレクトリが無い・空のときと、session や synced などマーケットプレイス導入でないプラグインのときは項目が出ません。測れなかった場合は dataDirUnreadable を見ます
  • アンインストールしたのにデータが残る: 成功の表示でも、--keep-data を付けていた、別のプラグインが同じフォルダーを使っていた、導入記録の読み戻しに失敗した、のいずれかが考えられます。--json の keptData と savedKept で見分けます
  • アンインストールが失敗する: 失敗行に設定ファイル名が出ていれば、そのスコープの設定がプラグインを有効にしたままです。v2.1.282より古いと、この確認自体が働きません
  • バージョンで項目が足りない: dataDirSize / projectEnabled / hasUserConfig はv2.1.285、readFromFolder はv2.1.289以降です。古い環境では項目自体が出ません

設定値を埋める手順はclaude plugin configureの記事に分けています。hasUserConfig が true のプラグインが、そちらの対象です。永続ディレクトリの置き場とパス変数の解決ルールはプラグインの環境変数とパスの解決ルールにあります。チームに配るプラグイン構成を決める側は、プラグインのバンドル配布と合わせて、配布後の確認にこの出力を使えます。Claude Code全体のプラグイン運用では、定期点検の入口になるコマンドです。

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