Claude Code Plugins: Install, Build, and Ship Your Own
Learn how Claude Code plugins work: install them with /plugin, write a plugin.json manifest, bundle skills, commands, hooks, and MCP servers, and ship to your team.
Claude Code plugins package slash commands, skills, hooks, subagents, and MCP servers into a single installable unit. Instead of asking every teammate to copy files into .claude/ by hand, you publish one plugin, they run one /plugin install command, and the whole toolkit shows up together — versioned, togglable, and removable in one step.
This guide walks the full lifecycle: what actually lives inside a plugin, how to install plugins from marketplaces, what every field in the plugin.json manifest does, how to build and test your own plugin from scratch, when a plugin is the right packaging (and when a standalone skill is better), and how to distribute plugins across a team.
What a Plugin Is: Skills, Commands, Hooks, and MCP in One Bundle
A plugin is just a directory with a manifest. Claude Code discovers each component by convention:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # required manifest
├── commands/ # slash commands (one .md file each)
├── agents/ # subagent definitions
├── skills/ # skills, each a folder with a SKILL.md
├── hooks/
│ └── hooks.json # hook configuration
└── .mcp.json # MCP server definitions
Every directory is optional — only .claude-plugin/plugin.json is required. A plugin can be a single hook, or it can be a complete workflow:
- Commands become namespaced slash commands:
commands/review.mdin a plugin namedacme-workflowis invoked as/acme-workflow:review. The file format is identical to project-level custom slash commands. - Skills are folders containing a
SKILL.mdwith name and description frontmatter. Claude loads them on demand when the description matches the task, exactly like personal or project skills — see our Claude Code skills guide for the format. - Hooks run shell commands on lifecycle events (before/after tool calls, on prompt submit, and so on). Plugin hooks live in
hooks/hooks.jsonand merge with the user's own hooks. The event model is covered in our Claude Code hooks guide. - Subagents in
agents/define specialized agents Claude can delegate to. - MCP servers declared in
.mcp.jsonstart automatically when the plugin is enabled, so a plugin can ship external tool access alongside the prompts that use it.
The value of the bundle is coherence: a code-review plugin can ship the /review command, the standards skill the command relies on, and a hook that blocks commits when the review fails — and they install, enable, and version as one unit.
How to Install Claude Code Plugins
To install Claude Code plugins you need two things: a marketplace (a catalog of plugins) and the plugin's name. Everything happens through the /plugin command inside Claude Code.
- Add a marketplace. A marketplace is any git repo, GitHub reference, or local directory containing a
.claude-plugin/marketplace.jsoncatalog. Register one withplugin marketplace add:
/plugin marketplace add acme/claude-plugins # GitHub owner/repo
/plugin marketplace add https://gitlab.com/acme/plugins.git
/plugin marketplace add ./local-marketplace # local directory
- Browse and install. Run
/pluginwith no arguments to open the interactive UI, where you can browse marketplaces, read plugin descriptions, and install with a keypress. Or install directly when you know the name:
/plugin install acme-workflow@acme-plugins
-
Verify it loaded. Type
/and look for the plugin's namespaced commands (e.g./acme-workflow:review). Skills, hooks, and MCP servers from the plugin activate alongside them. -
Manage what's enabled.
/pluginalso handles the rest of the lifecycle — enable or disable a plugin without uninstalling it, remove it entirely, or update a marketplace to pick up new versions:
/plugin marketplace list # what catalogs are registered
/plugin marketplace update acme-plugins
/plugin uninstall acme-workflow
Disabling is worth knowing about: plugins you rarely use still contribute their commands and hook overhead, so keeping seldom-used plugins disabled until needed keeps sessions lean.
Anatomy of the plugin.json Manifest
The plugin.json manifest lives at .claude-plugin/plugin.json and describes the plugin. A complete example:
{
"name": "acme-workflow",
"version": "1.2.0",
"description": "Acme's review command, API conventions skill, and format-on-save hook",
"author": {
"name": "Acme Engineering",
"email": "eng@acme.dev",
"url": "https://acme.dev"
},
"homepage": "https://github.com/acme/claude-plugins",
"repository": "https://github.com/acme/claude-plugins",
"license": "MIT",
"keywords": ["review", "conventions", "formatting"]
}
Field by field:
| Field | Required | Purpose |
|---|---|---|
name | Yes | Unique identifier, kebab-case. Becomes the command namespace. |
version | No | Semver string; bump it on every release so updates are visible. |
description | No | Shown in the /plugin browser — write it for the person deciding whether to install. |
author | No | Object with name, email, url. |
homepage / repository | No | Where users go for docs and source. |
keywords | No | Helps discovery in marketplace browsing. |
Two details trip people up:
- Only
nameis required, but treatversionanddescriptionas mandatory in practice. A marketplace full of undescribed plugins is unusable. - Paths are convention-based. Claude Code looks for
commands/,agents/,skills/,hooks/hooks.json, and.mcp.jsonrelative to the plugin root. The manifest can override these locations with explicit path fields, but the defaults are almost always the right choice.
Inside hook commands and MCP server configs, use the ${CLAUDE_PLUGIN_ROOT} variable to reference files bundled with the plugin. It expands to the plugin's installed location, so scripts resolve no matter where the plugin lands on disk.
Build Your First Plugin Step by Step
Let's build a small but real plugin: a review command, a conventions skill, and a formatting hook.
Step 1 — scaffold the structure.
mkdir -p acme-workflow/.claude-plugin \
acme-workflow/commands \
acme-workflow/skills/api-conventions \
acme-workflow/hooks \
acme-workflow/scripts
Step 2 — write the manifest at acme-workflow/.claude-plugin/plugin.json:
{
"name": "acme-workflow",
"version": "0.1.0",
"description": "Review command, API conventions skill, and format-on-save hook"
}
Step 3 — add a command at commands/review.md:
---
description: Review uncommitted changes against Acme standards
---
Review the uncommitted changes in this repository. Check for:
1. Endpoints that violate our API conventions skill
2. Missing or weak test coverage for changed logic
3. Error handling that swallows failures silently
Report findings as a prioritized list with file and line references.
Step 4 — add a skill at skills/api-conventions/SKILL.md:
---
name: api-conventions
description: Apply Acme's REST API conventions when designing, implementing, or reviewing endpoints. Use when creating routes, handlers, or API schemas.
---
# Acme API conventions
- Version every public route under /v1/
- Return RFC 7807 problem+json bodies for all error responses
- Paginate list endpoints with cursor parameters, never offset
The description matters more than the body: it's what Claude reads when deciding whether to load the skill, so state both what it does and when to use it.
Step 5 — add a hook at hooks/hooks.json that formats files after edits:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh"
}
]
}
]
}
}
Put the script at scripts/format.sh and make it executable. ${CLAUDE_PLUGIN_ROOT} guarantees the path resolves after installation.
Step 6 — test with a local marketplace. Create a sibling directory with a catalog file at local-marketplace/.claude-plugin/marketplace.json:
{
"name": "local-dev",
"owner": { "name": "You" },
"plugins": [
{
"name": "acme-workflow",
"source": "../acme-workflow",
"description": "Local development copy"
}
]
}
Then in Claude Code:
/plugin marketplace add ./local-marketplace
/plugin install acme-workflow@local-dev
Run /acme-workflow:review, edit a file to confirm the hook fires, and ask an API-design question to confirm the skill triggers.
Step 7 — publish. Push the plugin (and a real marketplace.json) to a git repo. Anyone can now /plugin marketplace add your-org/your-repo and install.
Claude Code Plugins vs Skills: When to Bundle
The most common packaging question is Claude Code plugins vs skills: if you have knowledge to share, do you write a standalone skill or wrap it in a plugin?
| Standalone skill | Plugin | |
|---|---|---|
| Contains | One SKILL.md folder | Skills + commands + hooks + agents + MCP |
| Namespace | None | Commands prefixed with plugin name |
| Works in | Any tool that reads the target format | Claude Code only |
| Best for | Reusable knowledge and procedures | Multi-component workflows |
Rules of thumb:
- Bundle when components depend on each other. If your command references a skill and a hook enforces the command's output, shipping them separately guarantees someone installs half the workflow and files a bug.
- Keep knowledge as standalone skills when it stands alone. A "how we write migrations" skill doesn't need a plugin wrapper — the wrapper just adds install friction and locks it to one tool.
- Think about portability. Plugins are Claude Code-specific. Skills are the portable layer: the same SKILL.md content is useful to Cursor, Windsurf, Copilot, and other agents. If your team is multi-tool, publish skills to a registry like localskills.sh — one
localskills installcan target several tools at once (--target cursor claude windsurf), writing.claude/skills/for Claude Code and each tool's native rules format elsewhere.
A sane split for most teams: skills carry the knowledge, plugins carry the Claude Code-specific automation (hooks, commands, MCP wiring) that consumes it.
Distributing Plugins to Your Team
For a team, "everyone runs /plugin marketplace add by hand" doesn't scale. Two better options:
Check marketplace config into the repo. Claude Code reads .claude/settings.json from the project, so you can pre-register your marketplace and pre-enable plugins for everyone who opens the repo:
{
"extraKnownMarketplaces": {
"acme-plugins": {
"source": {
"source": "github",
"repo": "acme/claude-plugins"
}
}
},
"enabledPlugins": {
"acme-workflow@acme-plugins": true
}
}
New teammates get the plugin on first launch — no onboarding doc required.
Run a private marketplace. A private git repo works as a marketplace out of the box: anyone with read access to the repo can add it and install from it. Structure it as one repo containing multiple plugin directories plus a single marketplace.json catalog, and treat plugin version bumps like any other reviewed change. We cover repo layout, access control, and versioning strategy in our guide to running a private Claude plugin marketplace.
For the skills inside those plugins, a registry adds what git alone doesn't: versioning with rollback, public/private/unlisted visibility, download analytics, org folders with member roles and folder-level access restrictions — and GitHub sync, so a skill library can still mirror bidirectionally to a repo while edits made in the repo import back as new skill versions.
FAQ
Do Claude Code plugins work with Cursor or other AI tools?
No. The plugin format — plugin.json, namespaced commands, hooks, bundled MCP config — is specific to Claude Code. The skills inside a plugin are the portable part: SKILL.md content can be reused across tools, which is why cross-tool teams distribute skills through a registry and reserve plugins for Claude Code-only automation.
What's the difference between /plugin marketplace add and /plugin install?
/plugin marketplace add registers a catalog — a repo or directory whose marketplace.json lists available plugins. /plugin install <name>@<marketplace> installs one specific plugin from a registered catalog. You add a marketplace once, then install any number of plugins from it.
Can a plugin contain just one component, like a single hook?
Yes. Every directory except .claude-plugin/plugin.json is optional. A plugin wrapping a single hook or a single MCP server is a perfectly good use of the format — you get versioning, easy enable/disable, and one-command installation for something that would otherwise be a snippet pasted into everyone's settings.
How do I update a plugin my team already installed?
Bump version in plugin.json, commit to the marketplace repo, and have users run /plugin marketplace update <marketplace-name> to refresh the catalog and pick up the new version. If the marketplace is pre-registered via .claude/settings.json, updates flow to the whole team from a single merged PR.
Where do installed plugins actually live?
Claude Code manages installed plugin files itself — you interact through /plugin rather than editing installed copies. To change a plugin's behavior, edit its source in the marketplace repo and ship a new version; local edits to installed files get overwritten on update.
Ready to make the knowledge inside your plugins portable across every tool your team uses? Sign up for localskills.sh and publish your first skill in minutes.
npm install -g @localskills/cli
localskills login
localskills publish