| title |
aliases |
tags |
sources |
created |
updated |
| Creating Claude Code Plugins |
| claude-code-plugins |
| plugin-authoring |
| claude-plugins |
|
| claude-code |
| plugins |
| skills |
| agents |
| hooks |
| mcp |
| extensibility |
|
|
2026-04-17 |
2026-04-17 |
Creating Claude Code Plugins
Plugins package skills, agents, hooks, MCP servers, LSP servers, and background monitors into a shareable, versioned unit. They are the distribution mechanism for Claude Code extensions.
Standalone Config vs. Plugins
| Approach |
Skill names |
Best for |
Standalone (.claude/ dir) |
/hello |
Personal workflows, single-project, quick experiments |
Plugin (dir with .claude-plugin/plugin.json) |
/my-plugin:hello |
Team sharing, multi-project reuse, marketplace distribution |
- Start standalone → convert to plugin when ready to share
- Plugins namespace skill names (
/plugin-name:skill) to prevent conflicts
Plugin Directory Structure
my-plugin/
├── .claude-plugin/
│ └── plugin.json ← manifest (ONLY file inside .claude-plugin/)
├── skills/
│ └── code-review/
│ └── SKILL.md
├── commands/ ← legacy flat .md skills (use skills/ for new)
├── agents/ ← custom agent definitions
├── hooks/
│ └── hooks.json
├── monitors/
│ └── monitors.json
├── bin/ ← executables added to PATH
├── .mcp.json ← MCP server configs
├── .lsp.json ← LSP server configs
└── settings.json ← default settings when plugin enabled
Critical mistake to avoid: Never put skills/, agents/, hooks/, or commands/ inside .claude-plugin/. Only plugin.json lives there.
Plugin Components
Skills
- Add
skills/<name>/SKILL.md at plugin root
- Include
description: in frontmatter so Claude knows when to invoke
- Model-invoked automatically based on task context
- Run
/reload-plugins after changes
---
description: Reviews code for best practices. Use when reviewing PRs or analyzing code quality.
---
When reviewing code, check for:
1. Error handling
2. Security concerns
3. Test coverage
LSP Servers
- Add
.lsp.json at plugin root for language intelligence
- Users must have the language server binary installed
- Use pre-built marketplace LSP plugins for common languages (TS, Python, Rust)
{
"go": {
"command": "gopls",
"args": ["serve"],
"extensionToLanguage": { ".go": "go" }
}
}
Background Monitors
- Add
monitors/monitors.json — array of monitor entries
- Each stdout line from
command is delivered to Claude as a notification
- Started automatically when plugin is active
[
{
"name": "error-log",
"command": "tail -F ./logs/error.log",
"description": "Application error log"
}
]
Default Settings
settings.json at plugin root applies config when plugin is enabled
- Supported keys:
agent, subagentStatusLine
- Setting
agent activates a plugin agent as the main thread
{ "agent": "security-reviewer" }
Testing Locally
# Load one plugin
claude --plugin-dir ./my-plugin
# Load multiple plugins
claude --plugin-dir ./plugin-one --plugin-dir ./plugin-two
- Local
--plugin-dir takes precedence over installed marketplace plugins of the same name
- Run
/reload-plugins during development to pick up changes without restart
- Test skills:
/plugin-name:skill-name | Check agents: /agents
Migrating from Standalone to Plugin
Standalone (.claude/) |
Plugin |
| Available in one project |
Shareable via marketplace |
commands/ in .claude/ |
commands/ at plugin root |
Hooks in settings.json |
hooks/hooks.json |
| Manual copy to share |
Install with /plugin install |
After migrating, remove original .claude/ files to avoid duplicates.
Distribution
- Add
README.md with install + usage instructions
- Use semantic versioning in
plugin.json
- Submit to official marketplace via
claude.ai/settings/plugins/submit or platform.claude.com/plugins/submit
- Distribute through a plugin marketplace (official or team-hosted)
Key Takeaways
- Plugin root structure: manifest in
.claude-plugin/plugin.json, everything else at root level
- Skills are model-invoked; slash commands are user-invoked — they live in different dirs (
skills/ vs commands/)
- Use
--plugin-dir for local testing; run /reload-plugins to hot-reload changes
- Background monitors run automatically and stream stdout lines to Claude as notifications
settings.json can activate a plugin agent as the default main-thread agent
- Start with standalone
.claude/ config, convert to plugin when ready to distribute
- Plugin skill names are always namespaced:
/plugin-name:skill-name
Related
Sources