{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://cognitive-delivery.github.io/contract/1.x/plugin-marketplace.schema.json",
  "title": "CDF Plugin Marketplace",
  "description": "A marketplace's `marketplace.json`, read from `.claude-plugin/marketplace.json`. Models every key the Claude Code plugin manifest and marketplace references, read 2026-10-05 document: owner, metadata, renames, forceRemoveDeletedPlugins, allowCrossMarketplaceDependenciesOn and the `plugins[]` entries with Claude Code's seven `source` forms, plus two CDF extensions the README names: a `local` source form for a marketplace that lists plugins already on disk, and an optional per-entry `cdf` block carrying a declared digest and the capabilities the entry expects. Every source form is DECLARED here, including the three the harness cannot yet fetch, because a marketplace that uses one must parse and be reported rather than fail to load. A listing is not an installation, and a declared digest is a claim to be checked, never a verdict.",
  "definitions": {
    "author": {
      "description": "Who publishes the plugin. An object is the documented form; a bare string is accepted because marketplaces in the wild carry one, and a reader that refused it would refuse a real plugin.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "object",
          "required": [
            "name"
          ],
          "properties": {
            "name": {
              "type": "string",
              "minLength": 1,
              "$comment": "stability: stable"
            },
            "email": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "url": {
              "type": "string",
              "$comment": "stability: stable"
            }
          },
          "additionalProperties": true
        }
      ]
    },
    "capabilities": {
      "type": "object",
      "description": "What the plugin's own code asks to be allowed when the harness runs it out of process. This is the lease manifest's `allow` shape, property for property, because a plugin worker's lease is generated from it and narrowed against the workspace root policy. It is deliberately NOT the store-listing `interface.capabilities` vocabulary a plugin may also carry: that is a shelf label, this is an authorisation request. Every list is optional here — an absent list is a plugin that asks for nothing, which is the correct default — whereas the granted manifest requires all five.",
      "properties": {
        "tools": {
          "type": "array",
          "description": "Governed tool names the agent may call.",
          "items": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[A-Za-z0-9_][A-Za-z0-9_.:/-]{0,127}$",
            "description": "A governed tool name the plugin asks to call. At most 128 characters of letters, digits, `_`, `.`, `:`, `/` and `-`, so a governed `cdf_` name and a `<server>/<tool>` pair both fit. `*` is refused: a lease that names every tool has not named one, and SPEC §5.2 R2 exists because a grant must say what it opens. Whitespace is refused."
          },
          "$comment": "stability: stable"
        },
        "read_paths": {
          "type": "array",
          "description": "Workspace-relative POSIX globs the agent may read. Refused here, without lookahead so any RE2 or I-Regexp validator can load the rule: a leading `/`, any `..` segment, a leading `~`, a drive-letter prefix and any backslash. The registry re-checks the resolved path against the workspace root.",
          "items": {
            "type": "string",
            "minLength": 1,
            "allOf": [
              {
                "not": {
                  "pattern": "^/"
                }
              },
              {
                "not": {
                  "pattern": "(^|/)\\.\\.(/|$)"
                }
              },
              {
                "not": {
                  "pattern": "^~"
                }
              },
              {
                "not": {
                  "pattern": "^[A-Za-z]:"
                }
              },
              {
                "not": {
                  "pattern": "\\\\"
                }
              }
            ]
          },
          "$comment": "stability: stable"
        },
        "write_paths": {
          "type": "array",
          "description": "Workspace-relative POSIX globs the agent may change. Refused here, without lookahead: a leading `/`, any `..` segment, a leading `~`, a drive-letter prefix and any backslash. The registry re-checks the resolved path against the workspace root, and a change outside the granted set is a scope violation that revokes the lease.",
          "items": {
            "type": "string",
            "minLength": 1,
            "allOf": [
              {
                "not": {
                  "pattern": "^/"
                }
              },
              {
                "not": {
                  "pattern": "(^|/)\\.\\.(/|$)"
                }
              },
              {
                "not": {
                  "pattern": "^~"
                }
              },
              {
                "not": {
                  "pattern": "^[A-Za-z]:"
                }
              },
              {
                "not": {
                  "pattern": "\\\\"
                }
              }
            ]
          },
          "$comment": "stability: stable"
        },
        "hosts": {
          "type": "array",
          "description": "Hostnames the agent may reach, with an optional leading wildcard label (`*.example.com`). Enforced by the egress proxy once it keys off the lease.",
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 253,
            "pattern": "^(\\*|(\\*\\.)?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*)$",
            "description": "A host the plugin asks to reach. A lower-case DNS name of one or more labels, an IPv4 literal or `localhost` (both are DNS-name shaped), with an optional single leading `*.` label, or the bare `*`. Refused by the pattern, which is RFC 9485 I-Regexp with no lookahead: a scheme, a port, a path, whitespace, upper case, a trailing dot and a wildcard anywhere but the first label. A port is not a host: the egress proxy matches hostnames, and a rule nothing enforces is a claim. IP literals are admitted because a local model provider (Ollama, LM Studio) lives at 127.0.0.1 and the root policy derives its hosts from provider URLs."
          },
          "$comment": "stability: stable"
        },
        "commands": {
          "type": "array",
          "description": "Executable names the agent may run.",
          "items": {
            "type": "string",
            "minLength": 1,
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$",
            "description": "An executable the plugin asks to run. The basename of the executable, at most 128 characters: letters, digits, `.`, `_`, `+`, `-`. No path separator (identity is the resolved executable's basename, not where it was found), no whitespace (an argument is not part of the name) and no shell operator."
          },
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "componentPath": {
      "description": "A component directory or file, or a list of them. Claude Code accepts a single string or an array of strings for `skills`, `commands`, `agents`, `outputStyles`, `workflows` and `experimental.themes`, and scans the default folder when the key is absent, so an absent key is not an empty contribution. Every path starts with `./` (`skills` also accepts `\".\"`). Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          }
        }
      ]
    },
    "entry": {
      "type": "object",
      "description": "One plugin listed by the marketplace. `name` and `source` are required: a listing that names nothing cannot be addressed, and one that resolves to nothing cannot be fetched. Every other key overrides or supplements what the fetched manifest says.",
      "required": [
        "name",
        "source"
      ],
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$",
          "$comment": "stability: stable"
        },
        "source": {
          "$ref": "#/definitions/source",
          "$comment": "stability: stable"
        },
        "displayName": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "description": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "version": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "author": {
          "$ref": "#/definitions/author",
          "$comment": "stability: stable"
        },
        "homepage": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "repository": {
          "$ref": "#/definitions/repository",
          "$comment": "stability: stable"
        },
        "license": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "keywords": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "$comment": "stability: stable"
        },
        "category": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "$comment": "stability: stable"
        },
        "defaultEnabled": {
          "type": "boolean",
          "$comment": "stability: stable"
        },
        "strict": {
          "type": "boolean",
          "description": "Whether the entry must match the fetched manifest exactly. Absent means true: the stricter reading is the default, so a marketplace relaxes it deliberately.",
          "$comment": "stability: stable"
        },
        "skills": {
          "$ref": "#/definitions/componentPath",
          "$comment": "stability: stable"
        },
        "commands": {
          "$ref": "#/definitions/commands",
          "$comment": "stability: stable"
        },
        "agents": {
          "$ref": "#/definitions/componentPath",
          "$comment": "stability: stable"
        },
        "hooks": {
          "$ref": "#/definitions/hooksSource",
          "$comment": "stability: stable"
        },
        "mcpServers": {
          "$ref": "#/definitions/mcpServersSource",
          "$comment": "stability: stable"
        },
        "lspServers": {
          "$ref": "#/definitions/lspServers",
          "$comment": "stability: stable"
        },
        "headers": {
          "type": "object",
          "description": "Request headers for an archive or url source. Never credentials: a value that needs a secret belongs in `headersHelper`, which the host runs and whose output the marketplace file never sees.",
          "additionalProperties": {
            "$ref": "#/definitions/credentialFree"
          },
          "propertyNames": {
            "not": {
              "pattern": "^[Aa][Uu][Tt][Hh][Oo][Rr][Ii][Zz][Aa][Tt][Ii][Oo][Nn]$"
            },
            "description": "An `authorization` header, in any case, is refused: its value would be a credential in a file everyone reads. `headersHelper` is the route."
          },
          "$comment": "stability: stable"
        },
        "headersHelper": {
          "type": "string",
          "minLength": 1,
          "description": "A path or command that produces this entry's archive-download headers at fetch time. Claude Code requires the entry to set `\"strict\": false`, and the schema enforces that with if/then. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
          "$comment": "stability: stable"
        },
        "relevance": {
          "$ref": "#/definitions/relevance",
          "$comment": "stability: stable"
        },
        "dependencies": {
          "$ref": "#/definitions/dependencies",
          "$comment": "stability: stable"
        },
        "metadata": {
          "type": "object",
          "description": "Free-form publisher metadata on the entry. Carried, never interpreted.",
          "$comment": "stability: stable"
        },
        "settings": {
          "type": "object",
          "additionalProperties": true,
          "$comment": "stability: stable"
        },
        "userConfig": {
          "$ref": "#/definitions/userConfig",
          "$comment": "stability: stable"
        },
        "channels": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/channel"
          },
          "$comment": "stability: stable"
        },
        "outputStyles": {
          "$ref": "#/definitions/componentPath",
          "$comment": "stability: stable"
        },
        "workflows": {
          "$ref": "#/definitions/componentPath",
          "$comment": "stability: stable"
        },
        "themes": {
          "$ref": "#/definitions/componentPath",
          "$comment": "stability: stable"
        },
        "experimental": {
          "$ref": "#/definitions/experimental",
          "$comment": "stability: stable"
        },
        "types": {
          "type": "string",
          "minLength": 1,
          "allOf": [
            {
              "not": {
                "pattern": "^/"
              }
            },
            {
              "not": {
                "pattern": "(^|/)\\.\\.(/|$)"
              }
            },
            {
              "not": {
                "pattern": "^~"
              }
            },
            {
              "not": {
                "pattern": "^[A-Za-z]:"
              }
            },
            {
              "not": {
                "pattern": "\\\\"
              }
            }
          ],
          "$comment": "stability: stable"
        },
        "cdf": {
          "$ref": "#/definitions/entryCdf",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true,
      "if": {
        "required": [
          "headersHelper"
        ]
      },
      "then": {
        "required": [
          "strict"
        ],
        "properties": {
          "strict": {
            "const": false,
            "$comment": "stability: stable"
          }
        }
      }
    },
    "entryCdf": {
      "type": "object",
      "description": "The additive CDF block for one entry. Absent in a plain Claude Code marketplace.",
      "properties": {
        "digest": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$",
          "description": "The sha256 the fetched tree must hash to, lower-case hex. A claim the loader checks; a mismatch is a refusal with both digests named, never a warning.",
          "$comment": "stability: stable"
        },
        "capabilities": {
          "$ref": "#/definitions/capabilities",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "metadata": {
      "type": "object",
      "description": "Marketplace-wide defaults.",
      "properties": {
        "pluginRoot": {
          "type": "string",
          "description": "The directory relative paths in `source` resolve from.",
          "$comment": "stability: stable"
        },
        "description": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "version": {
          "type": "string",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "owner": {
      "type": "object",
      "description": "Who publishes the marketplace. Required: a marketplace with no owner is an anonymous list of things to execute.",
      "required": [
        "name"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "email": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "url": {
          "type": "string",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "repository": {
      "description": "The source repository, as a URL string or as an object carrying one.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "object"
        }
      ]
    },
    "source": {
      "description": "Where a listed plugin comes from: a relative path inside the marketplace, or one of the seven object forms. The harness fetches `local`, `github`, `url` and `git-subdir` in v1; `npm`, `archive` and `command` parse and are reported as an unsupported source form, because a reader that threw on them would refuse a whole marketplace over one entry it could not fetch.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "$ref": "#/definitions/sourceLocal"
        },
        {
          "$ref": "#/definitions/sourceGithub"
        },
        {
          "$ref": "#/definitions/sourceUrl"
        },
        {
          "$ref": "#/definitions/sourceGitSubdir"
        },
        {
          "$ref": "#/definitions/sourceNpm"
        },
        {
          "$ref": "#/definitions/sourceArchive"
        },
        {
          "$ref": "#/definitions/sourceCommand"
        }
      ]
    },
    "sourceArchive": {
      "type": "object",
      "description": "A downloadable archive. Declared, not fetched in v1: no archive reader exists, and hand-rolling one is where path traversal, absolute entries, symlinks and zip-slip get written wrong.",
      "required": [
        "source",
        "url"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "archive"
          ],
          "$comment": "stability: stable"
        },
        "url": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "sha256": {
          "type": "string",
          "pattern": "^[0-9a-fA-F]{64}$",
          "description": "The archive digest as 64 hex characters, upper or lower case as Claude Code accepts. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "sourceCommand": {
      "type": "object",
      "description": "A command the host runs to produce the plugin. Declared, not fetched in v1: the harness does not run a marketplace-supplied command to obtain code it is about to run.",
      "required": [
        "source",
        "command"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "command"
          ],
          "$comment": "stability: stable"
        },
        "command": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "timeout": {
          "type": "integer",
          "minimum": 1,
          "maximum": 600,
          "description": "Seconds, 1 to 600; Claude Code defaults to 60. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
          "$comment": "stability: stable"
        },
        "mode": {
          "type": "string",
          "enum": [
            "copy",
            "link"
          ],
          "description": "`copy` (default) copies the printed directory; `link` loads it in place. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "sourceGitSubdir": {
      "type": "object",
      "description": "One directory of a git repository. `path` is repository-relative and may not escape it.",
      "required": [
        "source",
        "url",
        "path"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "git-subdir"
          ],
          "$comment": "stability: stable"
        },
        "url": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "path": {
          "type": "string",
          "minLength": 1,
          "allOf": [
            {
              "not": {
                "pattern": "^/"
              }
            },
            {
              "not": {
                "pattern": "(^|/)\\.\\.(/|$)"
              }
            },
            {
              "not": {
                "pattern": "^~"
              }
            },
            {
              "not": {
                "pattern": "^[A-Za-z]:"
              }
            },
            {
              "not": {
                "pattern": "\\\\"
              }
            }
          ],
          "$comment": "stability: stable"
        },
        "ref": {
          "type": "string",
          "minLength": 1,
          "description": "A branch, tag or other revision. A branch is not a pin.",
          "$comment": "stability: stable"
        },
        "sha": {
          "type": "string",
          "pattern": "^[0-9a-f]{7,40}$",
          "description": "A commit sha. The only ref that cannot move.",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "sourceGithub": {
      "type": "object",
      "description": "A GitHub repository.",
      "required": [
        "source",
        "repo"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "github"
          ],
          "$comment": "stability: stable"
        },
        "repo": {
          "type": "string",
          "pattern": "^[^/\\s]+/[^/\\s]+$",
          "description": "owner/repo.",
          "$comment": "stability: stable"
        },
        "ref": {
          "type": "string",
          "minLength": 1,
          "description": "A branch, tag or other revision. A branch is not a pin.",
          "$comment": "stability: stable"
        },
        "sha": {
          "type": "string",
          "pattern": "^[0-9a-f]{7,40}$",
          "description": "A commit sha. The only ref that cannot move.",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "sourceLocal": {
      "type": "object",
      "description": "A path already on disk. A CDF extension, not a Claude Code source form: Claude Code's only local form is the relative-path string. CDF's own marketplace lists first-party plugins that ship in the repository, and a local source is the one with nothing to fetch and nothing to pin. The README names it as such.",
      "required": [
        "source",
        "path"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "local"
          ],
          "$comment": "stability: stable"
        },
        "path": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "sourceNpm": {
      "type": "object",
      "description": "An npm package. Declared, not fetched in v1: the same missing archive reader, plus a registry the egress policy would have to permit.",
      "required": [
        "source",
        "package"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "npm"
          ],
          "$comment": "stability: stable"
        },
        "package": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "version": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "registry": {
          "type": "string",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "sourceUrl": {
      "type": "object",
      "description": "A git repository at an arbitrary URL.",
      "required": [
        "source",
        "url"
      ],
      "properties": {
        "source": {
          "type": "string",
          "enum": [
            "url"
          ],
          "$comment": "stability: stable"
        },
        "url": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "ref": {
          "type": "string",
          "minLength": 1,
          "description": "A branch, tag or other revision. A branch is not a pin.",
          "$comment": "stability: stable"
        },
        "sha": {
          "type": "string",
          "pattern": "^[0-9a-f]{7,40}$",
          "description": "A commit sha. The only ref that cannot move.",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "dependencies": {
      "type": "array",
      "description": "Plugins that must be enabled for this one to work. Each entry is `\"name\"`, `\"name@marketplace\"`, or an object with `name`, `marketplace` and `version`. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "items": {
        "anyOf": [
          {
            "type": "string",
            "minLength": 1
          },
          {
            "type": "object",
            "required": [
              "name"
            ],
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "$comment": "stability: stable"
              },
              "marketplace": {
                "type": "string",
                "$comment": "stability: stable"
              },
              "version": {
                "type": "string",
                "$comment": "stability: stable"
              }
            },
            "additionalProperties": true
          }
        ]
      }
    },
    "userConfigOption": {
      "type": "object",
      "description": "One user-configuration option. A STRICT object in Claude Code: an unknown key stops the plugin loading, so the contract refuses it too, which is the one place the contract closes a content model to mean what Claude Code means. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "required": [
        "type",
        "title",
        "description"
      ],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "string",
            "number",
            "boolean",
            "directory",
            "file"
          ],
          "$comment": "stability: stable"
        },
        "title": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "description": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "required": {
          "type": "boolean",
          "$comment": "stability: stable"
        },
        "default": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "boolean"
            },
            {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          ],
          "$comment": "stability: stable"
        },
        "options": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "$comment": "stability: stable"
        },
        "multiple": {
          "type": "boolean",
          "$comment": "stability: stable"
        },
        "sensitive": {
          "type": "boolean",
          "$comment": "stability: stable"
        },
        "min": {
          "type": "number",
          "$comment": "stability: stable"
        },
        "max": {
          "type": "number",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": false
    },
    "userConfig": {
      "type": "object",
      "description": "Values Claude Code prompts the user for when the plugin is enabled. Keys are identifiers of letters, digits and underscores not starting with a digit. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "propertyNames": {
        "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
      },
      "additionalProperties": {
        "$ref": "#/definitions/userConfigOption"
      }
    },
    "channel": {
      "type": "object",
      "description": "A message channel bound to one of the plugin's MCP servers. A STRICT object in Claude Code. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "required": [
        "server"
      ],
      "properties": {
        "server": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "displayName": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "userConfig": {
          "$ref": "#/definitions/userConfig",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": false
    },
    "lspServer": {
      "type": "object",
      "description": "One language server. A STRICT object in Claude Code: `command` and `extensionToLanguage` are required and an unknown key fails validation. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "required": [
        "command",
        "extensionToLanguage"
      ],
      "properties": {
        "command": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "extensionToLanguage": {
          "type": "object",
          "minProperties": 1,
          "propertyNames": {
            "pattern": "^\\."
          },
          "additionalProperties": {
            "type": "string",
            "minLength": 1
          },
          "$comment": "stability: stable"
        },
        "args": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "$comment": "stability: stable"
        },
        "transport": {
          "type": "string",
          "enum": [
            "stdio",
            "socket"
          ],
          "$comment": "stability: stable"
        },
        "env": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "$comment": "stability: stable"
        },
        "initializationOptions": {
          "type": "object",
          "$comment": "stability: stable"
        },
        "settings": {
          "type": "object",
          "$comment": "stability: stable"
        },
        "workspaceFolder": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "startupTimeout": {
          "type": "integer",
          "minimum": 1,
          "maximum": 9007199254740991,
          "$comment": "stability: stable"
        },
        "shutdownTimeout": {
          "type": "integer",
          "minimum": 1,
          "maximum": 9007199254740991,
          "$comment": "stability: stable"
        },
        "requestTimeout": {
          "type": "integer",
          "minimum": 1,
          "maximum": 9007199254740991,
          "$comment": "stability: stable"
        },
        "restartOnCrash": {
          "type": "boolean",
          "$comment": "stability: stable"
        },
        "maxRestarts": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "$comment": "stability: stable"
        },
        "diagnostics": {
          "type": "boolean",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": false
    },
    "lspServers": {
      "description": "`.json` LSP config files, an inline map of server name to config, or an array of either. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/lspServer"
          }
        },
        {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/definitions/lspServer"
                }
              }
            ]
          }
        }
      ]
    },
    "commandEntry": {
      "type": "object",
      "description": "One command in the `commands` object map. Exactly one of `source` (a path) or `content` (inline Markdown) is set. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "properties": {
        "source": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "content": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "description": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "argumentHint": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "model": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "allowedTools": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          },
          "$comment": "stability: stable"
        }
      },
      "oneOf": [
        {
          "required": [
            "source"
          ]
        },
        {
          "required": [
            "content"
          ]
        }
      ],
      "additionalProperties": true
    },
    "commands": {
      "description": "Flat `.md` command files, directories of them, or an object map of command name to `source` or `content`. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "anyOf": [
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1
          }
        },
        {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/commandEntry"
          }
        }
      ]
    },
    "monitor": {
      "type": "object",
      "description": "One background monitor. A STRICT object in Claude Code. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "required": [
        "name",
        "command",
        "description"
      ],
      "properties": {
        "name": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "command": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "description": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "when": {
          "type": "string",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": false
    },
    "experimental": {
      "type": "object",
      "description": "Container for `themes`, `monitors` and `evals`, whose manifest shape Claude Code says may still change. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "properties": {
        "themes": {
          "$ref": "#/definitions/componentPath",
          "$comment": "stability: stable"
        },
        "monitors": {
          "anyOf": [
            {
              "type": "string",
              "minLength": 1
            },
            {
              "type": "array",
              "items": {
                "$ref": "#/definitions/monitor"
              }
            }
          ],
          "$comment": "stability: stable"
        },
        "evals": {
          "$ref": "#/definitions/componentPath",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "relevance": {
      "type": "object",
      "description": "Signals that tell Claude Code when to suggest the plugin: `topic` and `signals`. Carried, not interpreted. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "properties": {
        "topic": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "signals": {
          "description": "Relevance signals as the marketplace reference leaves them: any value, not modelled.",
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "credentialFree": {
      "type": "string",
      "description": "A string that is not a credential. Refuses the seven shapes the reference evidence sanitiser refuses — a private key block, an AWS access key id, a GitHub token, an OpenAI key, a Slack token, a literal bearer token and a JWT — each as an I-Regexp without lookahead or word boundaries. A detector, not a guarantee: it catches these shapes and nothing else, and the documented route for a secret remains the host's own environment (`$VAR` interpolation) or `headersHelper`.",
      "allOf": [
        {
          "not": {
            "pattern": "-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----"
          }
        },
        {
          "not": {
            "pattern": "(^|[^A-Za-z0-9])AKIA[0-9A-Z]{16}([^A-Za-z0-9]|$)"
          }
        },
        {
          "not": {
            "pattern": "(^|[^A-Za-z0-9])gh[pousr]_[A-Za-z0-9]{36,}"
          }
        },
        {
          "not": {
            "pattern": "(^|[^A-Za-z0-9])sk-[A-Za-z0-9_-]{20,}"
          }
        },
        {
          "not": {
            "pattern": "(^|[^A-Za-z0-9])xox[baprs]-[A-Za-z0-9-]{10,}"
          }
        },
        {
          "not": {
            "pattern": "Bearer +[A-Za-z0-9._~+/-]{16,}"
          }
        },
        {
          "not": {
            "pattern": "eyJ[A-Za-z0-9_-]{8,}\\.eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}"
          }
        }
      ]
    },
    "hookHandler": {
      "description": "One hook, discriminated by `type`, after the Claude Code settings schema on SchemaStore (read 2026-10-05). The five types are closed because a handler of unknown type is one the harness cannot vet; each type's own fields stay open because Claude Code adds fields between releases and a plugin that uses one must not stop validating here.",
      "anyOf": [
        {
          "type": "object",
          "required": [
            "type",
            "command"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "command"
              ],
              "$comment": "stability: stable"
            },
            "command": {
              "type": "string",
              "minLength": 1,
              "description": "A shell command, or with `args` an executable run without a shell.",
              "$comment": "stability: stable"
            },
            "args": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "$comment": "stability: stable"
            },
            "async": {
              "type": "boolean",
              "$comment": "stability: stable"
            },
            "asyncRewake": {
              "type": "boolean",
              "$comment": "stability: stable"
            },
            "shell": {
              "type": "string",
              "enum": [
                "bash",
                "powershell"
              ],
              "$comment": "stability: stable"
            },
            "timeout": {
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "Seconds.",
              "$comment": "stability: stable"
            },
            "if": {
              "type": "string",
              "description": "A permission-rule filter; the hook runs only when it matches.",
              "$comment": "stability: stable"
            },
            "statusMessage": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "once": {
              "type": "boolean",
              "$comment": "stability: stable"
            }
          },
          "additionalProperties": true,
          "description": "Runs a command."
        },
        {
          "type": "object",
          "required": [
            "type",
            "prompt"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "prompt"
              ],
              "$comment": "stability: stable"
            },
            "prompt": {
              "type": "string",
              "minLength": 1,
              "$comment": "stability: stable"
            },
            "model": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "continueOnBlock": {
              "type": "boolean",
              "$comment": "stability: stable"
            },
            "timeout": {
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "Seconds.",
              "$comment": "stability: stable"
            },
            "if": {
              "type": "string",
              "description": "A permission-rule filter; the hook runs only when it matches.",
              "$comment": "stability: stable"
            },
            "statusMessage": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "once": {
              "type": "boolean",
              "$comment": "stability: stable"
            }
          },
          "additionalProperties": true,
          "description": "Asks the model a single-turn question."
        },
        {
          "type": "object",
          "required": [
            "type",
            "prompt"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "agent"
              ],
              "$comment": "stability: stable"
            },
            "prompt": {
              "type": "string",
              "minLength": 1,
              "$comment": "stability: stable"
            },
            "model": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "timeout": {
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "Seconds.",
              "$comment": "stability: stable"
            },
            "if": {
              "type": "string",
              "description": "A permission-rule filter; the hook runs only when it matches.",
              "$comment": "stability: stable"
            },
            "statusMessage": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "once": {
              "type": "boolean",
              "$comment": "stability: stable"
            }
          },
          "additionalProperties": true,
          "description": "Runs a subagent with tools."
        },
        {
          "type": "object",
          "required": [
            "type",
            "url"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "http"
              ],
              "$comment": "stability: stable"
            },
            "url": {
              "type": "string",
              "minLength": 1,
              "description": "Where the hook input is POSTed.",
              "$comment": "stability: stable"
            },
            "headers": {
              "type": "object",
              "additionalProperties": {
                "$ref": "#/definitions/credentialFree"
              },
              "description": "Request headers. Values may interpolate `$VAR` from `allowedEnvVars`; a literal credential is refused.",
              "$comment": "stability: stable"
            },
            "allowedEnvVars": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "$comment": "stability: stable"
            },
            "timeout": {
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "Seconds.",
              "$comment": "stability: stable"
            },
            "if": {
              "type": "string",
              "description": "A permission-rule filter; the hook runs only when it matches.",
              "$comment": "stability: stable"
            },
            "statusMessage": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "once": {
              "type": "boolean",
              "$comment": "stability: stable"
            }
          },
          "additionalProperties": true,
          "description": "POSTs the hook input to a URL."
        },
        {
          "type": "object",
          "required": [
            "type",
            "server",
            "tool"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "mcp_tool"
              ],
              "$comment": "stability: stable"
            },
            "server": {
              "type": "string",
              "minLength": 1,
              "description": "A configured MCP server.",
              "$comment": "stability: stable"
            },
            "tool": {
              "type": "string",
              "minLength": 1,
              "$comment": "stability: stable"
            },
            "input": {
              "type": "object",
              "additionalProperties": true,
              "$comment": "stability: stable"
            },
            "timeout": {
              "type": "number",
              "exclusiveMinimum": 0,
              "description": "Seconds.",
              "$comment": "stability: stable"
            },
            "if": {
              "type": "string",
              "description": "A permission-rule filter; the hook runs only when it matches.",
              "$comment": "stability: stable"
            },
            "statusMessage": {
              "type": "string",
              "$comment": "stability: stable"
            },
            "once": {
              "type": "boolean",
              "$comment": "stability: stable"
            }
          },
          "additionalProperties": true,
          "description": "Calls a tool on a connected MCP server."
        }
      ]
    },
    "hookMatcher": {
      "type": "object",
      "required": [
        "hooks"
      ],
      "properties": {
        "matcher": {
          "type": "string",
          "description": "A pattern matched against the event context; absent means every occurrence.",
          "$comment": "stability: stable"
        },
        "hooks": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/hookHandler"
          },
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true
    },
    "hooksMap": {
      "type": "object",
      "description": "The event map: event name to matchers. The event names are the thirty-three the Claude Code hooks reference lists (read 2026-10-05); an unknown event is refused because nothing would ever fire it.",
      "propertyNames": {
        "enum": [
          "PreToolUse",
          "PostToolUse",
          "PostToolUseFailure",
          "PermissionRequest",
          "Notification",
          "UserPromptSubmit",
          "Stop",
          "StopFailure",
          "SubagentStart",
          "SubagentStop",
          "PreCompact",
          "PostCompact",
          "Elicitation",
          "ElicitationResult",
          "TeammateIdle",
          "TaskCompleted",
          "Setup",
          "InstructionsLoaded",
          "CwdChanged",
          "FileChanged",
          "ConfigChange",
          "WorktreeCreate",
          "WorktreeRemove",
          "SessionStart",
          "SessionEnd",
          "PostToolBatch",
          "TaskCreated",
          "PermissionDenied",
          "UserPromptExpansion",
          "MessageDisplay",
          "DirectoryAdded",
          "PreModelSwitch",
          "PostModelSwitch"
        ]
      },
      "additionalProperties": {
        "type": "array",
        "items": {
          "$ref": "#/definitions/hookMatcher"
        }
      }
    },
    "hooksSource": {
      "description": "Hooks declared inline as the event map, as a path to a `.json` file that declares them (wrapped in a top-level `hooks` key), or as an array mixing both. Claude Code accepts all three.",
      "anyOf": [
        {
          "$ref": "#/definitions/hooksMap"
        },
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/hooksMap"
              },
              {
                "type": "string",
                "minLength": 1
              }
            ]
          }
        }
      ]
    },
    "mcpServer": {
      "type": "object",
      "description": "One MCP server config, keyed by name in `mcpServers`, after the Claude Code `.mcp.json` reference (read 2026-10-05). `stdio` needs `command`; `http`, `sse`, `ws` and `streamable-http` need `url`; an entry with no `type` is left as the reference leaves it. `env` and `headers` values are credential-free: a literal secret in a plugin manifest ships to everyone who installs it, and `${VAR}` interpolation or `headersHelper` is the route.",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "stdio",
            "http",
            "sse",
            "ws",
            "streamable-http"
          ],
          "$comment": "stability: stable"
        },
        "command": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "args": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "$comment": "stability: stable"
        },
        "env": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/credentialFree"
          },
          "$comment": "stability: stable"
        },
        "url": {
          "type": "string",
          "minLength": 1,
          "$comment": "stability: stable"
        },
        "headers": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/credentialFree"
          },
          "$comment": "stability: stable"
        },
        "headersHelper": {
          "type": "string",
          "$comment": "stability: stable"
        },
        "timeout": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991,
          "$comment": "stability: stable"
        },
        "alwaysLoad": {
          "type": "boolean",
          "$comment": "stability: stable"
        },
        "oauth": {
          "type": "object",
          "additionalProperties": true,
          "$comment": "stability: stable"
        }
      },
      "additionalProperties": true,
      "allOf": [
        {
          "if": {
            "properties": {
              "type": {
                "enum": [
                  "stdio"
                ],
                "$comment": "stability: stable"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "required": [
              "command"
            ]
          }
        },
        {
          "if": {
            "properties": {
              "type": {
                "enum": [
                  "http",
                  "sse",
                  "ws",
                  "streamable-http"
                ],
                "$comment": "stability: stable"
              }
            },
            "required": [
              "type"
            ]
          },
          "then": {
            "required": [
              "url"
            ]
          }
        }
      ]
    },
    "mcpServersMap": {
      "type": "object",
      "description": "Server name to config.",
      "additionalProperties": {
        "$ref": "#/definitions/mcpServer"
      }
    },
    "mcpServersSource": {
      "description": "MCP servers declared inline keyed by name, as a path to a `.json` config, an `.mcpb` or `.dxt` bundle path, an `https://` bundle URL, or an array mixing these. Claude Code accepts all of them.",
      "anyOf": [
        {
          "$ref": "#/definitions/mcpServersMap"
        },
        {
          "type": "string",
          "minLength": 1
        },
        {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/mcpServersMap"
              },
              {
                "type": "string",
                "minLength": 1
              }
            ]
          }
        }
      ]
    }
  },
  "type": "object",
  "required": [
    "name",
    "owner",
    "plugins"
  ],
  "properties": {
    "$schema": {
      "type": "string",
      "$comment": "stability: stable"
    },
    "name": {
      "type": "string",
      "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$",
      "description": "The marketplace id: letters, digits, `.`, `_` and `-`, starting with a letter or digit, no `..`, as Claude Code accepts. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "$comment": "stability: stable"
    },
    "owner": {
      "$ref": "#/definitions/owner",
      "$comment": "stability: stable"
    },
    "description": {
      "type": "string",
      "$comment": "stability: stable"
    },
    "version": {
      "type": "string",
      "$comment": "stability: stable"
    },
    "metadata": {
      "$ref": "#/definitions/metadata",
      "$comment": "stability: stable"
    },
    "allowCrossMarketplaceDependenciesOn": {
      "type": "array",
      "description": "Marketplace names this one permits its plugins to depend on. Absent means none.",
      "items": {
        "type": "string",
        "minLength": 1
      },
      "$comment": "stability: stable"
    },
    "renames": {
      "type": "object",
      "description": "Old plugin name to new name, or to null when the plugin is withdrawn. A rename does not carry a decision forward: the subject hash changes and the plugin is undecided again.",
      "additionalProperties": {
        "type": [
          "string",
          "null"
        ]
      },
      "$comment": "stability: stable"
    },
    "plugins": {
      "type": "array",
      "description": "The listed plugins. Required, and may be empty: an empty marketplace is a marketplace that lists nothing, not a malformed one.",
      "items": {
        "$ref": "#/definitions/entry"
      },
      "$comment": "stability: stable"
    },
    "forceRemoveDeletedPlugins": {
      "type": "boolean",
      "description": "When true, a plugin removed from `plugins` is uninstalled on users' machines. Claude Code plugin manifest and marketplace references, read 2026-10-05.",
      "$comment": "stability: stable"
    }
  },
  "additionalProperties": true
}
