Browse guides
Back to Guides
IntermediateSkills & CustomizationClaude Code

How to build a Claude Code plugin and share it through a marketplace

Build a Claude Code plugin from one directory, check it with claude plugin validate, then list it in a marketplace.json so your team installs it by name.

Theo Marsh25 minutes

Checked against Claude Code 2.1.294 on

A Claude Code plugin is one directory, and you can build a working one in about five minutes. Make a folder, put a skill in skills/<name>/SKILL.md, check it with claude plugin validate, and load it with claude --plugin-dir. Publishing is a separate and later step: a marketplace is just a .claude-plugin/marketplace.json file listing your plugins and where to fetch each one, so do not reach for one until the plugin already works on your own machine.

Everything below was run against Claude Code 2.1.294 on 8 October 2026, and the command output quoted is what the CLI actually printed.

#What is the smallest plugin that works?

A directory with one skill in it. The plugins overview describes a plugin as "a directory of skills, agents, hooks, MCP servers, or other components that Claude Code installs and loads as one unit", and the create page is explicit that of those components "none is required".

Here is a complete plugin. It ships a single skill that drafts release notes from the commits on a branch:

bash
mkdir -p release-notes-tools/.claude-plugin
mkdir -p release-notes-tools/skills/draft-notes

release-notes-tools/.claude-plugin/plugin.json:

json
{
"name": "release-notes-tools",
"description": "Draft release notes from the commits on the current branch",
"version": "1.0.0",
"author": {
"name": "Your Name"
},
"license": "MIT",
"keywords": ["release", "changelog"]
}

release-notes-tools/skills/draft-notes/SKILL.md:

markdown
---
name: draft-notes
description: Draft release notes from the commits on the current branch. Use when the user asks for release notes, a changelog entry, or a summary of what changed since the last tag.
---
Draft release notes for the current branch.
1. Run `git describe --tags --abbrev=0` to find the last tag. If there is no tag, use the first commit.
2. Run `git log <last-tag>..HEAD --no-merges --format=%s` to list the commit subjects.
3. Group the subjects under `Added`, `Changed` and `Fixed`, dropping anything that only touches tests or formatting.
4. Write the result to `RELEASE-NOTES.md` and show the user a diff before saving.
Ask before overwriting a `RELEASE-NOTES.md` that already exists.

That is the whole plugin. Check it and run it:

bash
claude plugin validate ./release-notes-tools
claude --plugin-dir ./release-notes-tools

Validation printed the manifest path it read and then Validation passed, exiting 0. In the session the skill runs as /release-notes-tools:draft-notes, because every plugin skill is namespaced under the plugin's name. That namespacing is the point of a plugin rather than a loose skill: two plugins can each ship a draft-notes skill without colliding.

One placement rule decides whether any of this loads. The create page states it as a warning: "Only plugin.json goes inside .claude-plugin/. Components saved there don't load." So skills/, agents/, hooks/ and .mcp.json all sit at the plugin root, beside that folder and never inside it. If your plugin loads but its skills are missing, this is the first thing to check.

For what each component type does once it loads, and when a plugin is the wrong answer in the first place, skills vs subagents vs plugins vs MCP servers draws the four distinctions. To write the skill the plugin ships, see building custom skills.

#Do you need a manifest, and what has to be in it?

No, and only name. The manifest reference says it outright: "The manifest is optional. Without it, Claude Code loads the components it finds in the standard layout. The plugin name then comes from the marketplace entry, or from the directory name when you load the plugin with --plugin-dir." In the fields table, "name is the only required key."

We checked both ends of that. A copy of the plugin above with its .claude-plugin/ folder deleted entirely validated clean, and the output line changed from Validating plugin manifest: to Validating components in:, which is how you can tell at a glance which mode you are in. A manifest carrying nothing but name also passed, with three warnings:

