Claude Code Plugins: The Complete Guide to Building and Sharing Extensions
Skills, agents, and hooks you add to .claude/ are powerful — but they are locked to one project. Every time you start a new repo you copy the same files, maintain them in multiple places, and drift out of sync. Claude Code plugins solve this: a plugin is a shareable, versioned package that carries all your customisations and can be installed in any project with one command.
This post covers what plugins are, when to use them, and how to build a real one from scratch — a DevOps helper that ships a deployment skill, a pre-deploy safety hook, and an MCP server connection to your Kubernetes cluster.
Plugins vs Standalone Configuration
Claude Code supports two ways to extend it:
| Approach | Skill names | Best for |
|---|---|---|
Standalone (.claude/ directory) | /deploy | One project, personal workflows, quick experiments |
| Plugins (separate directory with manifest) | /devops-helper:deploy | Sharing with team, multiple projects, versioned releases, marketplace distribution |
Start with standalone when you are iterating fast on a single project. Convert to a plugin when you want to share the same setup across projects or with teammates — or publish to the Anthropic marketplace.
The main trade-off is skill namespacing. Plugin skills are always prefixed with the plugin name (/devops-helper:deploy) to prevent conflicts when multiple plugins are installed. Standalone skills have no prefix (/deploy).
Plugin Structure
Every plugin is a directory with this layout:
devops-helper/
├── .claude-plugin/
│ └── plugin.json ← manifest (only file that goes in .claude-plugin/)
├── skills/
│ └── deploy/
│ └── SKILL.md ← skill definition
├── agents/
│ └── incident-responder.md
├── hooks/
│ └── hooks.json ← event hooks
├── .mcp.json ← MCP server config
├── monitors/
│ └── monitors.json ← background monitors
├── bin/ ← executables added to PATH
├── settings.json ← default settings applied when plugin is enabled
└── README.md
The critical rule: only plugin.json goes inside .claude-plugin/. Everything else — skills, agents, hooks — sits at the plugin root. This is the most common structural mistake.
What each component does
| Component | What it is |
|---|---|
skills/ | Skills Claude invokes automatically or you call with /plugin:skill-name |
agents/ | Subagent definitions for specialised parallel tasks |
hooks/ | Shell scripts that fire on lifecycle events (PreToolUse, PostToolUse, etc.) |
.mcp.json | MCP server config connecting Claude to external APIs and databases |
monitors/ | Background watchers (log tails, file watchers) that notify Claude as events arrive |
bin/ | Executables added to the Bash tool’s PATH during the session |
settings.json | Default settings applied when the plugin is enabled |
The Plugin Manifest
The manifest at .claude-plugin/plugin.json is the only required file:
{
"name": "devops-helper",
"description": "Deployment, Kubernetes, and incident-response tools for DevOps teams",
"version": "1.0.0",
"author": {
"name": "Your Name",
"email": "you@company.com"
},
"homepage": "https://github.com/your-org/devops-helper",
"repository": "https://github.com/your-org/devops-helper",
"license": "MIT"
}
| Field | Purpose |
|---|---|
name | Plugin identifier and skill namespace prefix |
description | Shown in the plugin manager when browsing |
version | Bump to trigger updates for installers. Omit to use git SHA |
author | Attribution — useful for marketplace listings |
homepage / repository | Links shown in the plugin manager |
Building a Real Plugin: DevOps Helper
Let’s build a plugin that DevOps teams can install across all their projects. It will include:
- A deploy skill — runs deployment with pre-flight checks
- A pre-deploy hook — blocks deploys to production without explicit confirmation
- A Kubernetes MCP server — gives Claude live cluster access
- A background log monitor — streams app errors to Claude automatically
Step 1: Create the structure
mkdir -p devops-helper/.claude-plugin
mkdir -p devops-helper/skills/deploy
mkdir -p devops-helper/skills/rollback
mkdir -p devops-helper/skills/incident-summary
mkdir -p devops-helper/hooks
mkdir -p devops-helper/agents
mkdir -p devops-helper/monitors
Step 2: Write the manifest
{
"name": "devops-helper",
"description": "Deployment safety, Kubernetes access, and incident response for DevOps teams",
"version": "1.0.0",
"author": {
"name": "DevOps Team"
}
}
Step 3: Create the deploy skill
<!-- devops-helper/skills/deploy/SKILL.md -->
---
description: >
Runs a deployment with pre-flight checks and rollback instructions.
Auto-invokes when the user asks to deploy, release, or push to production.
user-invocable: true
allowed-tools:
- Bash
- Read
---
# Deploy Skill
When the user asks to deploy, follow this sequence:
## 1. Read deployment config
Read `deploy.yaml` or `Makefile` to understand the deployment command. If neither exists, ask the user.
## 2. Pre-flight checks
Run these before any deploy:
```bash
# Check current branch
git branch --show-current
# Check for uncommitted changes
git status --porcelain
# Run tests
npm test --silent 2>&1 | tail -10
If tests fail or there are uncommitted changes, stop and report. Do not deploy.
3. Identify target environment
Parse $ARGUMENTS for the environment name (staging, production, etc.).
- Default to
stagingif none specified - If
productionis specified, ask the user to confirm: “Deploying to production. Type YES to confirm.”
4. Deploy
Run the deployment command. Stream output. Capture exit code.
5. Verify
After deploy, verify the service is healthy:
# Check rollout status (Kubernetes)
kubectl rollout status deployment/$SERVICE_NAME -n $NAMESPACE --timeout=120s
# Or check the health endpoint
curl -sf $HEALTH_URL || echo "Health check failed"
6. Report
Summarise: what was deployed, to which environment, any warnings, and the health check result. If deploy failed: run the rollback skill immediately and report what happened.
### Step 4: Create the rollback skill
```markdown
<!-- devops-helper/skills/rollback/SKILL.md -->
---
description: Rolls back the last deployment. Use when a deploy fails or causes issues.
user-invocable: true
allowed-tools:
- Bash
---
# Rollback Skill
## Steps
1. Identify the last stable deployment:
```bash
kubectl rollout history deployment/$SERVICE_NAME -n $NAMESPACE
- Roll back:
kubectl rollout undo deployment/$SERVICE_NAME -n $NAMESPACE
- Wait and verify:
kubectl rollout status deployment/$SERVICE_NAME -n $NAMESPACE --timeout=60s
- Report: whether rollback succeeded, which revision is now active, and recommend investigating what caused the failed deploy.
### Step 5: Create the incident summary skill
```markdown
<!-- devops-helper/skills/incident-summary/SKILL.md -->
---
description: >
Generates an incident summary from logs and recent changes.
Auto-invokes when the user mentions an incident, outage, or asks what went wrong.
user-invocable: true
allowed-tools:
- Bash
- Read
---
# Incident Summary Skill
Generate a structured incident summary. Collect:
1. **Timeline**: Run `git log --since="6 hours ago" --oneline` — what changed recently?
2. **Errors**: Read recent error logs from `logs/error.log` or run `kubectl logs --tail=100 -l app=$SERVICE`
3. **Impact**: Ask the user to describe impact if not obvious from logs
Write a summary in this format:
Incident Summary — [DATE]
Status: Ongoing / Resolved
Impact: [What broke, how many users affected]
Timeline:
- HH:MM — [event]
- HH:MM — [event]
Root cause: [One sentence]
Fix applied: [What was done]
Action items:
- [Follow-up task]
Keep it factual, under 300 words, suitable for a post-mortem or Slack channel update.
Step 6: Add a pre-deploy safety hook
The hook blocks deploys to production unless the user explicitly confirms. It intercepts the Bash tool and checks if the command matches a deploy pattern targeting production:
// devops-helper/hooks/hooks.json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "devops-helper/hooks/pre-deploy-check.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "devops-helper/hooks/log-commands.sh"
}
]
}
]
}
}
#!/bin/bash
# devops-helper/hooks/pre-deploy-check.sh
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
# Check for production deploy patterns
PROD_PATTERNS="prod|production|--env=prod"
if echo "$cmd" | grep -qiE "(deploy|release|kubectl apply|helm upgrade)" && \
echo "$cmd" | grep -qiE "$PROD_PATTERNS"; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "Production deployment detected. Confirm this is intentional before proceeding."
}
}'
exit 0
fi
exit 0
#!/bin/bash
# devops-helper/hooks/log-commands.sh
# Append every Bash command to an audit log
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
echo "[$ts] $cmd" >> "${AUDIT_LOG:-/tmp/claude-commands.log}"
exit 0
Step 7: Add a Kubernetes MCP server
The .mcp.json file at the plugin root connects Claude to your cluster:
{
"mcpServers": {
"kubernetes": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-kubernetes"],
"env": {
"KUBECONFIG": "${KUBECONFIG:-~/.kube/config}"
}
},
"pagerduty": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-server-pagerduty"],
"env": {
"PAGERDUTY_API_KEY": "${PAGERDUTY_API_KEY}"
}
}
}
}
With this in place, Claude can run kubectl commands, read pod logs, and check deployment status via MCP tools — without you manually setting up shell access.
Step 8: Add a background error log monitor
The monitor streams new error log lines to Claude during the session:
// devops-helper/monitors/monitors.json
[
{
"name": "app-errors",
"command": "tail -F logs/error.log 2>/dev/null || echo 'No error.log found'",
"description": "Application error log — new lines are delivered to Claude automatically"
}
]
Claude receives each new log line as a notification, letting it flag new errors without you having to ask.
Final plugin structure
devops-helper/
├── .claude-plugin/
│ └── plugin.json
├── skills/
│ ├── deploy/
│ │ └── SKILL.md
│ ├── rollback/
│ │ └── SKILL.md
│ └── incident-summary/
│ └── SKILL.md
├── hooks/
│ ├── hooks.json
│ ├── pre-deploy-check.sh
│ └── log-commands.sh
├── monitors/
│ └── monitors.json
├── .mcp.json
└── README.md
Testing Your Plugin
Test locally without installing using --plugin-dir:
# Load from directory
claude --plugin-dir ./devops-helper
# Load from a zip archive (Claude Code v2.1.128+)
claude --plugin-dir ./devops-helper.zip
# Load multiple plugins at once
claude --plugin-dir ./devops-helper --plugin-dir ./other-plugin
Inside the session, verify everything loaded:
# List skills
/help
# Test the deploy skill
/devops-helper:deploy staging
# Test the rollback skill
/devops-helper:rollback
# Check agents are visible
/agents
After making changes, reload without restarting:
/reload-plugins
If something does not work, check the structure first — the most common issue is placing skills/ or hooks/ inside .claude-plugin/ instead of the plugin root.
Installing Plugins
Once the plugin is in a git repository, anyone can install it:
# From GitHub
claude plugin add github:your-org/devops-helper
# From the official Anthropic marketplace
claude plugin add @anthropic/deploy-helper
# Project-scoped install (only active in this repo)
claude plugin add github:your-org/devops-helper --project
Managing installed plugins:
claude plugin list # see what's installed
claude plugin update github:your-org/devops-helper
claude plugin update --all # update everything
claude plugin remove github:your-org/devops-helper
Or use the in-app plugin manager:
/plugin
The /plugin command opens a browser with Discover, Installed, and Updates tabs.
Converting Existing Config to a Plugin
If you have skills and hooks in .claude/ already, migration is straightforward:
# 1. Create plugin structure
mkdir -p my-plugin/.claude-plugin
# 2. Write manifest
cat > my-plugin/.claude-plugin/plugin.json << 'EOF'
{
"name": "my-plugin",
"description": "Migrated from standalone .claude/ config",
"version": "1.0.0"
}
EOF
# 3. Copy existing components
cp -r .claude/skills my-plugin/
cp -r .claude/agents my-plugin/
cp -r .claude/commands my-plugin/
# 4. Migrate hooks
mkdir my-plugin/hooks
# Copy the hooks object from .claude/settings.json into my-plugin/hooks/hooks.json
What changes after migration:
| Before (standalone) | After (plugin) |
|---|---|
/deploy | /my-plugin:deploy |
| Copy files per project | claude plugin add github:you/my-plugin |
| Manual updates | claude plugin update --all |
| Only in one project | Available everywhere |
Publishing to the Anthropic Marketplace
When your plugin is ready to share publicly:
- Push to a public GitHub repository
- Add a
README.mdwith installation instructions and a usage guide - Submit via the in-app form:
- Claude.ai: Settings → Plugins → Submit
- Platform console: platform.claude.com/plugins/submit
Once listed, users can install with /plugin install your-plugin-name or claude plugin add @your-org/your-plugin.
For team-internal distribution, host the plugin in a private GitHub repo and configure the team marketplace URL in project settings — no public listing required.
When to Build a Plugin
flowchart TD
Q1{Do you need this\nacross multiple projects?} -->|Yes| Q2{Share with\nothers?}
Q1 -->|No| Standalone[Standalone .claude/ config]
Q2 -->|Yes| Plugin[Build a plugin]
Q2 -->|No| Q3{More than one\nproject?}
Q3 -->|Yes| Plugin
Q3 -->|No| Standalone
Build a plugin when:
- You want the same skills and hooks in every project without copying files
- You are building tools for a team and want them to install with one command
- You want version control over your tooling (bump
versionto push updates) - You want to publish to the Anthropic marketplace for the community
Stick with standalone when:
- The configuration is specific to one project and will never be reused
- You are experimenting and not sure if the skill is worth keeping
- You want short skill names without namespace prefixes
The practical path: build standalone first, convert to a plugin once the skill proves its value.
Plugin Ideas to Build Next
| Plugin | What it does |
|---|---|
git-helper | PR description writer, commit message generator, branch namer |
test-enforcer | Auto-run tests on edit, enforce coverage thresholds, generate missing tests |
security-scanner | IDOR checker, injection auditor, pre-commit security review |
doc-writer | Generate README, API docs, changelogs from code |
infra-ops | Terraform plan reviewer, cost estimator, drift detector |
incident-bot | Post-mortem template filler, on-call summary, PagerDuty integration |
Each of these follows the same pattern: a few skill files, an optional hook, and an MCP server connection if external data is needed.
