Journal
Tutorials

How to Build a Claude Code Plugin (and Share It)

C

Clearly Team

Engineering

7 min read
Jul 10, 2026

How to Build a Claude Code Plugin (and Share It)

Hooks and slash commands are great — until you want them on three machines and a teammate's laptop too. A plugin bundles them into one installable unit; a marketplace lets anyone add it with a single command. Here's the whole thing, using a real, tiny plugin (a desktop notifier) as the worked example.

What a plugin is

A plugin is a folder with a manifest (.claude-plugin/plugin.json) and any components it ships — hooks, slash commands, skills, agents, MCP servers. Install it and its hooks wire themselves into Claude Code automatically. No hand-editing settings.json on every machine.

The manifest

Create .claude-plugin/plugin.json. The minimum is a name, description, and version:

{
  "name": "mwah-notify",
  "description": "Desktop notification when your Claude Code session finishes or needs you.",
  "version": "1.0.0",
  "author": { "name": "You" },
  "license": "MIT",
  "keywords": ["notification", "hooks"],
  "category": "productivity"
}

That's a valid plugin already. Now give it something to do.

Bundling a hook

Plugin hooks live in hooks/hooks.json at the plugin root — not inside .claude-plugin/. Reference your scripts with ${CLAUDE_PLUGIN_ROOT}, which resolves to wherever the plugin gets installed:

{
  "hooks": {
    "Stop": [
      { "hooks": [ { "type": "command", "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/notify.mjs" } ] }
    ],
    "Notification": [
      { "matcher": "", "hooks": [ { "type": "command", "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/notify.mjs" } ] }
    ]
  }
}

The layout

my-plugin/
  .claude-plugin/
    plugin.json
  hooks/
    hooks.json
    notify.mjs
  README.md

Only plugin.json goes in .claude-plugin/; everything else — hooks, scripts, skills, agents — lives at the plugin root. (Don't nest them inside .claude-plugin/; that's the most common mistake.)

Sharing it: a marketplace

A marketplace is a repo with .claude-plugin/marketplace.json listing one or more plugins:

{
  "name": "my-tools",
  "owner": { "name": "You" },
  "plugins": [
    { "name": "mwah-notify", "source": "./plugin", "description": "Desktop notifier" }
  ]
}

Push it to GitHub, and anyone installs with two commands:

/plugin marketplace add you/my-tools
/plugin install mwah-notify@my-tools

A real one to copy

Rather than start from scratch, clone a working example: mwah-notify is a tiny, MIT-licensed notifier plugin (Stop + Notification → a native desktop notice) — read the source and lift the structure. Install it to see a plugin in action:

/plugin marketplace add clearly-sh/mwah-notify
/plugin install mwah-notify@mwah

(Building agent tooling in general? Mwah shows every live Claude Code session as a robot on your desktop — the visual layer over all the hooks and plugins you're wiring.)


Related: Claude Code hooks: the complete guide · 5 useful Claude Code hooks

#claude code#plugins#hooks#developer workflow