| aliases |
|
|---|
A plugin is a directory. It bundles skills, commands, agents, hooks, and MCP server configs into one unit you can install and share. Every piece inside works exactly as described in earlier notes; the plugin just gives them a common address.
A plugin directory follows this layout:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # Manifest (only file inside .claude-plugin/)
├── commands/ # Slash commands (.md files)
├── agents/ # Sub-agent definitions (.md files)
├── skills/ # Skills (each in its own subdirectory)
│ └── skill-name/
│ └── SKILL.md
├── hooks/
│ └── hooks.json # Event handler config
├── .mcp.json # MCP server definitions
├── scripts/ # Helper scripts for hooks
└── LICENSE
One critical rule: component directories live at the plugin root. Only plugin.json goes inside .claude-plugin/. Put commands inside .claude-plugin/commands/ and they won't load.
The manifest is .claude-plugin/plugin.json. It declares metadata and tells Claude Code where to find each component type.
{
"name": "my-plugin",
"version": "1.0.0",
"description": "Brief explanation of what this does",
"author": {
"name": "Author Name",
"email": "author@example.com"
},
"commands": "./commands/",
"agents": "./agents/",
"skills": "./skills/",
"hooks": "./hooks/hooks.json",
"mcpServers": "./.mcp.json",
"lspServers": "./.lsp.json"
}Every path field is optional. If your plugin only provides commands, you only declare commands. The manifest also supports homepage, repository, license, and keywords fields for registry metadata.
Path values can be a string (single directory) or an array of strings (multiple paths or individual files):
"commands": ["./custom/commands/special.md"],
"agents": ["./agents", "./specialized-agents"]Two ways to get a plugin:
claude plugin install plugin-name # From marketplace
claude plugin install plugin-name@marketplace-name # Specific marketplace
The --scope flag controls where settings land:
| Scope | Config location | Who sees it |
|---|---|---|
user |
User-level settings | Only you |
project |
.claude/settings.json |
All project collaborators |
local |
Local settings | Only you, this project |
You can also point to a local directory during development. Validate your plugin structure with claude plugin validate.
At session start, Claude Code scans installed plugins and merges their contents into the session. There is no special "plugin runtime." Each component type loads through its existing mechanism:
| Plugin component | Loads as | Where it lands |
|---|---|---|
skills/ |
[[04.2 Skill Anatomy | Skill]] text |
commands/ |
[[04.3 Command Anatomy | Command]] definitions |
agents/ |
[[03.3 Agent Anatomy | Sub-agent]] definitions |
hooks/ |
[[05.5 Hook Anatomy | Hook]] handlers |
.mcp.json |
[[06.1 MCP Servers | MCP server]] configs |
lspServers |
LSP server configs | Language intelligence |
This is the key insight. A plugin does not introduce a new execution model. Skills from a plugin become system prompt text, identical to skills from .claude/skills/. MCP servers from a plugin populate the tools array, identical to servers from your project's .mcp.json. Hooks from a plugin run client-side, identical to hooks from .claude/settings.json.
Hooks inside a plugin need to reference scripts relative to the plugin directory, not the project. The environment variable ${CLAUDE_PLUGIN_ROOT} resolves to the plugin's installed location:
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/process.sh"
}
]
}
]
}
}Without this, hook scripts break when the plugin is installed somewhere other than where it was developed.
A plugin adds nothing new to the API call. It is purely a distribution and organization mechanism on the client side.
+-------------------+ +----------------------------+
| plugin.json | | API call (unchanged) |
+-------------------+ +----------------------------+
| skills/ --------->|----->| system prompt text |
| commands/ ------->|----->| system prompt instructions |
| agents/ --------->|----->| system prompt definitions |
| .mcp.json ------->|----->| tools[] array entries |
| hooks/ ---------->|--X | (never reaches the API) |
+-------------------+ +----------------------------+
Hooks are the exception. They execute on the client before or after tool use and never appear in any API call. Everything else gets flattened into the same system prompt and tools array you would build manually.
A plugin is a zip-friendly directory with a manifest. If you already know how to write a [[04.1 Skills vs Commands|skill, a command]], a [[05.4 Hooks|hook]], or configure an [[06.1 MCP Servers|MCP server]], you know how to write a plugin. The manifest just tells Claude Code where to find each piece. See [[06.3 Plugin Anatomy|Plugin Anatomy]] for a complete walkthrough of building one.
Previous: [[06.1 MCP Servers|MCP Servers]] | Next: [[06.3 Plugin Anatomy|Plugin Anatomy]] Tags: #core #architecture Related: [[04.2 Skill Anatomy|Skill Anatomy]] | [[04.3 Command Anatomy|Command Anatomy]] | [[05.5 Hook Anatomy|Hook Anatomy]] | [[06.1 MCP Servers|MCP Servers]]