Claude-skill-registry claude-code-plugin-development
This skill should be used when the user asks to "create a plugin", "build a plugin", "write a plugin", or wants to bundle agents, hooks, commands, skills, or MCP servers into a distributable Claude Code plugin.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/claude-code-plugin-development" ~/.claude/skills/majiayu000-claude-skill-registry-claude-code-plugin-development && rm -rf "$T"
skills/data/claude-code-plugin-development/SKILL.mdClaude Code Plugin Development
Create distributable plugins that bundle commands, agents, skills, hooks, MCP servers, and LSP servers.
Official docs: https://code.claude.com/docs/en/plugins-reference
Quick Reference
You MUST read these references for detailed schemas and examples:
- Plugin Manifest - Complete plugin.json schema
- Plugin Components - Commands, agents, skills, hooks, MCP, LSP
- CLI Commands - Install, uninstall, enable, disable, update
- Debugging - Common issues and troubleshooting
Plugin Structure
my-plugin/ ├── .claude-plugin/ │ └── plugin.json # Required manifest ├── commands/ # Slash commands (.md files) ├── agents/ # Subagents (.md files) ├── skills/ # Skills (subdirs with SKILL.md) ├── hooks/ │ └── hooks.json # Hook configuration ├── .mcp.json # MCP server definitions ├── .lsp.json # LSP server configurations └── scripts/ # Hook and utility scripts
Important: Components go at plugin root, NOT inside
.claude-plugin/. Only plugin.json belongs in .claude-plugin/.
Marketplace Structure
A marketplace can contain multiple plugins. The marketplace root has its own
.claude-plugin/marketplace.json:
my-marketplace/ ├── .claude-plugin/ │ └── marketplace.json # Lists all plugins in this marketplace ├── plugins/ │ ├── plugin-a/ │ │ ├── .claude-plugin/ │ │ │ └── plugin.json │ │ └── skills/ │ └── plugin-b/ │ ├── .claude-plugin/ │ │ └── plugin.json │ └── commands/
marketplace.json
{ "name": "my-marketplace", "owner": { "name": "author-name" }, "plugins": [ { "name": "plugin-a", "source": "./plugins/plugin-a", "description": "First plugin description", "version": "1.0.0" }, { "name": "plugin-b", "source": "./plugins/plugin-b", "description": "Second plugin description", "version": "0.2.0" } ] }
Critical: When adding a new plugin to a marketplace:
- Add it to
or it won't be installablemarketplace.json - If using release-please, add a jsonpath entry to the config for the new plugin's version
Minimal plugin.json
{ "name": "my-plugin", "version": "1.0.0", "description": "Brief plugin description" }
Installation Scopes
| Scope | Location | Use case |
|---|---|---|
| user | | Personal plugins (default) |
| project | | Team plugins via version control |
| local | | Project-specific, gitignored |
| managed | | Read-only managed plugins |
Environment Variables
Use
${CLAUDE_PLUGIN_ROOT} for paths in hooks and MCP configs:
{ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh" }
Plugin Components Summary
| Component | Location | Format |
|---|---|---|
| Commands | | Markdown with frontmatter |
| Agents | | Markdown with frontmatter |
| Skills | | Directories with SKILL.md |
| Hooks | | JSON configuration |
| MCP servers | | MCP server config |
| LSP servers | | Language server config |
CLI Quick Reference
# Install claude plugin install <plugin>@<marketplace> --scope user # Manage claude plugin enable <plugin> claude plugin disable <plugin> claude plugin update <plugin> claude plugin uninstall <plugin> # Debug claude --debug
Permissions
Problem: Using
! backticks to run plugin scripts fails with permission error:
Error: Bash command permission check failed for pattern "!`${CLAUDE_PLUGIN_ROOT}/scripts/my-script.sh 2>&1 || true`": This Bash command contains multiple operations.
Cause:
! backticks have their own permission model separate from allowed-tools. Complex commands or scripts fail.
Solution: Use the Bash tool instead of
! backticks for scripts:
--- allowed-tools: Bash(${CLAUDE_PLUGIN_ROOT}/scripts/my-script.sh:*) --- Run the script: ```bash ${CLAUDE_PLUGIN_ROOT}/scripts/my-script.sh ```
Simple git commands still work with
! backticks: !git branch --show-current``
Common Issues
Plugin installed but commands don't appear?
The plugin may be disabled. Check
~/.claude/settings.json:
"enabledPlugins": { "my-plugin@my-marketplace": false // ← Disabled! }
Fix with:
claude plugin enable my-plugin@my-marketplace then restart Claude Code.
Local changes not picked up?
Use
claude plugin update <plugin> or do a full reinstall:
claude plugin marketplace remove my-marketplace claude plugin marketplace add ./ claude plugin install my-plugin@my-marketplace
Important
After creating or modifying plugins, inform the user:
Plugin changes take effect immediately after installation. Use
to verify plugin loading.claude --debug
Checklist
Before finalizing a plugin:
-
has name, version, descriptionplugin.json - Components at plugin root (not in
).claude-plugin/ - All paths use
variable${CLAUDE_PLUGIN_ROOT} - Scripts are executable (
)chmod +x - If part of a marketplace, plugin is listed in
marketplace.json - If using release-please, add jsonpath for new plugin version in config
- Test with
to verify loadingclaude --debug