Claude Code plugin.json Schema Reference
Complete reference for Claude Code plugin manifest files.
Minimal Valid plugin.json
For plugins using standard directory structures, this is all you need:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "Brief description of the plugin"
}
Auto-discovery will automatically load components from standard locations.
Complete Schema
{
"name": "plugin-name",
"version": "1.2.0",
"description": "Brief plugin description",
"author": {
"name": "Author Name",
"email": "author@example.com",
"url": "https://github.com/author"
},
"homepage": "https://docs.example.com/plugin",
"repository": "https://github.com/author/plugin",
"license": "MIT",
"keywords": ["keyword1", "keyword2"],
"commands": "./custom/commands/",
"agents": "./custom/agents/",
"skills": "./custom/skills/",
"hooks": "./config/hooks.json",
"mcpServers": "./mcp-config.json",
"outputStyles": "./styles/",
"lspServers": "./.lsp.json"
}
Field Reference
Required Fields
| Field | Type | Description |
|---|---|---|
name | string | Unique identifier, kebab-case, max 64 chars |
version | string | Semantic version (x.y.z) |
description | string | Brief explanation of the plugin |
Optional Metadata Fields
| Field | Type | Description |
|---|---|---|
author | object | {name, email?, url?} |
homepage | string | Documentation URL |
repository | string | Source code URL |
license | string | License identifier (MIT, Apache-2.0, etc.) |
keywords | array | Discovery tags (strings) |
Component Path Fields
| Field | Type | Auto-Discovery Location |
|---|---|---|
commands | string | array | commands/ |
agents | string | array | agents/ |
skills | string | array | skills/ |
hooks | string | object | hooks/hooks.json |
mcpServers | string | object | .mcp.json |
lspServers | string | object | .lsp.json |
outputStyles | string | array | (none) |
Auto-Discovery
Claude Code automatically loads components from standard directories without needing explicit paths in plugin.json:
my-plugin/ ├── .claude-plugin/ │ └── plugin.json # Only manifest required here ├── commands/ # Auto-discovered: all .md files ├── agents/ # Auto-discovered: all .md files ├── skills/ # Auto-discovered: subdirs with SKILL.md ├── hooks/ │ └── hooks.json # Auto-discovered ├── .mcp.json # Auto-discovered └── .lsp.json # Auto-discovered
Key insight: If using standard directories, omit the fields entirely from plugin.json. Explicit paths are only needed for non-standard locations.
When to Use Explicit Paths
Use explicit paths only when components are in non-standard locations:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "Plugin with custom paths",
"commands": "./src/custom-commands/",
"agents": ["./ai/agents/reviewer.md", "./ai/agents/tester.md"],
"hooks": "./config/hooks.json"
}
Custom paths supplement (don't replace) auto-discovered components.
Path Format Rules
Correct Path Formats
// Directory path "commands": "./custom/commands/" // Single file path "hooks": "./config/hooks.json" // Array of paths "agents": ["./agents/agent1.md", "./agents/agent2.md"]
Invalid Path Formats (Will Cause Validation Errors)
// WRONG: Missing leading ./ "commands": "commands/" // WRONG: Absolute path "commands": "/Users/me/plugins/commands/" // WRONG: Path traversal (../) "commands": "../shared/commands/" // WRONG: Relative to plugin.json location "commands": "../commands"
Inline Configuration
hooks, mcpServers, and lspServers can be inline objects instead of file paths:
Inline Hooks
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh"
}
]
}
]
}
}
Inline MCP Servers
{
"mcpServers": {
"database": {
"command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"]
}
}
}
Common Validation Errors
"hooks: Invalid input"
- •Cause: Using path traversal (
../) or wrong type - •Fix: Use
./hooks/hooks.jsonor omit field for auto-discovery
"commands: Invalid input"
- •Cause: Wrong path format or invalid type
- •Fix: Use string (
"./commands/") or array (["./cmd.md"]), or omit for auto-discovery
"agents: Invalid input"
- •Cause: Wrong path format, often using object instead of string/array
- •Fix: Use string (
"./agents/") or array (["./agent.md"]), or omit for auto-discovery
General Validation Failures
- •Check all paths start with
./ - •Remove component fields if using standard directories
- •Verify no path traversal (
../) - •Ensure arrays contain only strings (paths)
Best Practices
- •Prefer minimal manifests - Only specify what's non-standard
- •Use auto-discovery - Put components in standard directories
- •Avoid explicit paths for standard locations - Don't add
"commands": "./commands"if that's the default - •Use
${CLAUDE_PLUGIN_ROOT}- In hook scripts for portable paths - •Validate before publishing - Run
claude plugin validate /path/to/plugin
Directory Structure Template
my-plugin/
├── .claude-plugin/
│ └── plugin.json # Minimal manifest
├── README.md # Plugin documentation
├── commands/ # Slash commands (auto-discovered)
│ ├── deploy.md
│ └── status.md
├── agents/ # Agents (auto-discovered)
│ └── reviewer.md
├── skills/ # Skills (auto-discovered)
│ └── analysis/
│ └── SKILL.md
├── hooks/ # Hooks (auto-discovered)
│ ├── hooks.json
│ └── scripts/
│ └── post-edit.py
└── scripts/ # Shared scripts
└── utils.py
Debugging
# Validate plugin structure claude plugin validate /path/to/plugin # Debug mode for detailed loading info claude --debug # Check what components are loaded claude /help # Lists available commands from plugins