Found 3 warnings:
> version: No version specified. Consider adding a version following semver (e.g., "1.0.0")
> description: No description provided. Adding a description helps users understand what your plugin does
> author: No author information provided. Consider adding author details for plugin attribution
Validation passed with warnings

So "optional" means optional for loading, not optional for shipping. Write a manifest when you want metadata, a component outside its default directory, userConfig values Claude Code prompts the user for, or an inline component definition.

Two fields are worth deciding deliberately rather than copying:

  • name is permanent. Users install, enable and configure your plugin by name@marketplace, and the publish page warns that after a rename "users who already installed it lose the plugin, because their install is recorded under the old name". Set displayName for the label people see, and change that instead.
  • version is a commitment. The docs say that if you set it and then push commits without changing it, claude plugin update prints that the plugin "is already at the latest version" and users keep the old copy. Either increment it on every release, or omit it in a git-hosted marketplace so Claude Code uses the commit SHA instead.

The manifest also refuses names that pass as Anthropic's own. We confirmed this with a manifest named claude-helper, which fails with an error rather than a warning:

> name: Plugin name "claude-helper" is reserved: it passes as one of Anthropic's own.

(The real output prefixes each result line with a tick or a cross glyph, which renders differently depending on your terminal, so the lines above are quoted without it.)

Per the reference, that error covers any name starting with claude-, anthropic-, anthropics- or cc-plugin-, the bare names claude, anthropic, anthropics, claude-code and claude-mods, and anything putting official beside claude or anthropic. Having claude as a whole word elsewhere, such as mcp-for-claude, is only a warning.

#What does claude plugin validate actually catch?

Less than its name suggests, and knowing the gap is what saves you a broken release. The command reads only files inside the directory you point it at, so anything that depends on fetching a remote source or on a path existing elsewhere is invisible to it.

We ran each row below against Claude Code 2.1.294:

What we triedclaude plugin validateWhere it actually surfaces
Valid plugin, full manifestPasses, exit 0Nothing to surface
No manifest at allPasses, exit 0, reports Validating components in:Nothing to surface
Manifest with only namePasses with 3 warnings, exit 0--strict turns them into a failure, exit 1
Plugin name reserved to AnthropicFails, exit 1Caught before you ship
Marketplace source containing ..Fails, exit 1Caught before you ship
Marketplace source naming a missing directoryPasses, exit 0claude plugin install, as Source path does not exist
Entry name different from the manifest namePasses, exit 0Your users, when the install id does not resolve

The last two rows are the ones to plan around. The create-marketplace page says most failed installs from a new marketplace come from exactly these two mistakes, and neither is a validation error, so the only thing that catches them is installing from your own marketplace before you hand it to anyone.

In CI, run it with --strict:

bash
claude plugin validate --strict ./release-notes-tools

That turns warnings such as a missing version or an unknown manifest field into exit code 1. Drop --strict if you deliberately chose to omit version.

#How do you turn the plugin into a marketplace?

Add one JSON file and point Claude Code at the directory. A marketplace is a directory or repository holding .claude-plugin/marketplace.json, which the overview describes as "a catalog, not a hosted store".

The file requires name, owner and a plugins array, and each entry requires name and source:

json
{
"name": "acme-plugins",
"description": "Plugins the Acme platform team maintains",
"owner": {
"name": "Acme Platform Team",
"url": "https://github.com/acme"
},
"plugins": [
{
"name": "release-notes-tools",
"source": "./plugins/release-notes-tools",
"description": "Draft release notes from the commits on the current branch"
}
]
}

With the plugin copied to acme-plugins/plugins/release-notes-tools/, that file validated clean. Then register it and install from it:

bash
claude plugin marketplace add ./acme-plugins
claude plugin install release-notes-tools@acme-plugins
claude plugin list

