Slash commands, skills, subagents, MCP servers, and hooks bundled into a single installable package — with marketplaces to distribute them, a manifest that does real work, and a context price tag you can read before you buy.
Manual setup means installing slash commands one by one, creating subagents individually, configuring MCPs separately, wiring hooks, documenting everything — 2+ hours, and you hope teammates configure it correctly. Plugins are bundled collections of customizations — slash commands, subagents, MCP servers, and hooks — that install with a single command: 2 minutes, and the team reproduces the exact setup.
// .claude-plugin/plugin.json — the manifest { "name": "my-first-plugin", "description": "A greeting plugin", "version": "1.0.0", "author": { "name": "Your Name" }, "homepage": "https://example.com", "repository": "https://github.com/user/repo", "license": "MIT" }
Plus optional top-level dirs: templates/, scripts/, docs/, tests/, and themes/ (ship custom Claude Code themes, v2.1.118+).
| commands/ | Slash commands as Markdown files — chapter 1 |
| skills/ | Agent Skills with SKILL.md files — chapter 3 |
| agents/ | Custom subagent definitions — chapter 4 |
| .mcp.json | MCP server configurations — chapter 5 |
| hooks/hooks.json | Event handlers — chapter 6 |
| .lsp.json | LSP servers for code intelligence |
| bin/ | Executables added to the Bash tool's PATH |
| settings.json | Defaults applied when enabled (agent key) |
The lifecycle continues after install: use → update (when available) → disable → re-enable — components come and go as a unit, never one by one.
| Standalone /hello | Manual setup in CLAUDE.md — best for personal, project-specific workflows |
| Plugin /plugin-name:hello | Automated via plugin.json — best for sharing, distribution, team use |
Spaced invocation (v2.1.136+): /myplugin review resolves to the canonical /myplugin:review. Either form works; the colon form is recommended in scripts.
| Installation | Manual copy → one command |
| Setup time | 5–15 min per feature → 2 min total |
| Bundling | Single file each → multiple components |
| Versioning / updates | Manual → automatic, auto-available |
| Team sharing | Copy files around → install ID |
| Marketplace | No → yes |
| userConfig (v2.1.83+) | Declare user-configurable options — a description, an optional default, and "sensitive": true values stored in the system keychain rather than plain-text settings files (API keys belong here) |
| ${CLAUDE_PLUGIN_DATA} (v2.1.78+) | Per-plugin persistent state directory that survives across sessions — caches, databases, usage logs. Created on install, removed on uninstall; reference it in hook commands like node ${CLAUDE_PLUGIN_DATA}/track-usage.js |
| monitors (v2.1.105) | Background monitors that auto-arm — "trigger": "session_start" arms when a session begins, "skill_invoke" when the plugin's skill fires. Streams stdout lines as events Claude can react to |
| settings.json | Default settings applied on installation — currently the agent key, which sets the plugin's main-thread agent (e.g. "agent": "agents/specialist-1.md"). Users can override in their own config |
| source: "settings" (v2.1.80+) | Define a plugin inline in your settings file as a marketplace entry — no separate repository or marketplace needed for small local tools |
{
"go": {
"command": "gopls",
"args": ["serve"],
"extensionToLanguage": {
".go": "go"
}
}
}
Once configured: instant diagnostics after edits, go-to-definition / find references, hover types, symbol listing. Optional fields tune transport, env, timeouts, and restartOnCrash. Official marketplace ships pyright-lsp, typescript-lsp, rust-lsp pre-configured.
my-plugin/
├── plugin.json
└── bin/
└── my-tool # chmod +x
# with the plugin enabled:
$ my-tool --help
While the plugin is enabled, bin/ is prepended to PATH — hooks, skills, and commands in the same plugin can shell out to its helpers by bare name. Mark files executable in the repo; git preserves the bit.
| skills/ merge (v2.1.136+) | A skills entry in plugin.json no longer hides the plugin's default skills/ directory — skills declared in both places are merged, so you can list a few highlights in the manifest without losing the rest |
| Root SKILL.md (v2.1.142+) | A plugin with a top-level SKILL.md and no skills/ subdirectory is itself surfaced as a single skill — the plugin is the skill. An additional pattern for small single-skill plugins where directory layout adds no value |
| No marketplace needed (v2.1.157+) | Plugins placed in .claude/skills directories auto-load without a marketplace. claude plugin init <name> scaffolds a new one |
pr-review/ ├── .claude-plugin/plugin.json ├── commands/ │ ├── review-pr.md │ ├── check-security.md │ └── check-tests.md ├── agents/ │ ├── security-reviewer.md │ ├── test-checker.md │ └── performance-analyzer.md ├── mcp/github-config.json └── hooks/pre-review.js
Each agent is ~10 lines of frontmatter + focus areas; the GitHub MCP config reads ${GITHUB_TOKEN} from the environment — never hardcoded.
3 commands (/review-pr, /check-security, /check-tests) · 3 subagents · GitHub MCP · pre-review hook. Requires a GitHub token via export GITHUB_TOKEN.
4 commands (/deploy, /rollback, /status, /incident) · 3 subagents (deployment-specialist, incident-commander, alert-analyzer) · Kubernetes MCP · shell scripts (deploy, rollback, health-check) · pre/post-deploy hooks.
4 commands (/generate-api-docs, /generate-readme, /sync-docs, /validate-docs) · 3 subagents · GitHub docs MCP · templates: api-endpoint, function-docs, ADR.
Note the third shape: documentation bundles templates as a first-class component — plugins can ship reference material, not just executable parts.
// .claude-plugin/marketplace.json { "name": "my-team-plugins", "owner": "my-org", "plugins": [ { "name": "code-standards", "source": "./plugins/code-standards", "version": "1.2.0" }, { "name": "deploy-helper", "source": { "source": "github", "repo": "my-org/deploy-helper", "ref": "v2.0.0" } } ] }
| Relative path | "./plugins/my-plugin" — plugin lives in the marketplace repo itself |
| GitHub | { "source": "github", "repo": "acme/lint-plugin", "ref": "v1.0" } |
| Git URL | { "source": "url", "url": "https://git.internal/plugin.git" } — any git host |
| Git subdirectory | { "source": "git-subdir", "url": "…/monorepo.git", "path": "packages/plugin" } — one plugin out of a monorepo |
| npm | { "source": "npm", "package": "@acme/claude-plugin", "version": "^2.0" } |
| pip | { "source": "pip", "package": "claude-data-plugin", "version": ">=1.0" } |
GitHub and git sources accept optional ref (branch/tag) and sha (commit hash) for version pinning — reproducible environments. Plugins can also specify custom npm registries, and the default git timeout is 120 s for large plugin repositories.
# GitHub (recommended) /plugin marketplace add owner/repo-name # other git services — full URL /plugin marketplace add \ https://gitlab.com/org/marketplace-repo.git
Private repositories work via git credential helpers or environment tokens — users need read access. Official-marketplace submissions go through claude.ai/settings/plugins/submit or platform.claude.com/plugins/submit.
The /plugin marketplace browser shows each plugin's projected per-turn context-token cost (v2.1.143) — the sum of its always-loaded skills, hooks, and MCP server descriptors:
| install <name>@<mkt> | Install from a marketplace |
| uninstall / update / list | Remove · update to latest · list installed |
| enable / disable | Toggle without uninstalling (auto-detected scope) |
| validate | Check plugin structure before publishing |
| tag <version> | Release tag with version validation (v2.1.118+) |
| prune | Remove orphaned auto-installed dependencies (v2.1.121+); uninstall --prune cascades in one step |
| details <name> | Inventory + projected token cost (v2.1.139+) |
# load one or many local plugins claude --plugin-dir ./my-plugin claude --plugin-dir ./a --plugin-dir ./b # .zip archives work too (v2.1.128+) claude --plugin-dir ./my-plugin.zip # fetch a .zip from a URL (v2.1.129+) claude --plugin-url \ https://example.com/releases/my-plugin-0.3.0.zip # after editing plugin files mid-session /reload-plugins
| claude-plugins-official | Auto-update ✅ enabled by default |
| Third-party / local | Auto-update ❌ disabled by default |
| Toggle | /plugin → Marketplaces → Select |
When auto-update runs it: 1) refreshes the marketplace catalog, 2) updates installed plugins to latest, 3) shows a notification prompting /reload-plugins.
| DISABLE_AUTOUPDATER=1 | Disable all auto-updates — Claude Code and plugins |
| + FORCE_AUTOUPDATE_PLUGINS=1 | Keep plugin updates while Claude Code updates stay off |
| CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1 | (v2.1.141+) Clone GitHub plugin sources over HTTPS instead of SSH — for CI runners and containers without SSH keys |
| enabledPlugins | Allowlist enabled by default |
| deniedPlugins | Blocklist — cannot be installed |
| extraKnownMarketplaces | Additional marketplaces made available to users |
| strictKnownMarketplaces | Not set = any · [] = lockdown · patterns = allowlist (e.g. "my-org/*"). Managed-only |
| blockedMarketplaces | Blocklist; hostPattern / pathPattern regex since v2.1.119 |
| allowedChannelPlugins | Permitted plugins per release channel |
Enforced on every lifecycle event since v2.1.117 — install, update, refresh, and autoupdate, not just at first add. Managed settings take precedence over user-level settings.
So a plugin can't escalate privileges or modify the host environment beyond its declared scope — what you saw in the manifest is what it gets.
| Team onboarding | ✅ Plugin — instant setup, all configurations |
| Framework setup | ✅ Plugin — bundles framework-specific commands |
| Enterprise standards | ✅ Plugin — central distribution, version control |
| Quick task automation | ❌ Command — plugin is overkill complexity |
| Single domain expertise | ❌ Skill — too heavy as a plugin |
| Specialized analysis | ❌ Subagent — create manually or use a skill |
| Live data access | ❌ MCP — keep standalone, don't bundle |
A plugin is a directory: .claude-plugin/plugin.json plus the commands, skills, agents, MCP servers, hooks, LSP configs, and bin/ tools you already know — installed in one command, namespaced as /plugin:command, updated as a unit. The manifest carries real machinery (keychain-backed userConfig, persistent data, background monitors). Marketplaces are just repos with marketplace.json, pulling plugins from paths, git, npm, or pip — pinnable by sha, governed by managed settings, and priced in context tokens per turn that you can read before installing. Develop with --plugin-dir, reload with /reload-plugins, release with plugin tag.