Plugin Maker
Create discoverable Claude Code plugins that bundle commands, agents, skills, hooks, and MCP configurations.
Core Principles
- •Plugins bundle components: A plugin is a container for related commands, agents, skills, hooks, and MCP configs
- •Manifest-driven discovery: The
.claude-plugin/plugin.jsonfile makes the plugin discoverable - •Convention over configuration: Standard directory names enable automatic component discovery
- •Plugins vs Skills: Use plugins when bundling multiple component types; use standalone skills for single capabilities
Plugin Structure
Warning: Do not place
plugin.jsondirectly in the plugin directory. It must be inside the.claude-plugin/subdirectory for the plugin to be discovered.
my-plugin/ ├── .claude-plugin/ │ └── plugin.json # Required: manifest file (MUST be here) ├── README.md # Recommended: documentation ├── commands/ # Slash commands (*.md) │ ├── my-command.md │ └── help.md ├── agents/ # Subagent definitions (*.md) │ └── my-agent.md ├── skills/ # Skills (subdirs with SKILL.md) │ └── my-skill/ │ └── SKILL.md ├── hooks/ # Hook configurations │ ├── hooks.json │ └── handler.py ├── .mcp.json # MCP server configuration └── .lsp.json # LSP server configuration
Quick Template: plugin.json
Every plugin requires .claude-plugin/plugin.json:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "Brief description of what this plugin does"
}
Optional author field for attribution:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "Brief description of what this plugin does",
"author": {
"name": "Your Name",
"email": "you@example.com"
}
}
Creating a Plugin
Step 1: Create Directory Structure
mkdir -p ./my-plugin/.claude-plugin mkdir -p ./my-plugin/commands
Step 2: Create plugin.json
Create .claude-plugin/plugin.json with required fields:
{
"name": "my-plugin",
"description": "What this plugin does"
}
Step 3: Add Components
Add the components your plugin needs (see Component Quick Reference below).
Step 4: Test with --plugin-dir
Use the --plugin-dir flag to test your plugin without installing it:
claude --plugin-dir ./my-plugin
This loads your plugin for the current session only, allowing rapid iteration.
Step 5: Validate Structure
# Check manifest exists and is valid JSON cat ./my-plugin/.claude-plugin/plugin.json | jq . # List all components ls -la ./my-plugin/
Step 6: Test Discovery
Ask Claude to use your plugin's commands or agents to verify discovery works.
Component Quick Reference
Commands (commands/*.md)
Slash commands users invoke explicitly. Plugin commands are namespaced as /plugin-name:command-name.
--- description: What this command does argument-hint: [optional-args] allowed-tools: ["Read", "Write", "Bash"] --- # Command Name Instructions for Claude when this command is invoked. The user's input is available as $ARGUMENTS. **Advanced argument access:** - `$ARGUMENTS` - Full argument string - `$1`, `$2`, `$3` - Individual arguments (space-separated)
Fields:
| Field | Required | Description |
|---|---|---|
description | Yes | Shown in /help and command completion |
argument-hint | No | Hint text for arguments (e.g., [file-path]) |
allowed-tools | No | Restrict available tools (JSON array) |
disable-model-invocation | No | If true, only explicit /command triggers it |
model | No | Override model: inherit, sonnet, opus, haiku |
Agents (agents/*.md)
Specialized subagents for parallel or delegated work.
--- name: my-agent description: Use this agent when analyzing code for security issues. Examples: <example>Context: User asks about security\nuser: "Check this file for vulnerabilities"\nassistant: "I'll analyze with the security agent"</example> model: sonnet color: yellow tools: ["Read", "Grep", "Glob"] --- You are an expert at [specific task]. ## Your Role Detailed instructions for the agent...
Fields:
| Field | Required | Description |
|---|---|---|
name | Yes | Agent identifier (lowercase, hyphens) |
description | Yes | When to use. Include Examples tags: <example>Context: ...\nuser: "..."\nassistant: "..."</example> |
model | No | inherit, sonnet, opus, haiku |
color | No | Visual indicator: yellow, blue, green, etc. |
tools | No | Array of available tools |
Triggering Tip: Use <example> tags in descriptions for complex use cases. Include context, user message, and assistant response to guide invocation.
Skills (skills/skill-name/SKILL.md)
Model-invoked capabilities that Claude activates based on context. Plugin skills are namespaced as /plugin-name:skill-name.
--- name: my-skill description: What this skill does. Use when user mentions [trigger terms]. --- # Skill Name Instructions...
Hooks (hooks/hooks.json)
Event-driven automation scripts. Use for validation, context injection, and workflow automation.
Hook Types:
- •Prompt-based (recommended): LLM-driven decisions with
"type": "prompt" - •Command-based: Bash scripts with
"type": "command"
{
"hooks": {
"PreToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "prompt",
"prompt": "Validate file write safety. Check: path traversal, credentials. Return 'approve' or 'deny'."
}]
}],
"Stop": [{
"matcher": "*",
"hooks": [{
"type": "prompt",
"prompt": "Verify task completion: tests run, build succeeded. Return 'approve' or 'block'."
}]
}]
}
}
Available Events:
| Event | Trigger |
|---|---|
PreToolUse | Before any tool executes |
PostToolUse | After a tool executes |
UserPromptSubmit | When user submits a prompt |
Stop | When Claude wants to stop |
SubagentStop | When subagent wants to stop |
SessionStart | Session begins |
SessionEnd | Session ends |
PreCompact | Before context compaction |
Notification | User notification sent |
Important: Use ${CLAUDE_PLUGIN_ROOT} for paths in hook commands.
See Hook Development Guide for comprehensive patterns.
MCP Configuration (.mcp.json)
Integrate Model Context Protocol servers for additional tools:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/mcp-server/index.js"],
"env": {
"NODE_ENV": "production"
}
}
}
}
Server types: stdio, SSE, HTTP, WebSocket. Tools appear as mcp__plugin-name__tool-name.
Plugin Settings (.claude/plugin-name.local.md)
Store per-project configuration with YAML frontmatter:
--- enabled: true strict_mode: false max_retries: 3 --- # Plugin Configuration Settings documentation here.
Usage:
- •Read from hooks, commands, and agents
- •Control plugin behavior per-project
- •Store state and configuration
- •Should be in
.gitignore
See Plugin Settings Guide for parsing techniques and patterns.
LSP Configuration (.lsp.json)
Configure Language Server Protocol servers for enhanced editor support:
{
"lspServers": {
"my-lsp": {
"command": "my-language-server",
"args": ["--stdio"],
"filetypes": ["mylang"]
}
}
}
Fields:
| Field | Required | Description |
|---|---|---|
command | Yes | The LSP server executable |
args | No | Command-line arguments |
filetypes | Yes | File extensions to activate for |
Plugin Locations
| Location | Purpose |
|---|---|
--plugin-dir ./path | Development/testing (primary workflow) |
~/.claude/plugins/ | Personal plugins (installed) |
.claude/plugins/ | Project plugins (committed to git) |
When to Create a Plugin
Standalone Skill vs Plugin Comparison
| Feature | Standalone Skill | Plugin |
|---|---|---|
| Simplest option | One SKILL.md file | Multiple files/directories |
| Commands | No | Yes |
| Multiple skills | No | Yes |
| Agents | No | Yes |
| Hooks | No | Yes |
| MCP servers | No | Yes |
| LSP servers | No | Yes |
| Namespacing | None | /plugin-name:* |
| Distribution | Copy file | Package directory |
Create a plugin when:
- •You need multiple component types (commands + agents, skills + hooks, etc.)
- •You want to bundle and distribute related functionality
- •Your team needs shared tooling with consistent behavior
Don't create a plugin when:
- •You only need a single skill (use standalone skill instead)
- •You only need a single command (consider a skill or CLAUDE.md instruction)
- •The functionality is project-specific and simple
Naming Conventions
| Item | Convention | Example |
|---|---|---|
| Plugin directory | lowercase-hyphenated | my-plugin |
| plugin.json name | matches directory | "name": "my-plugin" |
| Commands directory | plural commands/ | not command/ |
| Agents directory | plural agents/ | not agent/ |
| Skills directory | plural skills/ | not skill/ |
| Hooks directory | singular hooks/ | with hooks.json inside |
Quick Reference
Create:
mkdir -p ./my-plugin/.claude-plugin
Test during development:
claude --plugin-dir ./my-plugin
Validate manifest:
cat ./my-plugin/.claude-plugin/plugin.json | jq .
Install plugin:
cp -r ./my-plugin ~/.claude/plugins/
List installed plugins:
ls ~/.claude/plugins/*/ ls .claude/plugins/*/
Additional Resources
- •Hook Development Guide - Events, prompt/command hooks, security patterns
- •Plugin Settings Guide - Configuration files with YAML frontmatter
- •Validation checklists
- •Complete plugin examples
- •Common mistakes
- •Copy-paste templates