CDF Plugin Marketplace
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.
- Schema
plugin-marketplace.schema.json, served as JSON at its$id: https://cognitive-delivery.github.io/contract/1.x/plugin-marketplace.schema.json- Dialect
http://json-schema.org/draft-07/schema#- Root
- object, open (additional properties are carried)
required:name,owner,plugins - Stability
- none stated at the root; every declared property carries its own
- Properties
- 186 declared: 10 under the root, 176 in definitions
Properties
Every declared property under the root, in the schema's own order. [] is an array's items, .* the shape of every unnamed member, #name a definition. Objects carry additional properties unless a row says otherwise.
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
$schema | string | stable | |||
name | string | yes | 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. | pattern ^[A-Za-z0-9][A-Za-z0-9._-]*$ | stable |
owner | object #owner | yes | Who publishes the marketplace. Required: a marketplace with no owner is an anonymous list of things to execute. | stable | |
description | string | stable | |||
version | string | stable | |||
metadata | object #metadata | Marketplace-wide defaults. | stable | ||
allowCrossMarketplaceDependenciesOn | array | Marketplace names this one permits its plugins to depend on. Absent means none. | stable | ||
allowCrossMarketplaceDependenciesOn[] | string | min length 1 | |||
renames | object | 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. | additional properties: see renames.* | stable | |
renames.* | string | null | ||||
plugins | array | yes | The listed plugins. Required, and may be empty: an empty marketplace is a marketplace that lists nothing, not a malformed one. | stable | |
plugins[] | object #entry | 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. | |||
forceRemoveDeletedPlugins | boolean | When true, a plugin removed from plugins is uninstalled on users' machines. Claude Code plugin manifest and marketplace references, read 2026-10-05. | stable |
Definitions
The named shapes this schema refers to as #name. A row above that links here is not expanded in place; its constraints are the definition's.
#author
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#author | string | object | 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. | any of: (1) string, min length 1; (2) object, with name, email, url, requires name | ||
#author.nameanyOf branch 2 of 2 | string | yes | min length 1 | stable | |
#author.emailanyOf branch 2 of 2 | string | stable | |||
#author.urlanyOf branch 2 of 2 | string | stable |
#capabilities
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#capabilities | object | 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. | |||
#capabilities.tools | array | Governed tool names the agent may call. | stable | ||
#capabilities.tools[] | string | 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. | pattern ^[A-Za-z0-9_][A-Za-z0-9_.:/-]{0,127}$min length 1 | ||
#capabilities.read_paths | array | Workspace-relative POSIX globs the agent may read. Refused here, without lookahead so any RE2-based 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. | stable | ||
#capabilities.read_paths[] | string | min length 1 must not match ^/, (^|/)\.\.(/|$), ^~, ^[A-Za-z]:, \\ | |||
#capabilities.write_paths | array | 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. | stable | ||
#capabilities.write_paths[] | string | min length 1 must not match ^/, (^|/)\.\.(/|$), ^~, ^[A-Za-z]:, \\ | |||
#capabilities.hosts | array | Hostnames the agent may reach, with an optional leading wildcard label (*.example.com). Enforced by the egress proxy once it keys off the lease. | stable | ||
#capabilities.hosts[] | string | 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 uses no lookahead or backreference and compiles under RE2: 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. | pattern ^(\*|(\*\.)?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*)$min length 1 max length 253 | ||
#capabilities.commands | array | Executable names the agent may run. | stable | ||
#capabilities.commands[] | string | 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. | pattern ^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$min length 1 | ||
#capabilities.tool_args | object | DECLARED argument constraints per tool a plugin asks for, as in the lease manifest it becomes (schema set 1.2, development stability): tool name to a JSON Schema the agent proposes for its own calls to that tool, after Progent's argument-schema policies. A declaration, not a grant: in 1.x an issuer MAY omit it from the granted manifest and MUST NOT treat it as granted authority, because the reference gate does not yet evaluate argument schemas and a narrowing rule without an enforcing gate is a claim the corpus cannot test. The vector tool-args-dropped shows the reference dropping it. It becomes a rule when a gate enforces it. | keys must match ^[A-Za-z0-9_][A-Za-z0-9_.:/-]{0,127}$additional properties: see #capabilities.tool_args.* | development a declaration an issuer MAY omit from the grant (SPEC 4.4); becomes a rule when a gate enforces it | |
#capabilities.tool_args.* | object | A JSON Schema. Not validated as one here: draft-07 cannot validate a schema as data without a meta-schema $ref, which the self-contained rule forbids. |
#componentPath
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#componentPath | string | array | 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. | any of: (1) string, min length 1; (2) array, of string, min length 1 | ||
#componentPath[]anyOf branch 2 of 2 | string | min length 1 |
#entry
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#entry | object | 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. | conditional requirements (below) | ||
#entry.name | string | yes | pattern ^[A-Za-z0-9][A-Za-z0-9._-]*$ | stable | |
#entry.source | string | object #source | yes | 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. | stable | |
#entry.displayName | string | stable | |||
#entry.description | string | stable | |||
#entry.version | string | stable | |||
#entry.author | string | object #author | 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. | stable | ||
#entry.homepage | string | stable | |||
#entry.repository | string | object #repository | The source repository, as a URL string or as an object carrying one. | stable | ||
#entry.license | string | stable | |||
#entry.keywords | array | stable | |||
#entry.keywords[] | string | min length 1 | |||
#entry.category | string | stable | |||
#entry.tags | array | stable | |||
#entry.tags[] | string | min length 1 | |||
#entry.defaultEnabled | boolean | stable | |||
#entry.strict | boolean | when headersHelper is present | Whether the entry must match the fetched manifest exactly. Absent means true: the stricter reading is the default, so a marketplace relaxes it deliberately. | stable | |
#entry.skills | string | array #componentPath | 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. | stable | ||
#entry.commands | string | array | object #commands | 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. | stable | ||
#entry.agents | string | array #componentPath | 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. | stable | ||
#entry.hooks | object | string | array #hooksSource | 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. | stable | ||
#entry.mcpServers | object | string | array #mcpServersSource | 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. | stable | ||
#entry.lspServers | string | object | array #lspServers | .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. | stable | ||
#entry.headers | object | 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. | keys must not match ^[Aa][Uu][Tt][Hh][Oo][Rr][Ii][Zz][Aa][Tt][Ii][Oo][Nn]$An authorization header, in any case, is refused: its value would be a credential in a file everyone reads. headersHelper is the route.additional properties: see #entry.headers.* | stable | |
#entry.headers.* | string #credentialFree | 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 a pattern without lookahead or word boundaries, which RE2 compiles. 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. | |||
#entry.headersHelper | string | 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. | min length 1 | stable | |
#entry.relevance | object #relevance | 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. | stable | ||
#entry.dependencies | array #dependencies | 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. | stable | ||
#entry.metadata | object | Free-form publisher metadata on the entry. Carried, never interpreted. | stable | ||
#entry.settings | object | stable | |||
#entry.userConfig | object #userConfig | 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. | stable | ||
#entry.channels | array | stable | |||
#entry.channels[] | object #channel | 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. | |||
#entry.outputStyles | string | array #componentPath | 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. | stable | ||
#entry.workflows | string | array #componentPath | 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. | stable | ||
#entry.themes | string | array #componentPath | 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. | stable | ||
#entry.experimental | object #experimental | 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. | stable | ||
#entry.types | string | min length 1 must not match ^/, (^|/)\.\.(/|$), ^~, ^[A-Za-z]:, \\ | stable | ||
#entry.cdf | object #entryCdf | The additive CDF block for one entry. Absent in a plain Claude Code marketplace. | stable | ||
#entry.strictthen: when headersHelper is present | any | when headersHelper is present | const false | stable |
#entryCdf
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#entryCdf | object | The additive CDF block for one entry. Absent in a plain Claude Code marketplace. | |||
#entryCdf.digest | string | 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. | pattern ^[0-9a-f]{64}$ | stable | |
#entryCdf.capabilities | object #capabilities | 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. | stable |
#metadata
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#metadata | object | Marketplace-wide defaults. | |||
#metadata.pluginRoot | string | The directory relative paths in source resolve from. | stable | ||
#metadata.description | string | stable | |||
#metadata.version | string | stable |
#owner
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#owner | object | Who publishes the marketplace. Required: a marketplace with no owner is an anonymous list of things to execute. | |||
#owner.name | string | yes | min length 1 | stable | |
#owner.email | string | stable | |||
#owner.url | string | stable |
#repository
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#repository | string | object | The source repository, as a URL string or as an object carrying one. | any of: (1) string, min length 1; (2) object |
#source
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#source | string | object | 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. | any of: (1) string, min length 1; (2) #sourceLocal; (3) #sourceGithub; (4) #sourceUrl; (5) #sourceGitSubdir; (6) #sourceNpm; (7) #sourceArchive; (8) #sourceCommand |
#sourceArchive
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#sourceArchive | object | 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. | |||
#sourceArchive.source | string | yes | one of "archive" | stable | |
#sourceArchive.url | string | yes | min length 1 | stable | |
#sourceArchive.sha256 | string | 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. | pattern ^[0-9a-fA-F]{64}$ | stable |
#sourceCommand
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#sourceCommand | object | 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. | |||
#sourceCommand.source | string | yes | one of "command" | stable | |
#sourceCommand.command | string | yes | min length 1 | stable | |
#sourceCommand.timeout | integer | Seconds, 1 to 600; Claude Code defaults to 60. Claude Code plugin manifest and marketplace references, read 2026-10-05. | min 1 max 600 | stable | |
#sourceCommand.mode | string | copy (default) copies the printed directory; link loads it in place. Claude Code plugin manifest and marketplace references, read 2026-10-05. | one of "copy", "link" | stable |
#sourceGitSubdir
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#sourceGitSubdir | object | One directory of a git repository. path is repository-relative and may not escape it. | |||
#sourceGitSubdir.source | string | yes | one of "git-subdir" | stable | |
#sourceGitSubdir.url | string | yes | min length 1 | stable | |
#sourceGitSubdir.path | string | yes | min length 1 must not match ^/, (^|/)\.\.(/|$), ^~, ^[A-Za-z]:, \\ | stable | |
#sourceGitSubdir.ref | string | A branch, tag or other revision. A branch is not a pin. | min length 1 | stable | |
#sourceGitSubdir.sha | string | A commit sha. The only ref that cannot move. | pattern ^[0-9a-f]{7,40}$ | stable |
#sourceGithub
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#sourceGithub | object | A GitHub repository. | |||
#sourceGithub.source | string | yes | one of "github" | stable | |
#sourceGithub.repo | string | yes | owner/repo. | pattern ^[^/\s]+/[^/\s]+$ | stable |
#sourceGithub.ref | string | A branch, tag or other revision. A branch is not a pin. | min length 1 | stable | |
#sourceGithub.sha | string | A commit sha. The only ref that cannot move. | pattern ^[0-9a-f]{7,40}$ | stable |
#sourceLocal
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#sourceLocal | object | 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. | |||
#sourceLocal.source | string | yes | one of "local" | stable | |
#sourceLocal.path | string | yes | min length 1 | stable |
#sourceNpm
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#sourceNpm | object | An npm package. Declared, not fetched in v1: the same missing archive reader, plus a registry the egress policy would have to permit. | |||
#sourceNpm.source | string | yes | one of "npm" | stable | |
#sourceNpm.package | string | yes | min length 1 | stable | |
#sourceNpm.version | string | stable | |||
#sourceNpm.registry | string | stable |
#sourceUrl
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#sourceUrl | object | A git repository at an arbitrary URL. | |||
#sourceUrl.source | string | yes | one of "url" | stable | |
#sourceUrl.url | string | yes | min length 1 | stable | |
#sourceUrl.ref | string | A branch, tag or other revision. A branch is not a pin. | min length 1 | stable | |
#sourceUrl.sha | string | A commit sha. The only ref that cannot move. | pattern ^[0-9a-f]{7,40}$ | stable |
#dependencies
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#dependencies | array | 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. | |||
#dependencies[] | string | object | any of: (1) string, min length 1; (2) object, with name, marketplace, version, requires name | |||
#dependencies[].nameanyOf branch 2 of 2 | string | yes | min length 1 | stable | |
#dependencies[].marketplaceanyOf branch 2 of 2 | string | stable | |||
#dependencies[].versionanyOf branch 2 of 2 | string | stable |
#userConfigOption
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#userConfigOption | object | 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. | no additional properties | ||
#userConfigOption.type | string | yes | one of "string", "number", "boolean", "directory", "file" | stable | |
#userConfigOption.title | string | yes | min length 1 | stable | |
#userConfigOption.description | string | yes | stable | ||
#userConfigOption.required | boolean | stable | |||
#userConfigOption.default | string | number | boolean | array | any of: (1) string; (2) number; (3) boolean; (4) array, of string | stable | ||
#userConfigOption.default[]anyOf branch 4 of 4 | string | ||||
#userConfigOption.options | array | stable | |||
#userConfigOption.options[] | string | min length 1 max length 64 | |||
#userConfigOption.multiple | boolean | stable | |||
#userConfigOption.sensitive | boolean | stable | |||
#userConfigOption.min | number | stable | |||
#userConfigOption.max | number | stable |
#userConfig
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#userConfig | object | 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. | keys must match ^[A-Za-z_][A-Za-z0-9_]*$additional properties: see #userConfig.* | ||
#userConfig.* | object #userConfigOption | 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. |
#channel
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#channel | object | 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. | no additional properties | ||
#channel.server | string | yes | min length 1 | stable | |
#channel.displayName | string | stable | |||
#channel.userConfig | object #userConfig | 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. | stable |
#lspServer
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#lspServer | object | 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. | no additional properties | ||
#lspServer.command | string | yes | min length 1 | stable | |
#lspServer.extensionToLanguage | object | yes | min properties 1 keys must match ^\.additional properties: see #lspServer.extensionToLanguage.* | stable | |
#lspServer.extensionToLanguage.* | string | min length 1 | |||
#lspServer.args | array | stable | |||
#lspServer.args[] | string | ||||
#lspServer.transport | string | one of "stdio", "socket" | stable | ||
#lspServer.env | object | additional properties: see #lspServer.env.* | stable | ||
#lspServer.env.* | string | ||||
#lspServer.initializationOptions | object | stable | |||
#lspServer.settings | object | stable | |||
#lspServer.workspaceFolder | string | stable | |||
#lspServer.startupTimeout | integer | min 1 max 9007199254740991 | stable | ||
#lspServer.shutdownTimeout | integer | min 1 max 9007199254740991 | stable | ||
#lspServer.requestTimeout | integer | min 1 max 9007199254740991 | stable | ||
#lspServer.restartOnCrash | boolean | stable | |||
#lspServer.maxRestarts | integer | min 0 max 9007199254740991 | stable | ||
#lspServer.diagnostics | boolean | stable |
#lspServers
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#lspServers | string | object | array | .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. | any of: (1) string, min length 1; (2) object, additional properties #lspServer; (3) array, of string | object, any of 2 branches | ||
#lspServers.*anyOf branch 2 of 3 | object #lspServer | 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. | |||
#lspServers[]anyOf branch 3 of 3 | string | object | any of: (1) string, min length 1; (2) object, additional properties #lspServer | |||
#lspServers[].*anyOf branch 3 of 3; anyOf branch 2 of 2 | object #lspServer | 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. |
#commandEntry
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#commandEntry | object | 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. | exactly one of: (1) requires source; (2) requires content | ||
#commandEntry.source | string | min length 1 | stable | ||
#commandEntry.content | string | stable | |||
#commandEntry.description | string | stable | |||
#commandEntry.argumentHint | string | stable | |||
#commandEntry.model | string | stable | |||
#commandEntry.allowedTools | array | stable | |||
#commandEntry.allowedTools[] | string | min length 1 |
#commands
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#commands | string | array | object | 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. | any of: (1) string, min length 1; (2) array, of string, min length 1; (3) object, additional properties #commandEntry | ||
#commands[]anyOf branch 2 of 3 | string | min length 1 | |||
#commands.*anyOf branch 3 of 3 | object #commandEntry | 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. |
#monitor
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#monitor | object | One background monitor. A STRICT object in Claude Code. Claude Code plugin manifest and marketplace references, read 2026-10-05. | no additional properties | ||
#monitor.name | string | yes | min length 1 | stable | |
#monitor.command | string | yes | min length 1 | stable | |
#monitor.description | string | yes | min length 1 | stable | |
#monitor.when | string | stable |
#experimental
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#experimental | object | 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. | |||
#experimental.themes | string | array #componentPath | 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. | stable | ||
#experimental.monitors | string | array | any of: (1) string, min length 1; (2) array, of #monitor | stable | ||
#experimental.monitors[]anyOf branch 2 of 2 | object #monitor | One background monitor. A STRICT object in Claude Code. Claude Code plugin manifest and marketplace references, read 2026-10-05. | |||
#experimental.evals | string | array #componentPath | 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. | stable |
#relevance
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#relevance | object | 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. | |||
#relevance.topic | string | stable | |||
#relevance.signals | any | Relevance signals as the marketplace reference leaves them: any value, not modelled. | stable |
#credentialFree
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#credentialFree | string | 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 a pattern without lookahead or word boundaries, which RE2 compiles. 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. | must not match -----BEGIN [A-Z0-9 ]*PRIVATE KEY-----, (^|[^A-Za-z0-9])AKIA[0-9A-Z]{16}([^A-Za-z0-9]|$), (^|[^A-Za-z0-9])gh[pousr]_[A-Za-z0-9]{36,}, (^|[^A-Za-z0-9])sk-[A-Za-z0-9_-]{20,}, (^|[^A-Za-z0-9])xox[baprs]-[A-Za-z0-9-]{10,}, Bearer +[A-Za-z0-9._~+/-]{16,}, eyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,} |
#hookHandler
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#hookHandler | object | 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. | any of: (1) object, with type = "command", command, args, async, asyncRewake, shell one of "bash", "powershell", timeout, if, statusMessage, once, requires type, command, Runs a command.; (2) object, with type = "prompt", prompt, model, continueOnBlock, timeout, if, statusMessage, once, requires type, prompt, Asks the model a single-turn question.; (3) object, with type = "agent", prompt, model, timeout, if, statusMessage, once, requires type, prompt, Runs a subagent with tools.; (4) object, with type = "http", url, headers, allowedEnvVars, timeout, if, statusMessage, once, requires type, url, POSTs the hook input to a URL.; (5) object, with type = "mcp_tool", server, tool, input, timeout, if, statusMessage, once, requires type, server, tool, Calls a tool on a connected MCP server. | ||
#hookHandler.typeanyOf branch 1 of 5: Runs a command. | string | yes | one of "command" | stable | |
#hookHandler.commandanyOf branch 1 of 5: Runs a command. | string | yes | A shell command, or with args an executable run without a shell. | min length 1 | stable |
#hookHandler.argsanyOf branch 1 of 5: Runs a command. | array | stable | |||
#hookHandler.args[]anyOf branch 1 of 5: Runs a command. | string | ||||
#hookHandler.asyncanyOf branch 1 of 5: Runs a command. | boolean | stable | |||
#hookHandler.asyncRewakeanyOf branch 1 of 5: Runs a command. | boolean | stable | |||
#hookHandler.shellanyOf branch 1 of 5: Runs a command. | string | one of "bash", "powershell" | stable | ||
#hookHandler.timeoutanyOf branch 1 of 5: Runs a command. | number | Seconds. | greater than 0 | stable | |
#hookHandler.ifanyOf branch 1 of 5: Runs a command. | string | A permission-rule filter; the hook runs only when it matches. | stable | ||
#hookHandler.statusMessageanyOf branch 1 of 5: Runs a command. | string | stable | |||
#hookHandler.onceanyOf branch 1 of 5: Runs a command. | boolean | stable | |||
#hookHandler.typeanyOf branch 2 of 5: Asks the model a single-turn question. | string | yes | one of "prompt" | stable | |
#hookHandler.promptanyOf branch 2 of 5: Asks the model a single-turn question. | string | yes | min length 1 | stable | |
#hookHandler.modelanyOf branch 2 of 5: Asks the model a single-turn question. | string | stable | |||
#hookHandler.continueOnBlockanyOf branch 2 of 5: Asks the model a single-turn question. | boolean | stable | |||
#hookHandler.timeoutanyOf branch 2 of 5: Asks the model a single-turn question. | number | Seconds. | greater than 0 | stable | |
#hookHandler.ifanyOf branch 2 of 5: Asks the model a single-turn question. | string | A permission-rule filter; the hook runs only when it matches. | stable | ||
#hookHandler.statusMessageanyOf branch 2 of 5: Asks the model a single-turn question. | string | stable | |||
#hookHandler.onceanyOf branch 2 of 5: Asks the model a single-turn question. | boolean | stable | |||
#hookHandler.typeanyOf branch 3 of 5: Runs a subagent with tools. | string | yes | one of "agent" | stable | |
#hookHandler.promptanyOf branch 3 of 5: Runs a subagent with tools. | string | yes | min length 1 | stable | |
#hookHandler.modelanyOf branch 3 of 5: Runs a subagent with tools. | string | stable | |||
#hookHandler.timeoutanyOf branch 3 of 5: Runs a subagent with tools. | number | Seconds. | greater than 0 | stable | |
#hookHandler.ifanyOf branch 3 of 5: Runs a subagent with tools. | string | A permission-rule filter; the hook runs only when it matches. | stable | ||
#hookHandler.statusMessageanyOf branch 3 of 5: Runs a subagent with tools. | string | stable | |||
#hookHandler.onceanyOf branch 3 of 5: Runs a subagent with tools. | boolean | stable | |||
#hookHandler.typeanyOf branch 4 of 5: POSTs the hook input to a URL. | string | yes | one of "http" | stable | |
#hookHandler.urlanyOf branch 4 of 5: POSTs the hook input to a URL. | string | yes | Where the hook input is POSTed. | min length 1 | stable |
#hookHandler.headersanyOf branch 4 of 5: POSTs the hook input to a URL. | object | Request headers. Values may interpolate $VAR from allowedEnvVars; a literal credential is refused. | additional properties: see #hookHandler.headers.* | stable | |
#hookHandler.headers.*anyOf branch 4 of 5: POSTs the hook input to a URL. | string #credentialFree | 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 a pattern without lookahead or word boundaries, which RE2 compiles. 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. | |||
#hookHandler.allowedEnvVarsanyOf branch 4 of 5: POSTs the hook input to a URL. | array | stable | |||
#hookHandler.allowedEnvVars[]anyOf branch 4 of 5: POSTs the hook input to a URL. | string | ||||
#hookHandler.timeoutanyOf branch 4 of 5: POSTs the hook input to a URL. | number | Seconds. | greater than 0 | stable | |
#hookHandler.ifanyOf branch 4 of 5: POSTs the hook input to a URL. | string | A permission-rule filter; the hook runs only when it matches. | stable | ||
#hookHandler.statusMessageanyOf branch 4 of 5: POSTs the hook input to a URL. | string | stable | |||
#hookHandler.onceanyOf branch 4 of 5: POSTs the hook input to a URL. | boolean | stable | |||
#hookHandler.typeanyOf branch 5 of 5: Calls a tool on a connected MCP server. | string | yes | one of "mcp_tool" | stable | |
#hookHandler.serveranyOf branch 5 of 5: Calls a tool on a connected MCP server. | string | yes | A configured MCP server. | min length 1 | stable |
#hookHandler.toolanyOf branch 5 of 5: Calls a tool on a connected MCP server. | string | yes | min length 1 | stable | |
#hookHandler.inputanyOf branch 5 of 5: Calls a tool on a connected MCP server. | object | stable | |||
#hookHandler.timeoutanyOf branch 5 of 5: Calls a tool on a connected MCP server. | number | Seconds. | greater than 0 | stable | |
#hookHandler.ifanyOf branch 5 of 5: Calls a tool on a connected MCP server. | string | A permission-rule filter; the hook runs only when it matches. | stable | ||
#hookHandler.statusMessageanyOf branch 5 of 5: Calls a tool on a connected MCP server. | string | stable | |||
#hookHandler.onceanyOf branch 5 of 5: Calls a tool on a connected MCP server. | boolean | stable |
#hookMatcher
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#hookMatcher | object | ||||
#hookMatcher.matcher | string | A pattern matched against the event context; absent means every occurrence. | stable | ||
#hookMatcher.hooks | array | yes | stable | ||
#hookMatcher.hooks[] | object #hookHandler | 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. |
#hooksMap
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#hooksMap | object | 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. | keys one of 33 values all 33"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"additional properties: see #hooksMap.* | ||
#hooksMap.* | array | ||||
#hooksMap.*[] | object #hookMatcher |
#hooksSource
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#hooksSource | object | string | array | 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. | any of: (1) #hooksMap; (2) string, min length 1; (3) array, of object | string, any of 2 branches | ||
#hooksSource[]anyOf branch 3 of 3 | object | string | any of: (1) #hooksMap; (2) string, min length 1 |
#mcpServer
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#mcpServer | object | 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. | conditional requirements (below) | ||
#mcpServer.type | string | one of "stdio", "http", "sse", "ws", "streamable-http" | stable | ||
#mcpServer.command | string | when type is "stdio" | min length 1 | stable | |
#mcpServer.args | array | stable | |||
#mcpServer.args[] | string | ||||
#mcpServer.env | object | additional properties: see #mcpServer.env.* | stable | ||
#mcpServer.env.* | string #credentialFree | 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 a pattern without lookahead or word boundaries, which RE2 compiles. 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. | |||
#mcpServer.url | string | when type is "http", "sse", "ws" or "streamable-http" | min length 1 | stable | |
#mcpServer.headers | object | additional properties: see #mcpServer.headers.* | stable | ||
#mcpServer.headers.* | string #credentialFree | 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 a pattern without lookahead or word boundaries, which RE2 compiles. 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. | |||
#mcpServer.headersHelper | string | stable | |||
#mcpServer.timeout | integer | min 0 max 9007199254740991 | stable | ||
#mcpServer.alwaysLoad | boolean | stable | |||
#mcpServer.oauth | object | stable |
#mcpServersMap
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#mcpServersMap | object | Server name to config. | additional properties: see #mcpServersMap.* | ||
#mcpServersMap.* | object #mcpServer | 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. |
#mcpServersSource
| Path | Type | Required | Description | Constraints | Stability |
|---|---|---|---|---|---|
#mcpServersSource | object | string | array | 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. | any of: (1) #mcpServersMap; (2) string, min length 1; (3) array, of object | string, any of 2 branches | ||
#mcpServersSource[]anyOf branch 3 of 3 | object | string | any of: (1) #mcpServersMap; (2) string, min length 1 |
Conditional requirements
What an if/then clause makes required, one line per property and condition value; the same text appears in the Required column above.
| Property | Required | Where |
|---|---|---|
strict | when headersHelper is present | #entry |
strict | when headersHelper is present, must be const false | #entry |
command | when type is "stdio" | #mcpServer |
url | when type is "http" | #mcpServer |
url | when type is "sse" | #mcpServer |
url | when type is "ws" | #mcpServer |
url | when type is "streamable-http" | #mcpServer |