Two rules about source cause most of the trouble:

  • Relative paths start from the marketplace root, which is the directory containing .claude-plugin/, not from marketplace.json itself. So the entry above reads ./plugins/release-notes-tools and not ./../plugins/.... A path with .. is a validation error, and the message we got names the fix: Plugin source paths are resolved relative to the marketplace root (the directory containing .claude-plugin/), not relative to marketplace.json.
  • The entry name and the manifest name must match. The entry name is the install id and the key written into the user's settings; the manifest name is the prefix on the plugin's skills. When they differ and someone installs by the manifest name, Claude Code reports that the plugin was not found in the marketplace.

For a plugin that lives outside the marketplace directory, source becomes an object instead of a path. The github form is { "source": "github", "repo": "your-org/your-plugin" }, and git-subdir takes a url and a path for a plugin inside a monorepo. The reference also documents url, archive, npm and command sources.

To publish from the plugin's own repository rather than a separate one, keep marketplace.json beside plugin.json in .claude-plugin/ and give the single entry a source of "./".

#Which way should you distribute it?

By who needs to install it, not by how finished the plugin feels. The docs set out three routes, and only one of them involves a submission:

RouteWho can installWhat you needAutomatic updates
No marketplaceThe people you send the folder or a .zip toThe plugin's folderNone. They load the copy you sent
Your own marketplaceAnyone who can clone the repository, including a private oneA git host with .claude-plugin/marketplace.jsonOff by default, per marketplace
Anthropic's directoryPeople who add it on claude.ai or in Cowork, and it reaches their Claude Code through account syncA GitHub repository and a paid claude.ai plan to submit fromYes, once the version you push is published

Start at the top of that table and move down only when you need to. Sending a directory needs no marketplace and no review, and a recipient loads it with claude --plugin-dir ./release-notes-tools for one session, with or without a manifest, or by moving the directory, with its .claude-plugin/plugin.json, under ~/.claude/skills/ so it loads in every session. Only the --plugin-dir route works without a manifest: Claude Code loads a folder under ~/.claude/skills/ only when it holds .claude-plugin/plugin.json, and one without it loads nothing and reports no error.

Your own marketplace is published the moment the file is in the repository, with no form to fill in. Your users then run two commands:

bash
claude plugin marketplace add your-org/your-marketplace
claude plugin install release-notes-tools@your-marketplace

Since Claude Code 2.1.292 those collapse into one, which is the change that matters most here if you write install instructions for other people:

bash
claude plugin install release-notes-tools --marketplace your-org/your-marketplace

The changelog entry for 2.1.292, dated 6 October 2026, describes it as adding "--marketplace <source> to claude plugin install: adds the marketplace if needed, under the same policy checks as claude plugin marketplace add, then installs the plugin from it". The in-session form, /plugin install <name> --marketplace <source>, requires 2.1.275 or later.

Anthropic's directory is the only route with a gate on it. Submission goes through the developer portal at claude.ai/directory/manage, requires a paid claude.ai plan, and each version goes through review before it is published. The publish page is also clear that a clean local validation is not a pass: "The portal applies additional directory rules that the CLI doesn't check." Note too that Anthropic's official marketplace, claude-plugins-official, does not take submissions through that portal at all. The directory is a different thing again from Claude Marketplace, the website Anthropic opened in September 2026 for browsing plugins, connectors and partners.

#What breaks first, and how do you tell?

Four failures account for most of the time lost, and each has its own diagnostic.

Components inside .claude-plugin/. The plugin loads and its skills are missing. Move skills/ to the plugin root and run /reload-plugins.

--plugin-dir pointed at a marketplace root. Nothing loads and there is no error, because Claude Code does not read marketplace.json for that flag. Point it at one plugin's own directory, the one holding .claude-plugin/plugin.json and the component folders.

A component path in the manifest that does not exist. Every component path must start with ./, resolve inside the plugin root and exist. The /plugin panel's Errors tab reports <component> path not found: <path>, and validation reports Path not found.

