This skill should be used when creating plugins, publishing to marketplaces, or when "plugin.json", "marketplace", "create plugin", or "distribute plugin" are mentioned.
Complete lifecycle for developing, validating, and distributing Claude Code plugins.
plugin.jsonoutfitter:claude-commands skilloutfitter:claude-agents skilloutfitter:claude-hooks skilloutfitter:skills-dev skilloutfitter:claude-plugin-audit skill for validation# 1. Scaffold plugin
./scripts/scaffold-plugin.sh my-plugin --with-commands
# 2. Add components (commands, agents, hooks, skills)
# 3. Test locally
/plugin marketplace add ./my-plugin
/plugin install my-plugin@my-plugin
# 4. Distribute
git push origin main --tags
Discovery -> Init -> Components -> Validate -> Distribute -> Marketplace
| | | | | |
v v v v v v
Purpose Scaffold Commands Structure Package Catalog
Scope plugin.json Agents Testing Version Publish
Type README Hooks Quality Release Share
Before creating a plugin, clarify:
| Question | Impact |
|---|---|
| What problem does this solve? | Plugin scope and features |
| Who will use it? | Distribution method |
| What components are needed? | Commands, agents, hooks, MCP servers |
| Where will it live? | Personal, project, or marketplace |
Standalone plugins need their own .claude-plugin/plugin.json:
my-plugin/
āāā .claude-plugin/
ā āāā plugin.json # Required for standalone
āāā README.md # Required for distribution
āāā commands/ # Optional components
āāā agents/
āāā skills/
āāā hooks/
{
"name": "my-plugin",
"version": "1.0.0",
"description": "Brief description of what this plugin does",
"author": {
"name": "Your Name",
"email": "you@example.com"
},
"license": "MIT"
}
For marketplaces where all plugins live in the same repo, use strict: false to consolidate metadata. Plugins don't need their own manifests:
my-marketplace/
āāā .claude-plugin/
ā āāā marketplace.json # All metadata here (strict: false)
āāā plugin-a/
ā āāā commands/
āāā plugin-b/
ā āāā skills/
āāā README.md
{
"name": "my-marketplace",
"owner": {
"name": "Team Name",
"email": "team@example.com"
},
"strict": false,
"plugins": [
{"name": "plugin-a", "source": "./plugin-a", "version": "1.0.0", "description": "Plugin A", "license": "MIT"},
{"name": "plugin-b", "source": "./plugin-b", "version": "1.0.0", "description": "Plugin B", "license": "MIT"}
]
}
Benefits: Single source of truth, no version drift between marketplace and plugin manifests.
For external plugins (GitHub repos), use minimal entries and let the external repo own its manifest.
See structure.md for complete plugin.json schema.
Add components based on plugin needs. See Steps section for which skills to load.
Create custom commands in commands/ directory:
---
description: "Review code for quality issues"
---
Review the following code: {{0}}
Check for: code style, bugs, performance, security
For complex commands, load the outfitter:claude-commands skill.
Define specialized agents in agents/ directory:
---
name: security-reviewer
description: "Security-focused code reviewer"
---
You are a security expert. When reviewing code:
1. Check for vulnerabilities
2. Verify input validation
3. Report issues with severity levels
For agent design patterns, load the outfitter:claude-agents skill.
Two ways to define hooks:
File-based (auto-discovered from hooks/hooks.json):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{"type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"}]
}
]
}
}
Inline in plugin.json - same structure, add "hooks" key directly.
Hook types: PreToolUse, PostToolUse, UserPromptSubmit, Stop, SessionStart, SessionEnd
For hook implementation, load the outfitter:claude-hooks skill. See structure.md for hook JSON format and script interface.
Add reusable methodology patterns in skills/ directory. For skill authoring, load the outfitter:skills-dev skill.
{
"mcpServers": {
"my-server": {
"command": "${CLAUDE_PLUGIN_ROOT}/servers/my-server",
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
"env": {"API_KEY": "${MY_API_KEY}"}
}
}
}
Path variables: ${CLAUDE_PLUGIN_ROOT} (plugin directory), ${VAR_NAME} (env var)
When plugins are installed, Claude Code copies them to a cache directory. This has implications:
../../shared/file.md will not work after installplugin:skill-name) instead of file referencesSee caching.md for workarounds and best practices.
Before distribution, validate the plugin.
Structure:
strict: falseComponents:
chmod +x)Documentation:
# Add as local marketplace
/plugin marketplace add ./my-plugin
# Install and test
/plugin install my-plugin@my-plugin
# Test commands
/my-command arg1 arg2
See structure.md for validation commands and detailed component schemas.
Follow semver (MAJOR.MINOR.PATCH):
# 1. Update version in plugin.json
# 2. Update CHANGELOG.md
# 3. Commit and tag
git add plugin.json CHANGELOG.md
git commit -m "chore: release v1.0.0"
git tag v1.0.0
git push origin main --tags
# 4. Create GitHub release
gh release create v1.0.0 --title "v1.0.0" --notes "Initial release"
| Method | Best For | Setup |
|---|---|---|
| GitHub repo | Public/team plugins | Push to GitHub |
| Git URL | GitLab, Bitbucket | Full URL in source |
| Local path | Development/testing | Relative path |
See distribution.md for packaging, CI/CD, and release automation.
A marketplace catalogs plugins for discovery and installation.
Create .claude-plugin/marketplace.json:
{
"name": "my-marketplace",
"owner": {"name": "Team Name", "email": "team@example.com"},
"plugins": [
{"name": "my-plugin", "source": "./plugins/my-plugin"}
]
}
// Relative path
{"source": "./plugins/my-plugin"}
// GitHub
{"source": {"source": "github", "repo": "owner/plugin-repo", "ref": "v1.0.0"}}
// Git URL
{"source": {"source": "url", "url": "https://gitlab.com/team/plugin.git"}}
/plugin marketplace add owner/repo # Add marketplace
/plugin marketplace list # List available
/plugin install plugin-name@marketplace # Install from marketplace
/plugin marketplace update marketplace # Update
See marketplace.md for full schema, team configuration, and hosting strategies.
dev-tools)review-pr)security-reviewer)Plugin not loading:
jq empty .claude-plugin/plugin.jsonstrict: false if no plugin.jsonCommands not appearing:
commands/ directoryHooks not executing:
chmod +xMCP servers failing:
~/Library/Logs/Claude/ALWAYS:
.claude-plugin/plugin.jsonstrict: false and consolidate metadata in marketplace.jsonNEVER:
../) for cross-plugin resources