Claude Media
Claude Code plugin.jsonスキーマ完全リファレンス

Claude Code plugin.jsonスキーマ完全リファレンス

plugin.jsonは省略可能で、書く場合もnameだけが必須フィールドです。メタデータ・コンポーネントパス・userConfig・channelsまで、全フィールドの型と挙動を一覧にします。

.claude-plugin/plugin.jsonは省略できます。省略した場合、コンポーネントは既定のディレクトリ構成から自動検出され、プラグイン名はマーケットプレイスのエントリから決まります(--plugin-dirで読み込むときはディレクトリ名です)。書く場合でも必須フィールドはnameだけで、残りはすべて任意です。この「ほぼ全部が任意」という設計のせいで、実際にどのフィールドが何を制御するのかが公式ドキュメントの複数の節に分散しています。プラグインの基本構造や自作の最小手順はClaude Codeプラグイン完全ガイドにまとまっているので、本記事はマニフェストのフィールド1つずつの型と挙動をリファレンスとしてまとめます。

スキーマの全体像

フィールドをすべて使うと、plugin.jsonは次のような形になります。実際のプラグインでここまで埋めることはまれですが、どこに何を書けるかの見取り図として押さえておくと、以降の節で個々のフィールドを追うときに迷いません。

{
  "name": "plugin-name",
  "displayName": "Plugin Name",
  "version": "1.2.0",
  "description": "Brief plugin description",
  "author": { "name": "Author Name", "email": "author@example.com" },
  "homepage": "https://docs.example.com/plugin",
  "repository": "https://github.com/author/plugin",
  "license": "MIT",
  "keywords": ["keyword1", "keyword2"],
  "metadata": { "catalogId": "cat-123", "tier": "pro" },
  "skills": "./custom/skills/",
  "commands": ["./custom/commands/special.md"],
  "agents": ["./custom/agents/reviewer.md"],
  "hooks": "./config/hooks.json",
  "mcpServers": "./mcp-config.json",
  "outputStyles": "./styles/",
  "lspServers": "./.lsp.json",
  "experimental": {
    "themes": "./themes/",
    "monitors": "./monitors.json"
  },
  "dependencies": ["helper-lib", { "name": "secrets-vault", "version": "~2.1.0" }]
}

必須フィールドとトップレベルの挙動

nameはkebab-caseの一意な識別子で、スペース・制御文字・双方向テキスト制御文字のほか、@・:・パス区切りも含められません。UI上のコンポーネント名前空間に使われ、plugin-devという名前のプラグインのagent-creatorエージェントはplugin-dev:agent-creatorと表示されます。マーケットプレイスのエントリが別名でプラグインを一覧している場合、enabledPluginsのキーや/pluginが参照するのはマーケットプレイス側の名前です。

claude-・anthropic-・anthropics-・cc-plugin-で始まる名前や、claude・anthropic・anthropics・claude-modsそのものなど、Anthropic公式を思わせる名前はclaude plugin validateがエラーにします。officialをclaudeやanthropicの隣に置いた名前もエラーです。claudeやanthropicが単語として含まれる名前(mcp-for-claudeなど)は警告です。ただし検査するのはvalidate・plugin init・plugin tagだけで、Claude Codeはvalidateが拒否する名前でもインストールして読み込みます。

認識されないトップレベルフィールドは取り除かれ、プラグインは読み込まれます。claude plugin validateは未認識のフィールドを警告として報告し、終了コードは0のままです。次はv2.1.287で、version・description・authorを書いたマニフェストのhooksをhoksと書き間違えて検証した出力です。この3つを省くと、欠落の警告も加わって件数が増えます。

claude plugin validate ./demo-plugin
⚠ Found 1 warning:
 
  ❯ hoks: Unknown field 'hoks' — did you mean 'hooks'? Claude Code ignores unrecognized fields at load time, so this field has no effect.
 
✔ Validation passed with warnings

同じマニフェストに--strictを付けると、末尾が✘ Validation failed (--strict treats warnings as errors)に変わり、終了コードは1になります。--strictが失敗扱いにするのは未認識フィールドのほか、version・description・authorの欠落といったランタイムが許容する指摘です。

結果

validateの3つの結果

  • Validation passed

    マニフェストが読み込める状態です。終了コードは0です。

  • passed with warnings

    読み込めますが、直す点があります。終了コードは0で、--strictでは1になります。

  • Validation failed

    型の不一致、存在しないパス、userConfigなどの未知キーがあります。終了コードは1です。

どの指摘が警告で、どれがエラーかは、フィールドの場所で分かれます。v2.1.287での挙動です。

くらべる

警告で済むものと、エラーで止まるもの

トップレベル

警告(終了コード0)

未認識のトップレベルフィールドは取り除かれ、警告になります。metadataにオブジェクト以外を渡した場合は'metadata' must be a free-form object; got string. It will be ignored at load time.と出て、値は無視されます。

型・厳格なオブジェクト

エラー(終了コード1)

