
How to Build & Publish a Claude Code Plugin (2026)
The whole process in five lines
- 1Layout → .claude-plugin/plugin.json (only "name" is required), with skills/, agents/, hooks/hooks.json and .mcp.json at the plugin root.
- 2Test → claude --plugin-dir ./my-plugin loads it for one session; run /reload-plugins after edits.
- 3Publish → submit the GitHub repo as a "Plugin bundle" at claude.ai/directory/manage (any paid plan; reviewed before listing).
If you've built up a set of Claude Code skills, hooks and MCP servers for your team, a plugin is how you package them so anyone can install the whole setup in one step. Since late September 2026, Anthropic's developer portal also lets anyone on a paid Claude plan submit a plugin to the public directory, where people can find it from Claude's apps. This tutorial builds a small but useful plugin from an empty folder: a skill that writes a conventional commit message and a hook that runs your linter after every edit. Then it covers testing, validation, and the three ways to share it. If you're still unsure how skills, hooks and plugins differ, read Claude Code skills vs subagents vs hooks vs plugins first.
Step 1: Create the Folder and Manifest
A plugin is a directory. Its manifest lives at .claude-plugin/plugin.json, and that file is the only thing that goes inside .claude-plugin/. Everything else (skills, agents, hooks, MCP config) sits at the plugin root next to it. Putting components inside .claude-plugin/ is the most common reason a plugin loads with nothing in it.
team-workflow/.claude-plugin/plugin.json
{
"name": "team-workflow",
"description": "Commit messages and lint-on-edit for our React projects",
"version": "1.0.0",
"author": { "name": "Your Name" }
}- name is the only required field. No spaces; it becomes the prefix on every skill, as in /team-workflow:commit.
- Setting version keeps users on that version until you change it. Leave it out if you want users to always get the latest commit.
- Inside author, name is required and email and url are optional.
Step 2: Add a Skill
Each skill is a folder under skills/ containing a SKILL.md file with YAML frontmatter. The description matters: Claude reads the name and description of every model-invocable skill on every turn to decide when to use it, so keep it short and specific.
disable-model-invocation: true means Claude only runs this skill when you call it yourself with /team-workflow:commit. Remove that line for skills you want Claude to pick up on its own when they're relevant.
team-workflow/skills/commit/SKILL.md
--- name: commit description: Write a Conventional Commits message for the staged changes disable-model-invocation: true --- Run `git diff --staged` and write one commit message in Conventional Commits format: - type(scope): summary, imperative mood, at most 72 characters - types: feat, fix, refactor, perf, test, docs, chore - a body only if the change needs explaining; wrap at 72 characters - never mention files that aren't staged Show the message and ask before running `git commit`.
Step 3: Add a Hook
Hooks run shell commands at points in Claude Code's lifecycle. They live in hooks/hooks.json, under a top-level "hooks" key, in the same shape as the hooks section of a settings file. This one runs ESLint's autofix on every file Claude writes or edits:
team-workflow/hooks/hooks.json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx eslint --fix"
}
]
}
]
}
}Step 4: Test It Locally
You don't need a marketplace to test. --plugin-dir loads the plugin for a single session without installing anything:
Validate, then load the plugin for one session.
# Check the manifest and every skill/agent frontmatter claude plugin validate ./team-workflow # Start a session with the plugin loaded claude --plugin-dir ./team-workflow # Inside the session: # /team-workflow:commit run the skill # /reload-plugins pick up edits without restarting # /plugin Installed and Errors tabs show what loaded
- Validation prints ✔ Validation passed or lists each field to fix. Add --strict to fail on warnings too.
- If a skill is missing, check that skills/ is at the plugin root, not inside .claude-plugin/.
- To check the hook, ask Claude to edit a file and confirm ESLint ran.
- If you already have skills or hooks in a project's .claude/ folder, copy them into the plugin structure. Plugin skills get the plugin-name prefix, so the old and new copies don't collide while you test.
Step 5: Share or Publish
There are three ways to get the plugin to other people, depending on who they are:
| audience | method | how |
|---|---|---|
| A few teammates | Send the folder or a .zip | They run claude --plugin-dir with it; nothing is published |
| Your team or company | Your own marketplace | A repo with .claude-plugin/marketplace.json listing your plugins; teammates add it once and install by name |
| Anyone using Claude | Anthropic's directory | Submit the GitHub repo as a Plugin bundle in the developer portal |
Submitting to Anthropic's Directory
The developer portal at claude.ai/directory/manage is where you submit and maintain listings. The rules from Anthropic's publishing guide:
- Who: anyone on Pro, Max, Team or Enterprise. Free accounts can't submit. On Team and Enterprise, an Owner submits (Enterprise Owners can grant a Directory permission to others).
- What: choose Plugin bundle for a plugin, or MCP connector for a single remote MCP server. Skills alone aren't a submission type; put them in a bundle.
- Source: a GitHub repository, which must be public before the listing goes live.
- Ownership: the first organization to submit a given repository folder owns that listing, so submit from the account that should own it long term.
- Review: every version gets automated validation and a security scan, and a person reviews a new listing before it goes live. Review time isn't fixed.
- Updates: after the first submission you don't resubmit. Merge to the tracked branch; the directory scans each commit and serves it once published.
- Analytics: a published plugin's Usage tab shows installs, versions, how often each skill and MCP server runs, and error rates.
What Makes a Plugin Worth Installing
An enabled plugin adds the name and description of each of its model-invocable skills, agents and commands to Claude's context on every turn, whether or not they're used. Users notice plugins that cost context and do little. A few habits keep yours lean:
- Ship a few focused skills, not twenty overlapping ones.
- Use disable-model-invocation: true for skills people should only run on purpose.
- Write descriptions that say when to use the skill, in one line.
- Document every hook command in your README, because hooks run on their own.
- Test behaviour, not just loading: claude plugin eval runs test cases with and without your plugin and scores the difference.
Frequently Asked Questions
Strategic Summary
Final Thoughts
A Claude Code plugin is a folder with a manifest and the skills, hooks and servers you already use, packaged so others can install them in one step. Start small: one skill, one hook, validated and tested with --plugin-dir. Share it inside your team first, then submit it to the directory once it's proven useful. For how the pieces fit together, see Claude Code skills vs subagents vs hooks vs plugins, and for the servers you might bundle, MCP servers for frontend developers. --- Last reviewed: November 6, 2026. Steps are from Anthropic's Claude Code plugin documentation and directory publishing guide. No affiliation with Anthropic.
Built a plugin? Send me the repo. I'm putting together a list of useful community plugins for React and Node developers.
Next Up
Continue your research
Sources & Research
Claude Code Docs: Create a plugin
https://code.claude.com/docs/en/plugins/create
Claude Code Docs: Plugins overview
https://code.claude.com/docs/en/plugins
Claude Docs: Publish to the directory
https://claude.com/docs/directory/publish
Anthropic Help Center: Release notes (September 25, 2026: Build plugins for Claude)
https://support.claude.com/en/articles/12138966-release-notes





