Skip to content

Claude Code Plugins: Build, Install, and Share Extensions

A plugin bundles skills, agents, hooks and MCP servers so a team installs them in one step. Here is how to build one, and the mistake that costs an afternoon.

Claude Code Guides: Claude Code Plugins. One package containing skills, agents, hooks and MCP blocks.

What a plugin is

A plugin is a directory that bundles Claude Code extensions — skills, agents, hooks, MCP servers, and more — so they can be installed, versioned, and shared in one step.

Everything a plugin contains, you could put loose in a .claude/ directory. The difference is distribution. A plugin can be published to a marketplace, pinned to a version, installed by a teammate with one command, and updated when you release. Loose configuration has to be copied by hand and drifts the moment two people have it.

Plugin or plain .claude/?

Standalone .claude/ Plugin
Skill name /hello /plugin-name:hello
Best for Personal workflows, project quirks, quick experiments Sharing, distributing, versioned releases
Install Copy the files /plugin install
Updates Manual, and it will drift Version bump

The sensible path is to start standalone. Iterate in .claude/ where there is no packaging step between you and a change, and convert to a plugin when you actually want someone else to have it. Building a plugin for something only you will use is overhead with no return.

The namespacing is worth noticing early: plugin skills are always prefixed, so /my-plugin:deploy and a project /deploy coexist instead of one shadowing the other. That is a real advantage of plugins over loose skills, which do shadow each other.

Installing one

Anthropic maintains two public marketplaces:

  • claude-plugins-official — curated by Anthropic. Registered automatically the first time you start Claude Code interactively. If that never happened, add it yourself:
    claude plugin marketplace add anthropics/claude-plugins-official
  • claude-community — third-party submissions that have passed review:
    /plugin marketplace add anthropics/claude-plugins-community
    and install from it as @claude-community.

The /plugin manager is where you browse, install, enable, and disable. Its Errors tab is the first place to look when a plugin appears to do nothing — a failed MCP or LSP server shows up there rather than announcing itself.

Building one

Three steps to something that runs.

mkdir -p my-first-plugin/.claude-plugin

my-first-plugin/.claude-plugin/plugin.json:

{
  "name": "my-first-plugin",
  "description": "Web build audits and launch checks",
  "version": "1.0.0",
  "author": { "name": "Your Name" }
}

Then a skill at my-first-plugin/skills/audit/SKILL.md:

---
description: Technical SEO and accessibility audit. Use before shipping
  any page change.
---

Audit the rendered output, not the template source.

Report measured values: contrast ratios, scrollWidth against clientWidth
at 320px, actual status codes. Cite file and line for source findings.

Say what you could not verify.

Load it without installing anything:

claude --plugin-dir ./my-first-plugin

Then /my-first-plugin:audit.

The name field is not cosmetic — it is the namespace every skill in the plugin is prefixed with. Changing it later changes every command your users type.

There is also a scaffold that skips the manual setup:

claude plugin init my-tool

which creates ~/.claude/skills/my-tool/ with a manifest and a starter SKILL.md, loading as my-tool@skills-dir on the next session with no marketplace step at all.

The directory structure, and the mistake everyone makes

Here is the one that costs people an afternoon:

Only plugin.json goes inside .claude-plugin/. Everything else — skills/, agents/, hooks/, commands/ — lives at the plugin root. Put them inside .claude-plugin/ and they are silently not found. Nothing errors; the plugin simply does nothing.

my-plugin/
├── .claude-plugin/
│   └── plugin.json          ← only this
├── skills/
│   └── audit/SKILL.md
├── agents/
│   └── reviewer.md
├── hooks/
│   └── hooks.json
├── .mcp.json
└── settings.json

The plugin root is the plugin's own directory — the one you pass to --plugin-dir. It is never ~/.claude/. A .mcp.json at ~/.claude/.mcp.json is not read by anything.

One shortcut: a plugin shipping exactly one skill can put SKILL.md at the plugin root and skip the skills/ directory entirely. Use the folder layout for anything that might grow.

Two plugin directory trees side by side. The correct one has plugin.json alone inside .claude-plugin, with skills, agents, hooks and .mcp.json at the plugin root. The broken one nests skills and agents inside .claude-plugin, where they are never found and no error is raised.
The broken layout produces no error at all. The plugin loads and does nothing.

What a plugin can carry

Directory or file Contents
skills/ Skills as <name>/SKILL.md
commands/ Skills as flat Markdown files. Legacy — use skills/ for new work
agents/ Subagent definitions
hooks/hooks.json Event handlers
.mcp.json MCP server configuration
.lsp.json Language servers, for real code intelligence
monitors/monitors.json Background watchers that notify Claude as events arrive
bin/ Executables added to the Bash tool's PATH while enabled
settings.json Defaults applied when enabled. Only agent and subagentStatusLine are supported

Two of these are more interesting than they look.

settings.json with an agent key makes one of the plugin's own agents the main thread — its system prompt, its tool restrictions, its model. A plugin can therefore change how Claude Code behaves by default when enabled, not merely add commands to it.

monitors/monitors.json starts background watchers automatically. Each stdout line from the command reaches Claude as a notification:

[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]

For a web project this is the cheapest useful thing in the list — Claude finds out about a runtime error as it happens rather than when you paste it.

