Create a marketplace
Build a plugin marketplace around a marketplace.json catalogue, install from it locally, and catch mistakes before anyone else sees them.
A marketplace is how you hand a set of plugins to a group of people and keep them updated. Physically it is nothing more than a directory (usually a git repository) containing .claude-plugin/marketplace.json, a catalogue that names each plugin and says where to fetch it. Your colleagues register the catalogue once, then install whichever plugins they want from it, and they pick up new versions as you publish them.
Reach for a marketplace when you want a defined audience, such as your team, a client, or the whole organisation, to install from a list you control. The repository can be private, there is no limit on how many plugins it lists, and an administrator can make it mandatory on every machine (see Manage plugins for your organisation).
You probably do not need one if:
- You are sharing a single plugin with one or two people. Send them the folder or a zip. Publish a plugin covers that route.
- You want the plugin listed publicly. Submitting to Anthropic's directory is also described on Publish a plugin.
- The plugin is just for you. Load it with
--plugin-dirwhile you work on it, as shown in Create a plugin.
Build one end to end
The quickest way to understand a marketplace is to make one locally and install from it. The loop below is exactly what your users will do later, just against a local path instead of a git URL.
I'll use a plugin called copy-check, which holds one skill that reviews website copy for house style. Swap in any plugin you already have; if you have none, follow Create a plugin first. All commands run in your normal shell.
1. Lay out the directory
Make the marketplace folder, its .claude-plugin/ subfolder, and a plugins/ folder, then copy your plugin in:
mkdir -p brand-tools/.claude-plugin brand-tools/plugins
cp -r ~/dev/copy-check brand-tools/plugins/
Validate the plugin in its new home before going further. If anything is wrong at this stage it is a plugin problem, not a marketplace problem, and it is easier to fix now:
claude plugin validate ./brand-tools/plugins/copy-check
You want the final line to say ✔ Validation passed.
2. Write the catalogue
Create brand-tools/.claude-plugin/marketplace.json. Three top-level fields are mandatory: name, owner and plugins. Each item in plugins needs at least a name and a source.
{
"name": "brand-tools",
"description": "Writing and publishing helpers for cameronshields.co.uk",
"owner": {
"name": "Cameron Shields",
"email": "hello@example.com"
},
"plugins": [
{
"name": "copy-check",
"source": "./plugins/copy-check",
"description": "Flags US spellings, em dashes and over-long paragraphs"
}
]
}
The source path is relative to the marketplace root, which is brand-tools/ (the folder that contains .claude-plugin/), not to the JSON file itself.
3. Validate the catalogue
Point the same validate command at the marketplace directory. It parses marketplace.json, checks required fields, and validates every relative-path plugin it lists:
claude plugin validate ./brand-tools
4. Register it and install
claude plugin marketplace add ./brand-tools
claude plugin install copy-check@brand-tools
The first command records the marketplace in your user settings and confirms with a line ending (declared in user settings). The second installs at user scope. An install id is always the plugin entry's name, an @, then the marketplace name.
The same two steps work inside a session as /plugin marketplace add ./brand-tools and /plugin install copy-check@brand-tools. The slash-command version opens the plugin's detail view in the /plugin panel and you confirm the install there. Install plugins walks through that interface.
5. Check it loaded
claude plugin list
claude plugin details copy-check
list should show copy-check@brand-tools as enabled. details prints a component inventory, so you can see that the skill was picked up. Start a session and run the skill with its plugin prefix, for example /copy-check:review.
Adding more plugins
Each additional plugin is another object in the plugins array. Most entries only need three fields:
| Field | What it does |
|---|---|
name | The identifier typed before the @ at install time. Allowed characters are listed in the marketplace reference. |
source | Where to fetch the plugin: a relative path string for plugins inside the marketplace folder, or a source object for anything elsewhere. |
description | The line shown beside the plugin when someone browses your catalogue in /plugin. |
Entries can also carry many of the fields normally found in a plugin's own plugin.json. The marketplace reference lists them all and explains which wins when both are set.
Two rules that prevent most failures
When an install from a brand-new marketplace fails, it is nearly always one of these.
Relative paths start at the marketplace root
Write paths as seen from the folder holding .claude-plugin/, starting with ./. Do not try to climb out with ... The two common mistakes fail at different points:
- A path containing
..is rejected byclaude plugin validate; the message beginsPath contains "..". - A path pointing at a folder that does not exist passes validation but fails on install with
Source path does not exist: <path>, where<path>is the absolute location Claude Code looked in.
Keep the two names identical
A listed plugin has two names: the entry name in marketplace.json and the name inside its own plugin.json (the manifest name). They are used in different places:
- The entry name forms the install id, appears in
claude plugin list, and is the key written underenabledPluginsin the user's settings. - The manifest name is the prefix on the plugin's skills and the name
claude plugin detailsexpects.
If they differ and someone tries to install using the manifest name, they get Plugin "<name>" not found in marketplace "<marketplace>". Make them match and the problem cannot happen. How plugins load has more on how the two names are resolved.
Picking a source type
Every entry's source says where that one plugin lives. Choose based on where the files actually are:
| Where the plugin lives | Source to use | Example value |
|---|---|---|
| Inside the marketplace folder | Relative path | "./plugins/copy-check" |
| Its own GitHub repository | github | { "source": "github", "repo": "cshields/copy-check" } |
| A subfolder of another repo (a monorepo, say) | git-subdir | { "source": "git-subdir", "url": "cshields/site-tooling", "path": "plugins/copy-check" } |
For git-subdir, url accepts either a full git URL or the owner/repo GitHub shorthand.
Four further types exist for less common setups:
url: any git repository by URL, on any host.archive: a zip downloaded over HTTPS.npm: an npm package.command: a folder produced by running a command on the installing machine.
Git-based sources can be pinned to a ref or an exact sha. Field-by-field details for every type are in the marketplace reference.
Validate, then install for real
Run claude plugin validate ./brand-tools after every edit, and do a real install on your own machine before you share the repository. The two checks catch different classes of problem.
What validation catches
Validation only reads files inside the marketplace folder. It reports:
- Malformed JSON, as
json: Invalid JSON syntax: <reason>. - Missing required fields (a missing owner shows up as
owner: Invalid input). - Marketplace or plugin names that break the naming rules.
- Relative sources containing
... - Unrecognised fields at the top level or inside an entry, as warnings rather than errors.
- Problems inside each relative-path plugin's
plugin.json, reported asplugins[N] plugin.json → <field>: <message>.
The full message catalogue lives in the marketplace reference, and the command's flags and exit codes are on the plugin CLI reference.
What only shows up later
Some problems are invisible to validation:
- Reserved names. Official marketplace names such as
claude-plugins-officialpass validation, but adding a marketplace with one of those names is refused with a message startingThe name '<name>' is reserved for official Anthropic marketplaces. - Remote sources.
github,git-subdirand other remote sources are only fetched at install time, so a typo inrepoorpathsurfaces then. - Missing local folders. As above, a relative path to a non-existent directory fails at install.
Iterating on a plugin
Because you added the marketplace from a local folder and the plugin uses a relative path, Claude Code reads the plugin straight out of brand-tools/plugins/. Edits take effect at the next session start, or immediately after /reload-plugins, with no need to bump version.
Anyone installing from the hosted copy gets a cached snapshot instead, so they only see changes when a new version reaches them. Host a marketplace explains how updates flow.
Starting again
claude plugin marketplace remove brand-tools deletes the registration and uninstalls every plugin that came from it, which gives you a clean slate.
Sharing it
Once a local install works, push brand-tools/ to a git host. Colleagues then run claude plugin marketplace add <owner>/<repo> for a GitHub repository, or pass the full repository URL for anything else, and install plugins by name exactly as you did. Private repositories, update behaviour, versioning and renaming are all covered in Host a marketplace.