Edits that do not appear. Plugins load at session start. Run /reload-plugins in the session to apply changes you made on disk, then confirm with claude plugin list or the Installed tab of /plugin, which lists the components Claude Code actually found.

When a plugin loads cleanly but does not change how Claude behaves, that is a different problem and has its own tool: claude plugin eval runs your test cases with and without the plugin and scores the difference.

#What should you check before installing someone else's plugin?

Read it first. A plugin can ship skills, hooks, MCP servers and executables, and the overview is blunt about the consequence: "what the plugin runs, it runs as you." A marketplace's tier does not change that. Claude Code accepts Anthropic's official and community marketplace names only for marketplaces sourced from github.com/anthropics/ repositories, and the docs note that every other marketplace, including one your own employer publishes, is third-party.

Before you install anything from a marketplace you do not control, read every SKILL.md, every file under hooks/, every script those hooks call, and anything in bin/, which the manifest reference says is placed on the Bash tool's PATH while the plugin is enabled. Our skill security audit is the checklist we use for the skill half of that. Nothing on ClawDocx is an endorsement of a third-party plugin or skill, including any named in a source we cite.

One last thing worth knowing before you install rather than after: an enabled plugin is part of every session, not only the ones where you use it. Each invocable skill, agent and command keeps its name and description in Claude's context on every turn, which costs tokens and context window even in sessions where nothing from the plugin runs. Plugins in Anthropic's official marketplace show a context cost estimate in the Marketplaces tab of /plugin, and claude plugin disable stops a plugin without uninstalling it.

If what you actually wanted was to change Claude Code's behaviour rather than package components for other people, mods are the component type to read about next.

Frequently asked questions

Do you need a plugin.json to build a Claude Code plugin?
No. The manifest reference says in as many words that the manifest is optional, and without it Claude Code loads whatever components it finds in the standard layout, naming the plugin after its directory when you load it with --plugin-dir. Write one when you want metadata, a component outside its default folder, or userConfig. When you do write one, name is the only required field.
How do you test a Claude Code plugin without publishing it?
Run claude plugin validate ./your-plugin from your shell to check the manifest and every skill, agent and command file, then start a session with claude --plugin-dir ./your-plugin. The plugin loads for that session only and nothing is written to your settings. Run /reload-plugins in the session to pick up edits you make on disk.
What is the difference between a plugin marketplace and Claude Marketplace?
A plugin marketplace is a directory or repository with a .claude-plugin/marketplace.json file that lists plugins and where to fetch each one, which you register with claude plugin marketplace add. Claude Marketplace is Anthropic's website at claude.com/marketplace for browsing plugins, connectors and partners. The docs state plainly that it is not a marketplace you add with /plugin marketplace add.
Why does my plugin install fail when claude plugin validate passed?
Validation only reads files inside the directory you point it at, so it cannot see a remote source or a path that does not exist yet. We confirmed two cases that pass validation and fail later: a relative source naming a directory that is not there fails at install with Source path does not exist, and a marketplace entry name that differs from the name in the plugin's own plugin.json passes validation but breaks the install id.
How do people get a new version of your plugin?
If your plugin.json sets a version, increment it and push, and users receive it when they run claude plugin update or when auto-update is on for your marketplace. Auto-update is off by default. If you push commits without changing the version, the docs say claude plugin update reports the plugin is already at the latest version and users keep the old copy.

Sources

  1. Claude Code docs: Plugins overview
  2. Claude Code docs: Create a Claude Code plugin
  3. Claude Code docs: Plugin manifest reference
  4. Claude Code docs: Create a marketplace
  5. Claude Code docs: Publish and distribute a plugin
  6. Claude Code docs: Add components to a plugin
  7. Claude Code changelog

Skip the trial and error

ClawDocx members get 500+ tested prompts, ready-to-install SKILL.md files, SOUL.md and CLAUDE.md templates, and an MCP server so your agent can pull all of it directly while it works.