The .mcp.json entry is worth understanding before you bundle one, since a plugin that ships an MCP server is shipping a capability grant — see Claude Code and MCP.

Hooks: the part that enforces

Skills and agents are followed. Hooks run. That difference is why a plugin carrying hooks is qualitatively different from one carrying only prompts.

A hook is a shell command bound to a tool event. Put it in hooks/hooks.json at the plugin root:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix"
          }
        ]
      }
    ]
  }
}

Two details that cost people time. The hook receives its input as JSON on stdin, which is why the example pipes through jq to pull out the file path rather than reading an argument. And the format is identical to the hooks object in settings.json, so migrating existing hooks is a copy rather than a rewrite.

The rule worth adopting: anything mechanical and unconditional should be a hook, not an instruction. A formatter that runs after every edit does not need anybody to remember it. Moving that class of rule out of CLAUDE.md also shortens the file, which makes everything left in it work better.

Confirm a hook actually fired rather than assuming. Trigger the event it matches and check the effect; Claude Code records which hooks matched, their exit codes, and their output in the debug log. A hook with a typo in its matcher fails silently and looks exactly like a hook that ran and did nothing.

Testing while you build

claude --plugin-dir ./my-plugin

The flag also takes a .zip, and can be repeated to load several plugins at once. If a --plugin-dir plugin shares a name with an installed one, the local copy wins for that session — so you can test changes without uninstalling.

After edits, /reload-plugins picks them up without restarting. Then check each component actually loaded, because a plugin that half-works looks identical to one that works:

  • Skills: run /plugin-name:skill-name
  • Agents: confirm they appear in /context under Custom Agents
  • Hooks: trigger the matching event and confirm the effect
  • Anything failing: check the /plugin manager's Errors tab

Before publishing:

claude plugin validate ./my-plugin

Add --strict to treat warnings as errors. The review pipeline runs the same check, so passing locally is the cheapest way to avoid a rejection.

Distributing through a marketplace

A marketplace is a repository with a catalogue of plugins. Point people at it and they install from it. Host it privately and it stays internal to your team — which is the usual case for company tooling, and needs no submission or review.

For public distribution, submissions go through review via the in-app forms on claude.ai or the Console. Approved plugins are pinned to a specific commit SHA in the community catalogue, with CI bumping the pin as you push. The catalogue syncs nightly, so there is a delay between approval and installability.

The official marketplace is curated separately, at Anthropic's discretion. There is no application process for it, and submitting to the community marketplace does not put you in it.

Converting what you already have

If you have accumulated skills and hooks in .claude/, converting is mostly copying:

mkdir -p my-plugin/.claude-plugin
cp -r .claude/skills   my-plugin/
cp -r .claude/agents   my-plugin/
cp -r .claude/commands my-plugin/

Hooks are the one genuine change: they move from the hooks object in settings.json into my-plugin/hooks/hooks.json. The format is the same, so it is a copy of that object.

Then remove the originals, and know exactly what happens if you do not:

  • Agents: project and user .claude/agents/ definitions override same-named plugin agents. Leave the original and the plugin version never runs.
  • Skills: plugin skills are namespaced, so /deploy and /my-plugin:deploy both exist. Nothing overrides anything — you just have two, and people will use whichever they type.

Trust

A plugin can add executables to your PATH, register MCP servers, run hooks on tool events, and start background processes. That is a lot of capability, and it is exactly why plugins are useful.

Treat installing one as you would adding a dependency: from a source you trust, ideally read first. The same applies to --plugin-url, which fetches an archive at startup — point it only at archives you control or trust.

For a project's own .claude/skills/, a skill folder that is also a plugin requires accepting the workspace trust dialogue before it loads. That prompt is doing real work; it is not a formality.

Where plugins go wrong

Components inside .claude-plugin/

The failure is silent. If your plugin loads but does nothing, check this first.

Packaging before it works

Iterate loose in .claude/, package when it is worth sharing.

Renaming after release

name is the command namespace. Changing it breaks every command your users have learned.

Shipping without validating

claude plugin validate takes seconds and catches what review would reject.

Leaving the originals behind after converting

Your project agents keep overriding the plugin's, and you conclude the plugin is broken.

Where to go next

Plugins are the distribution layer for skills and subagents — read those first if you are deciding what to put inside one. The rules that apply regardless of packaging belong in a production CLAUDE.md. For rolling plugins out across an organisation with managed settings, see Claude Code for teams and enterprise, and for what the packaged procedures should actually contain, the prompt library and the complete website workflow.

Sources and further reading

More Claude Code guides

Free download

The CLAUDE.md Starter Kit, free

Four working CLAUDE.md files you can drop into a project today, plus the one-page checklist for what belongs in one and how to tell whether yours is actually working.

  • CLAUDE.md for a static marketing site
  • CLAUDE.md for a web application, with security and migration rules
  • CLAUDE.md for a Shopify theme, including the gotchas that cost hours
  • CLAUDE.md for a shared package in a monorepo
  • A one-page checklist, and how to test the file is actually working

The download appears here as soon as you submit. I will also email you when there is a new guide worth reading. No fixed schedule, no selling your address, unsubscribe from any email. See the privacy policy.