{"$schema":"http://json-schema.org/draft-07/schema#","$id":"https://json.schemastore.org/claude-code-plugin-manifest.json","$comment":"Generated on 2026-04-23T05:09:41.810Z","type":"object","properties":{"$schema":{"description":"JSON Schema reference for editor autocomplete/validation; ignored at load time","type":"string"},"name":{"description":"Unique identifier for the plugin, used for namespacing (prefer kebab-case)","type":"string","minLength":1},"version":{"description":"Semantic version (e.g., 1.2.3) following semver.org specification","type":"string"},"description":{"description":"Brief, user-facing explanation of what the plugin provides","type":"string"},"author":{"description":"Information about the plugin creator or maintainer","type":"object","properties":{"name":{"description":"Display name of the plugin author or organization","type":"string","minLength":1},"email":{"description":"Contact email for support or feedback","type":"string"},"url":{"description":"Website, GitHub profile, or organization URL","type":"string"}},"required":["name"]},"homepage":{"description":"Plugin homepage or documentation URL","type":"string","format":"uri"},"repository":{"description":"Source code repository URL","type":"string"},"license":{"description":"SPDX license identifier (e.g., MIT, Apache-2.0)","type":"string"},"keywords":{"description":"Tags for plugin discovery and categorization","type":"array","items":{"type":"string"}},"dependencies":{"description":"Plugins that must be enabled for this plugin to function. Bare names (no \"@marketplace\") are resolved against the declaring plugin's own marketplace.","type":"array","items":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][-A-Za-z0-9._]*(@[A-Za-z0-9][-A-Za-z0-9._]*)?(@\\^[^@]*)?$"},{"type":"object","properties":{"name":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9][-A-Za-z0-9._]*$"},"marketplace":{"type":"string","minLength":1,"pattern":"^[A-Za-z0-9][-A-Za-z0-9._]*$"}},"required":["name"],"additionalProperties":{}}]}},"hooks":{"anyOf":[{"description":"Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.json$"}]},{"description":"Additional hooks (in addition to those in hooks/hooks.json, if it exists)","type":"object","propertyNames":{"anyOf":[{"type":"string","enum":["PreToolUse","PostToolUse","PostToolUseFailure","PostToolBatch","Notification","UserPromptSubmit","UserPromptExpansion","SessionStart","SessionEnd","Stop","StopFailure","SubagentStart","SubagentStop","PreCompact","PostCompact","PermissionRequest","PermissionDenied","Setup","TeammateIdle","TaskCreated","TaskCompleted","Elicitation","ElicitationResult","ConfigChange","WorktreeCreate","WorktreeRemove","InstructionsLoaded","CwdChanged","FileChanged"]},{"not":{}}]},"additionalProperties":{"type":"array","items":{"type":"object","properties":{"matcher":{"description":"String pattern to match (e.g. tool names like \"Write\")","type":"string"},"hooks":{"description":"List of hooks to execute when the matcher matches","type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"description":"Shell command hook type","type":"string","const":"command"},"command":{"description":"Shell command to execute","type":"string"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"shell":{"description":"Shell interpreter. 'bash' uses your $SHELL (bash/zsh/sh); 'powershell' uses pwsh. Defaults to bash.","type":"string","enum":["bash","powershell"]},"timeout":{"description":"Timeout in seconds for this specific command","type":"number","exclusiveMinimum":0},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"},"async":{"description":"If true, hook runs in background without blocking","type":"boolean"},"asyncRewake":{"description":"If true, hook runs in background and wakes the model on exit code 2 (blocking error). Implies async.","type":"boolean"}},"required":["type","command"]},{"type":"object","properties":{"type":{"description":"LLM prompt hook type","type":"string","const":"prompt"},"prompt":{"description":"Prompt to evaluate with LLM. Use $ARGUMENTS placeholder for hook input JSON.","type":"string"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for this specific prompt evaluation","type":"number","exclusiveMinimum":0},"model":{"description":"Model to use for this prompt hook (e.g., \"claude-sonnet-4-6\"). If not specified, uses the default small fast model.","type":"string"},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","prompt"]},{"type":"object","properties":{"type":{"description":"Agentic verifier hook type","type":"string","const":"agent"},"prompt":{"description":"Prompt describing what to verify (e.g. \"Verify that unit tests ran and passed.\"). Use $ARGUMENTS placeholder for hook input JSON.","type":"string"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for agent execution (default 60)","type":"number","exclusiveMinimum":0},"model":{"description":"Model to use for this agent hook (e.g., \"claude-sonnet-4-6\"). If not specified, uses Haiku.","type":"string"},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","prompt"]},{"type":"object","properties":{"type":{"description":"HTTP hook type","type":"string","const":"http"},"url":{"description":"URL to POST the hook input JSON to","type":"string","format":"uri"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for this specific request","type":"number","exclusiveMinimum":0},"headers":{"description":"Additional headers to include in the request. Values may reference environment variables using $VAR_NAME or ${VAR_NAME} syntax (e.g., \"Authorization\": \"Bearer $MY_TOKEN\"). Only variables listed in allowedEnvVars will be interpolated.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"allowedEnvVars":{"description":"Explicit list of environment variable names that may be interpolated in header values. Only variables listed here will be resolved; all other $VAR references are left as empty strings. Required for env var interpolation to work.","type":"array","items":{"type":"string"}},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","url"]},{"type":"object","properties":{"type":{"description":"MCP tool hook type","type":"string","const":"mcp_tool"},"server":{"description":"Name of an already-configured MCP server to invoke","type":"string"},"tool":{"description":"Name of the tool on that server to call","type":"string"},"input":{"description":"Arguments passed to the MCP tool. String values support ${path} interpolation from the hook input JSON (e.g. \"${tool_input.file_path}\").","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for this specific tool call","type":"number","exclusiveMinimum":0},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","server","tool"]}]}}},"required":["hooks"]}}},{"type":"array","items":{"anyOf":[{"description":"Path to file with additional hooks (in addition to those in hooks/hooks.json, if it exists), relative to the plugin root","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.json$"}]},{"description":"Additional hooks (in addition to those in hooks/hooks.json, if it exists)","type":"object","propertyNames":{"anyOf":[{"type":"string","enum":["PreToolUse","PostToolUse","PostToolUseFailure","PostToolBatch","Notification","UserPromptSubmit","UserPromptExpansion","SessionStart","SessionEnd","Stop","StopFailure","SubagentStart","SubagentStop","PreCompact","PostCompact","PermissionRequest","PermissionDenied","Setup","TeammateIdle","TaskCreated","TaskCompleted","Elicitation","ElicitationResult","ConfigChange","WorktreeCreate","WorktreeRemove","InstructionsLoaded","CwdChanged","FileChanged"]},{"not":{}}]},"additionalProperties":{"type":"array","items":{"type":"object","properties":{"matcher":{"description":"String pattern to match (e.g. tool names like \"Write\")","type":"string"},"hooks":{"description":"List of hooks to execute when the matcher matches","type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"description":"Shell command hook type","type":"string","const":"command"},"command":{"description":"Shell command to execute","type":"string"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"shell":{"description":"Shell interpreter. 'bash' uses your $SHELL (bash/zsh/sh); 'powershell' uses pwsh. Defaults to bash.","type":"string","enum":["bash","powershell"]},"timeout":{"description":"Timeout in seconds for this specific command","type":"number","exclusiveMinimum":0},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"},"async":{"description":"If true, hook runs in background without blocking","type":"boolean"},"asyncRewake":{"description":"If true, hook runs in background and wakes the model on exit code 2 (blocking error). Implies async.","type":"boolean"}},"required":["type","command"]},{"type":"object","properties":{"type":{"description":"LLM prompt hook type","type":"string","const":"prompt"},"prompt":{"description":"Prompt to evaluate with LLM. Use $ARGUMENTS placeholder for hook input JSON.","type":"string"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for this specific prompt evaluation","type":"number","exclusiveMinimum":0},"model":{"description":"Model to use for this prompt hook (e.g., \"claude-sonnet-4-6\"). If not specified, uses the default small fast model.","type":"string"},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","prompt"]},{"type":"object","properties":{"type":{"description":"Agentic verifier hook type","type":"string","const":"agent"},"prompt":{"description":"Prompt describing what to verify (e.g. \"Verify that unit tests ran and passed.\"). Use $ARGUMENTS placeholder for hook input JSON.","type":"string"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for agent execution (default 60)","type":"number","exclusiveMinimum":0},"model":{"description":"Model to use for this agent hook (e.g., \"claude-sonnet-4-6\"). If not specified, uses Haiku.","type":"string"},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","prompt"]},{"type":"object","properties":{"type":{"description":"HTTP hook type","type":"string","const":"http"},"url":{"description":"URL to POST the hook input JSON to","type":"string","format":"uri"},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for this specific request","type":"number","exclusiveMinimum":0},"headers":{"description":"Additional headers to include in the request. Values may reference environment variables using $VAR_NAME or ${VAR_NAME} syntax (e.g., \"Authorization\": \"Bearer $MY_TOKEN\"). Only variables listed in allowedEnvVars will be interpolated.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"allowedEnvVars":{"description":"Explicit list of environment variable names that may be interpolated in header values. Only variables listed here will be resolved; all other $VAR references are left as empty strings. Required for env var interpolation to work.","type":"array","items":{"type":"string"}},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","url"]},{"type":"object","properties":{"type":{"description":"MCP tool hook type","type":"string","const":"mcp_tool"},"server":{"description":"Name of an already-configured MCP server to invoke","type":"string"},"tool":{"description":"Name of the tool on that server to call","type":"string"},"input":{"description":"Arguments passed to the MCP tool. String values support ${path} interpolation from the hook input JSON (e.g. \"${tool_input.file_path}\").","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"if":{"description":"Permission rule syntax to filter when this hook runs (e.g., \"Bash(git *)\"). Only runs if the tool call matches the pattern. Avoids spawning hooks for non-matching commands.","type":"string"},"timeout":{"description":"Timeout in seconds for this specific tool call","type":"number","exclusiveMinimum":0},"statusMessage":{"description":"Custom status message to display in spinner while hook runs","type":"string"},"once":{"description":"If true, hook runs once and is removed after execution","type":"boolean"}},"required":["type","server","tool"]}]}}},"required":["hooks"]}}}]}}]},"commands":{"anyOf":[{"description":"Path to additional command file or skill directory (in addition to those in the commands/ directory, if it exists), relative to the plugin root","anyOf":[{"type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.md$"}]},{"type":"string","pattern":"^\\.\\/.*"}]},{"description":"List of paths to additional command files or skill directories","type":"array","items":{"description":"Path to additional command file or skill directory (in addition to those in the commands/ directory, if it exists), relative to the plugin root","anyOf":[{"type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.md$"}]},{"type":"string","pattern":"^\\.\\/.*"}]}},{"description":"Object mapping of command names to their metadata and source files. Command name becomes the slash command name (e.g., \"about\" → \"/plugin:about\")","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"source":{"description":"Path to command markdown file, relative to plugin root","anyOf":[{"type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.md$"}]},{"type":"string","pattern":"^\\.\\/.*"}]},"content":{"description":"Inline markdown content for the command","type":"string"},"description":{"description":"Command description override","type":"string"},"argumentHint":{"description":"Hint for command arguments (e.g., \"[file]\")","type":"string"},"model":{"description":"Default model for this command","type":"string"},"allowedTools":{"description":"Tools allowed when command runs","type":"array","items":{"type":"string"}}}}}]},"agents":{"anyOf":[{"description":"Path to additional agent file (in addition to those in the agents/ directory, if it exists), relative to the plugin root","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.md$"}]},{"description":"List of paths to additional agent files","type":"array","items":{"description":"Path to additional agent file (in addition to those in the agents/ directory, if it exists), relative to the plugin root","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.md$"}]}}]},"skills":{"anyOf":[{"description":"Path to additional skill directory (in addition to those in the skills/ directory, if it exists), relative to the plugin root","type":"string","pattern":"^\\.\\/.*"},{"description":"List of paths to additional skill directories","type":"array","items":{"description":"Path to additional skill directory (in addition to those in the skills/ directory, if it exists), relative to the plugin root","type":"string","pattern":"^\\.\\/.*"}}]},"outputStyles":{"anyOf":[{"description":"Path to additional output styles directory or file (in addition to those in the output-styles/ directory, if it exists), relative to the plugin root","type":"string","pattern":"^\\.\\/.*"},{"description":"List of paths to additional output styles directories or files","type":"array","items":{"description":"Path to additional output styles directory or file (in addition to those in the output-styles/ directory, if it exists), relative to the plugin root","type":"string","pattern":"^\\.\\/.*"}}]},"themes":{"anyOf":[{"description":"Path to additional themes directory or file (in addition to those in the themes/ directory, if it exists), relative to the plugin root","type":"string","pattern":"^\\.\\/.*"},{"description":"List of paths to additional themes directories or files","type":"array","items":{"description":"Path to additional themes directory or file (in addition to those in the themes/ directory, if it exists), relative to the plugin root","type":"string","pattern":"^\\.\\/.*"}}]},"channels":{"description":"Channels this plugin provides. Each entry declares an MCP server as a message channel and optionally specifies user configuration to prompt for at enable time.","type":"array","items":{"type":"object","properties":{"server":{"description":"Name of the MCP server this channel binds to. Must match a key in this plugin's mcpServers.","type":"string","minLength":1},"displayName":{"description":"Human-readable name shown in the config dialog title (e.g., \"Telegram\"). Defaults to the server name.","type":"string"},"userConfig":{"description":"Fields to prompt the user for when enabling this plugin in assistant mode. Saved values are substituted into ${user_config.KEY} references in the mcpServers env.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"type":{"description":"Type of the configuration value","type":"string","enum":["string","number","boolean","directory","file"]},"title":{"description":"Human-readable label shown in the config dialog","type":"string"},"description":{"description":"Help text shown beneath the field in the config dialog","type":"string"},"required":{"description":"If true, validation fails when this field is empty","type":"boolean"},"default":{"description":"Default value used when the user provides nothing","anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]},"multiple":{"description":"For string type: allow an array of strings","type":"boolean"},"sensitive":{"description":"If true, masks dialog input and stores value in secure storage (keychain/credentials file) instead of settings.json","type":"boolean"},"min":{"description":"Minimum value (number type only)","type":"number"},"max":{"description":"Maximum value (number type only)","type":"number"}},"required":["type","title","description"],"additionalProperties":false}}},"required":["server"],"additionalProperties":false}},"mcpServers":{"anyOf":[{"description":"MCP servers to include in the plugin (in addition to those in the .mcp.json file, if it exists)","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.json$"}]},{"description":"Path or URL to MCPB file containing MCP server configuration","anyOf":[{"description":"Path to MCPB file relative to plugin root","type":"string","pattern":"^\\.\\/.*"},{"description":"URL to MCPB file","type":"string","format":"uri"}]},{"description":"MCP server configurations keyed by server name","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"stdio"},"command":{"type":"string","minLength":1},"args":{"default":[],"type":"array","items":{"type":"string"}},"env":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["command"]},{"type":"object","properties":{"type":{"type":"string","const":"sse"},"url":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"headersHelper":{"type":"string"},"oauth":{"type":"object","properties":{"clientId":{"type":"string"},"callbackPort":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"authServerMetadataUrl":{"type":"string","format":"uri","pattern":"^https:\\/\\/.*"},"scopes":{"type":"string","minLength":1},"xaa":{"type":"boolean"}}}},"required":["type","url"]},{"type":"object","properties":{"type":{"type":"string","const":"http"},"url":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"headersHelper":{"type":"string"},"oauth":{"type":"object","properties":{"clientId":{"type":"string"},"callbackPort":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"authServerMetadataUrl":{"type":"string","format":"uri","pattern":"^https:\\/\\/.*"},"scopes":{"type":"string","minLength":1},"xaa":{"type":"boolean"}}}},"required":["type","url"]},{"type":"object","properties":{"type":{"type":"string","const":"ws"},"url":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"headersHelper":{"type":"string"}},"required":["type","url"]}]}},{"description":"Array of MCP server configurations (paths, MCPB files, or inline definitions)","type":"array","items":{"anyOf":[{"description":"Path to MCP servers configuration file","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.json$"}]},{"description":"Path or URL to MCPB file","anyOf":[{"description":"Path to MCPB file relative to plugin root","type":"string","pattern":"^\\.\\/.*"},{"description":"URL to MCPB file","type":"string","format":"uri"}]},{"description":"Inline MCP server configurations","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","const":"stdio"},"command":{"type":"string","minLength":1},"args":{"default":[],"type":"array","items":{"type":"string"}},"env":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}}},"required":["command"]},{"type":"object","properties":{"type":{"type":"string","const":"sse"},"url":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"headersHelper":{"type":"string"},"oauth":{"type":"object","properties":{"clientId":{"type":"string"},"callbackPort":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"authServerMetadataUrl":{"type":"string","format":"uri","pattern":"^https:\\/\\/.*"},"scopes":{"type":"string","minLength":1},"xaa":{"type":"boolean"}}}},"required":["type","url"]},{"type":"object","properties":{"type":{"type":"string","const":"http"},"url":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"headersHelper":{"type":"string"},"oauth":{"type":"object","properties":{"clientId":{"type":"string"},"callbackPort":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"authServerMetadataUrl":{"type":"string","format":"uri","pattern":"^https:\\/\\/.*"},"scopes":{"type":"string","minLength":1},"xaa":{"type":"boolean"}}}},"required":["type","url"]},{"type":"object","properties":{"type":{"type":"string","const":"ws"},"url":{"type":"string"},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"headersHelper":{"type":"string"}},"required":["type","url"]}]}}]}}]},"lspServers":{"anyOf":[{"description":"Path to .lsp.json configuration file relative to plugin root","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.json$"}]},{"description":"LSP server configurations keyed by server name","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"command":{"description":"Command to execute the LSP server (e.g., \"typescript-language-server\")","type":"string","minLength":1},"args":{"description":"Command-line arguments to pass to the server","type":"array","items":{"type":"string","minLength":1}},"extensionToLanguage":{"description":"Mapping from file extension to LSP language ID. File extensions and languages are derived from this mapping.","type":"object","propertyNames":{"type":"string","minLength":2},"additionalProperties":{"type":"string","minLength":1}},"transport":{"description":"Communication transport mechanism","default":"stdio","type":"string","enum":["stdio","socket"]},"env":{"description":"Environment variables to set when starting the server","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"initializationOptions":{"description":"Initialization options passed to the server during initialization"},"settings":{"description":"Settings passed to the server via workspace/didChangeConfiguration"},"workspaceFolder":{"description":"Workspace folder path to use for the server","type":"string"},"startupTimeout":{"description":"Maximum time to wait for server startup (milliseconds)","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"shutdownTimeout":{"description":"Maximum time to wait for graceful shutdown (milliseconds)","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"restartOnCrash":{"description":"Whether to restart the server if it crashes","type":"boolean"},"maxRestarts":{"description":"Maximum number of restart attempts before giving up","type":"integer","minimum":0,"maximum":9007199254740991}},"required":["command","extensionToLanguage"],"additionalProperties":false}},{"description":"Array of LSP server configurations (paths or inline definitions)","type":"array","items":{"anyOf":[{"description":"Path to LSP configuration file","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.json$"}]},{"description":"Inline LSP server configurations","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","properties":{"command":{"description":"Command to execute the LSP server (e.g., \"typescript-language-server\")","type":"string","minLength":1},"args":{"description":"Command-line arguments to pass to the server","type":"array","items":{"type":"string","minLength":1}},"extensionToLanguage":{"description":"Mapping from file extension to LSP language ID. File extensions and languages are derived from this mapping.","type":"object","propertyNames":{"type":"string","minLength":2},"additionalProperties":{"type":"string","minLength":1}},"transport":{"description":"Communication transport mechanism","default":"stdio","type":"string","enum":["stdio","socket"]},"env":{"description":"Environment variables to set when starting the server","type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"}},"initializationOptions":{"description":"Initialization options passed to the server during initialization"},"settings":{"description":"Settings passed to the server via workspace/didChangeConfiguration"},"workspaceFolder":{"description":"Workspace folder path to use for the server","type":"string"},"startupTimeout":{"description":"Maximum time to wait for server startup (milliseconds)","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"shutdownTimeout":{"description":"Maximum time to wait for graceful shutdown (milliseconds)","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"restartOnCrash":{"description":"Whether to restart the server if it crashes","type":"boolean"},"maxRestarts":{"description":"Maximum number of restart attempts before giving up","type":"integer","minimum":0,"maximum":9007199254740991}},"required":["command","extensionToLanguage"],"additionalProperties":false}}]}}]},"monitors":{"description":"Background watch scripts the host arms as persistent Monitor tasks (unsandboxed, same trust tier as hooks) so plugins need not instruct the model to arm them. When omitted, monitors/monitors.json at the plugin root is loaded if present.","anyOf":[{"description":"Path to a JSON file containing the monitors array, relative to the plugin root","type":"string","allOf":[{"type":"string","pattern":"^\\.\\/.*"},{"type":"string","pattern":".*\\.json$"}]},{"type":"array","items":{"type":"object","properties":{"name":{"description":"Identifier for this monitor, unique within the plugin. Used to dedupe so re-arming (plugin reload, repeat skill invoke) does not spawn duplicates.","type":"string","minLength":1},"command":{"description":"Shell command to run as a persistent background monitor. Each stdout line is delivered to the model as a <task_notification> event; the process runs for the session lifetime. ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}, ${user_config.*}, and ${ENV_VAR} are substituted. Runs in the session cwd — prefix with `cd \"${CLAUDE_PLUGIN_ROOT}\" && ` if the script needs its own directory.","type":"string","minLength":1},"description":{"description":"Short human-readable description of what is being monitored (shown in task panel and notification summary).","type":"string","minLength":1},"when":{"description":"Arm trigger. \"always\" arms at session start and on plugin reload. \"on-skill-invoke:<skill>\" arms the first time that skill is dispatched (via Skill tool or slash command).","default":"always","anyOf":[{"type":"string","const":"always"},{"type":"string","pattern":"^on-skill-invoke:.*"}]}},"required":["name","command","description"],"additionalProperties":false}}]},"settings":{"description":"Settings to merge into the user settings while this plugin is enabled. Only the documented allowlisted keys are applied.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"userConfig":{"description":"User-configurable values this plugin needs. Prompted at enable time. Non-sensitive values saved to settings.json; sensitive values to secure storage. Available as ${user_config.KEY} in MCP/LSP server config, hook commands, and (non-sensitive only) skill/agent content. Keep sensitive value counts small.","type":"object","propertyNames":{"type":"string","pattern":"^[A-Za-z_]\\w*$"},"additionalProperties":{"type":"object","properties":{"type":{"description":"Type of the configuration value","type":"string","enum":["string","number","boolean","directory","file"]},"title":{"description":"Human-readable label shown in the config dialog","type":"string"},"description":{"description":"Help text shown beneath the field in the config dialog","type":"string"},"required":{"description":"If true, validation fails when this field is empty","type":"boolean"},"default":{"description":"Default value used when the user provides nothing","anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string"}}]},"multiple":{"description":"For string type: allow an array of strings","type":"boolean"},"sensitive":{"description":"If true, masks dialog input and stores value in secure storage (keychain/credentials file) instead of settings.json","type":"boolean"},"min":{"description":"Minimum value (number type only)","type":"number"},"max":{"description":"Maximum value (number type only)","type":"number"}},"required":["type","title","description"],"additionalProperties":false}}},"required":["name"],"title":"Claude Code Plugin Manifest","description":"Manifest (.claude-plugin/plugin.json) for a Claude Code plugin. Learn more: https://code.claude.com/docs/en/plugins-reference"}