Skip to content

Latest commit

 

History

History
144 lines (111 loc) · 6.26 KB

File metadata and controls

144 lines (111 loc) · 6.26 KB
aliases
Plugins

Plugins

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.

What a plugin contains

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

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"]

Installation

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.

How plugins load

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.

The CLAUDE_PLUGIN_ROOT variable

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.

How it maps to the API

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.

Developer takeaway

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]]