keywordsに文字列を渡すとexpected array, received stringで失敗します。userConfigのオプション内にsensitivと書き間違えるとUnrecognized key: "sensitiv"で失敗し、channelsのエントリ、lspServersの設定、monitorsのエントリでも同様に、未知キー1つでプラグインが読み込まれません。

メタデータフィールド一覧

フィールド型内容
name型string内容必須。kebab-caseの一意な識別子
$schema型string内容エディタ補完用のJSON Schema URL。読み込み時には無視される
displayName型string内容/pluginピッカーでの表示名。省略時はnameにフォールバック
version型string内容バージョン文字列。semverとしては検査されず、設定するとその値にピン留めされる
description型string内容プラグインの用途を短く説明
author型object内容name(必須) / email / urlを持つ作者情報
homepage型string内容ドキュメントURL。URLとして解釈できないと、プラグインが読み込まれない
repository型string内容ソースコードURL。検証はされない
license型string内容ライセンス識別子(MITなど)
keywords型array内容検索・発見用のタグ
metadata型object内容自由形式。Claude Codeはこの値を読まない(v2.1.222以降)
defaultEnabled型boolean内容既定の有効状態。既定値はtrue

icon・documentationUrl・supportUrl・privacyPolicyUrl・termsOfServiceUrlの5つは、Anthropicのディレクトリへ提出するときの掲載情報として読まれ、Claude Codeは読み込み時に無視します。v2.1.281以降のclaude plugin validateは警告なしで受け付けますが、それ以前はUnknown field警告が出るので--strictが失敗します。マーケットプレイスエントリに書いた場合は未知フィールドとして報告されます。

このほか、settings(有効なのはagentとsubagentStatusLineだけ)、types、experimental.evalsも使えます。userConfigのoptionsはv2.1.271以降のフィールドで、宣言したプラグインはそれ以前の版では読み込めません。

versionを省略すると、マーケットプレイスエントリ側のversion、それも無ければgithub/url/git-subdirや相対パスのgitホスト型ソースの場合はコミットSHAが使われます。バージョン解決の詳細なフォールバック順序はClaude Codeプラグインの依存バージョンを固定するで扱っています。両方にversionがあるときはplugin.json側が優先されます。

defaultEnabled: falseは、インストール直後は無効な状態で配布したいプラグインに使います。外部サービスへ接続するなど、ユーザーが明示的に選んでから使わせたいプラグインが典型例です。defaultEnabledは、enabledPluginsにまだ値が書かれていないときの既定です。一度書き込まれた値は更新をまたいで残るので、後のリリースでdefaultEnabledを変えても既存ユーザーの設定は変わりません。有効なプラグインから依存されているプラグインは、この値にかかわらず有効な状態で始まります。マーケットプレイスのエントリ側にも同名のdefaultEnabledを置けますが、その場合はplugin.json側の値よりマーケットプレイス側が優先されます。

コンポーネントパスフィールド

フィールド型既定の扱い
skills型string|array既定の扱い既定のskills/スキャンに追加される
commands型string|array既定の扱い既定のcommands/を置き換える
agents型string|array既定の扱い既定のagents/を置き換える
workflows型string|array既定の扱い既定のworkflows/を置き換える
outputStyles型string|array既定の扱い既定のoutput-styles/を置き換える
hooks型string|array|object既定の扱い独自の合流ルールで既定と合算
mcpServers型string|array|object既定の扱い独自の合流ルールで既定と合算
lspServers型string|array|object既定の扱い独自の合流ルールで既定と合算
experimental.themes型string|array既定の扱い既定のthemes/を置き換える
experimental.monitors型string|array既定の扱い既定のmonitors.jsonを置き換える
userConfig型object既定の扱い有効化時にユーザーへ入力を求める値の定義
channels型array既定の扱いメッセージ注入チャンネルの宣言
dependencies型array既定の扱い他プラグインへの依存(バージョン制約つき)

「置き換える」に分類されるフィールドは、指定した瞬間に既定ディレクトリのスキャンが止まります。既定を残したまま追加したい場合は、既定パス自身を配列に含めます。"commands": ["./commands/", "./extras/"]のように書けば、既定のcommands/を保ったままextras/も読み込みます。skillsだけは例外で、既定のskills/は常にスキャンされたうえで、指定したディレクトリが追加で読み込まれます。マーケットプレイスエントリのsourceがマーケットプレイスのルートで、そのエントリがskillsのサブディレクトリを列挙している場合は、列挙したものだけが読み込まれ、既定のskills/はスキャンされません。

パスフィールドは共通して、プラグインルートからの相対パスで./から始める必要があります。skillsだけ"."も使え、v2.1.221より前では"."がマニフェスト検証に失敗するため"./"と書きます。プラグインルートの外に出るパス(..を含むものなど)や存在しないパスは、読み込まれずエラーになります。

{
  "commands": [
    "./specialized/deploy.md",
    "./utilities/batch-process.md"
  ],
  "agents": [
    "./custom-agents/reviewer.md",
    "./custom-agents/tester.md"
  ]
}

この例のように、commandsやagentsへ個別ファイルを列挙すれば、標準のcommands/・agents/ディレクトリを使わない独自の配置に変更できます。

userConfigとchannelsの要点

userConfigは、プラグイン有効化時にユーザーへ入力を求める値を宣言します。各キーはtype(string / number / boolean / directory / file)、title、descriptionが必須で、sensitive・required・default・multiple・min/maxが任意です。値は${user_config.KEY}として、MCPサーバー設定・LSPサーバー設定・exec形式のhookのargsに埋め込めます。SkillやAgentの本文には、非機密の値に限って埋め込めます。

ただしシェルで実行されるフィールド(シェル形式のhookコマンド・Monitorのコマンド・MCPのheadersHelper)は${user_config.*}の埋め込みを拒否します。設定値をそのままシェルへ渡すと任意のコマンド実行を許すことになるためで、シェル形式のhookなら、代わりにCLAUDE_PLUGIN_OPTION_<KEY>環境変数として読むか、exec形式にしてargsから渡します。MonitorのコマンドとheadersHelperにはこの環境変数も渡らないため、スクリプト自身が値を取得します。

{
  "userConfig": {
    "api_endpoint": {
      "type": "string",
      "title": "API endpoint",
      "description": "チームのAPIエンドポイント"
    },
    "api_token": {
      "type": "string",
      "title": "API token",
      "description": "API認証トークン",
      "sensitive": true
    }
  }
}

非機密の値はユーザーのsettings.jsonのpluginConfigsに保存されます。機密値はmacOSではKeychainに入り、書き込みを拒否されたときは~/.claude/.credentials.jsonにフォールバックします。Keychainのないプラットフォームでは最初から.credentials.jsonです。

pluginConfigsが置かれるのはユーザー設定かmanaged settingsです。有効化時のダイアログがユーザー設定へ書き込むので、手で編集する必要は通常ありません。詳しい設定例はClaude Code plugin userConfigの書き方で扱っています。

channelsは、Telegram・Slack・Discordのようにメッセージを会話へ注入するチャンネルをプラグインが宣言するためのフィールドです。各エントリのserverは、そのプラグインのmcpServersに定義されたキーと一致している必要があります。チャンネルごとにuserConfigと同じスキーマの入力を追加で求めることもできます。実装の具体例はClaude Code Channelsプラグイン化にまとめています。

環境変数の要点

変数解決先
${CLAUDE_PLUGIN_ROOT}解決先プラグインのインストール先ディレクトリの絶対パス
${CLAUDE_PLUGIN_DATA}解決先更新をまたいで残る永続ディレクトリ。初回参照時に作成される
${CLAUDE_PROJECT_DIR}解決先プロジェクトルート

hookとLSPサーバーには3つとも、MCPのstdioサーバーにはCLAUDE_PLUGIN_ROOTとCLAUDE_PLUGIN_DATAの2つが環境変数として渡されます。文字列内へのプレースホルダー埋め込みが効くフィールドと効かないフィールドがあり、その対応関係とパス解決の優先順位はClaude Codeプラグインの環境変数とパスの解決ルールにまとめています。

パスの誤りはどこに表示されるか

コンポーネントのパスは、プラグインルートの内側にあり、実在している必要があります。外へ出るパスは読み込まれず、/pluginのErrorsタブに<component> path escapes plugin directory: <path>と出ます。存在しないパスは<component> path not found: <path>です。claude plugin validateは同じ2つをPath contains ".." which could be a path traversal attemptとPath not foundのエラーにします。

outputStyles・lspServers・monitors・themesのパス検査はv2.1.283以降のvalidateが対象です。それ以前の版では、この4つのパスの誤りはインストール後のErrorsタブで初めて見えます。

置き換え型のキーを書いた場合は、エラーにはならない別の表示が出ます。commands/のような既定フォルダがあるのにcommandsキーも書くと、マニフェストのパスだけが読み込まれ、claude plugin listと/pluginにDefault <folder>/ folder is ignored because the manifest sets "<key>"という警告が出ます。

よくある質問

plugin.json自体が無いプラグインは動きますか

動きます。Claude Codeは既定ディレクトリを自動でスキャンし、プラグイン名はマーケットプレイスのエントリから決まります(--plugin-dirで読み込む場合はディレクトリ名)。名前空間の衝突を避けたい、displayNameやauthorのようなメタデータを添えたい、既定と異なる場所にコンポーネントを置きたい、といった理由が出てきて初めてplugin.jsonが必要になります。

claude --json-schemaと$schemaは、plugin.jsonのスキーマとどう違いますか

別物です。claude -p --json-schema '{...}'は、非対話(print)モードの出力を指定したJSON Schemaに合わせるCLIフラグで、プラグインとは関係がありません。plugin.jsonの$schemaは、エディタの補完に使うスキーマURLを書く欄です。Claude Codeは読み込み時にこの値を無視するため、書かなくてもプラグインの動作は変わりません。

まとめ

CIに置く検査はclaude plugin validate --strictが一本あれば足ります。トップレベルのタイポまで終了コード1にでき、パスの誤りは素のvalidateでもエラーになります。依存関係のバージョン制約はClaude Codeプラグイン依存関係にあります。.mcp.json側の検査はclaude plugin validateのMCP検査で扱っています。

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