marketplace.json is the file that defines a plugin marketplace. It contains the marketplace’s name, its owner, and one entry per plugin. Each entry’s plugin source says where Claude Code fetches that plugin from.
A marketplace source is a separate object that says where Claude Code fetches the marketplace file itself. You write one in settings, or Claude Code builds one when you run claude plugin marketplace add.
This reference is for marketplace maintainers who need an exact field name or value, and for administrators who need to know which source values are valid in extraKnownMarketplaces, strictKnownMarketplaces, and blockedMarketplaces.
These cases are covered on other pages:
- Building or hosting a marketplace: see Create a marketplace and Host and maintain a marketplace
- Allowlist and blocklist recipes: see Manage plugins for your organization
- The marketplace file: Top-level fields and Plugin entries
- An entry’s
source: Plugin sources - A
sourceobject in settings: Marketplace sources - Output from
claude plugin validate <path>: Validation messages, which maps each message to the field it names
Marketplace file
Save the marketplace file at.claude-plugin/marketplace.json in your marketplace’s directory. If you keep the file somewhere else in the repository, users have to declare the marketplace in extraKnownMarketplaces with path set on its source, because claude plugin marketplace add has no option for it.
The directory that contains .claude-plugin/ is called the marketplace root, and every relative plugin source resolves from it, not from .claude-plugin/.
Each user registers one marketplace per name, so a user can’t have two marketplaces with the same name registered at once.
Claude Code ignores an unknown top-level key or plugin-entry key rather than rejecting it, so a typo loads silently. claude plugin validate reports each unknown key as a warning.
Reserved names
You can’t give your marketplace any of the following names:- Official marketplace names:
claude-code-marketplace,claude-code-plugins,claude-plugins-official,anthropic-marketplace,anthropic-plugins,agent-skills,anthropic-agent-skills,life-sciences,knowledge-work-plugins,claude-for-legal,claude-for-financial-services,financial-services-plugins,first-party-plugins, andclaude-tag-plugins. Reserved unless the marketplace comes from agithuborgitmarketplace source undergithub.com/anthropics/. - Community marketplace names:
claude-community,claude-plugins-community, andhealthcare. Reserved under the same rule as the official names. - Plugin directory names:
anthropic-plugin-directoryandclaude-plugin-directory. Reserved under the same rule as the official names. - Names that impersonate an official marketplace: names such as
official-claude-pluginsorclaude-plugins-v2, and any name containing a non-ASCII character. The error isMarketplace name impersonates an official Anthropic/Claude marketplace. A control or bidirectional-formatting character in a name also reportsMarketplace name cannot contain control or bidirectional-formatting characters. - Another spelling of a reserved name: a name that differs from a reserved name only by a trailing dot, or by a symbol other than an underscore in place of a hyphen, so
claude.code.pluginscounts asclaude-code-plugins.claude plugin validateaccepts such a name; adding the marketplace fails withis another spelling of "<reserved>", a reserved marketplace name, and a marketplace already registered under one stops loading. This check requires Claude Code v2.1.280 or later. - Names Claude Code uses for plugins that don’t come from a marketplace:
inlinefor plugins loaded with--plugin-dir,builtinfor built-in plugins,skills-dirfor plugins auto-loaded from.claude/skills/, andsyncedfor plugins synced from your claude.ai account.claude-plugin-testis also reserved.skills-diralso appears as{"source": "skills-dir"}instrictKnownMarketplacesandblockedMarketplaces, described under Source values valid only in policy lists. npm,pip,uv,cargo,github, andgh: reserved in any casing. This check requires Claude Code v2.1.275 or later.- Names starting with
claudeai-: reserved for marketplaces hosted on claude.ai.claude plugin marketplace addrefuses any other marketplace that uses one withCannot add marketplace "<name>": names starting with "claudeai-" are reserved for marketplaces hosted on claude.ai.
Top-level fields
The table lists every key Claude Code reads frommarketplace.json. name, owner, and plugins are required.
Plugin entries
Each object in the top-levelplugins array of marketplace.json names a plugin and says where to fetch it. name and source are required.
An entry also accepts every plugin.json field, such as description, version, author, commands, and hooks. For when those fields apply, see How an entry combines with plugin.json.
The table lists the entry’s own fields and the manifest fields whose meaning changes in an entry.
How an entry combines with plugin.json
The entry’s fields apply differently to a fetched plugin that has its own.claude-plugin/plugin.json and to one that doesn’t:
- No
plugin.json: the entry is the manifest regardless ofstrict. Every manifest field in the entry applies, includingmcpServers,lspServers,userConfig, andchannels. plugin.jsonpresent:plugin.jsonis the manifest. Strict mode decides whether the entry’s six component fields,commands,agents,skills,hooks,outputStyles, andthemes, are combined with it or rejected as a conflict. EntrymcpServers,lspServers,userConfig, andchannelsdon’t apply. Declare them inplugin.json.
Hooks in an entry
Write entryhooks as an inline object that maps hook event names to matcher arrays. If you write a file path or an array instead, claude plugin validate passes it. Those hooks never run, and Claude Code reports a not yet supported in a marketplace entry error for the plugin. Put file-based hooks in the plugin’s own hooks/hooks.json or plugin.json.
Display fields
Both the entry and the plugin’s ownplugin.json can set the display fields displayName, description, author, homepage, repository, license, and keywords. Users see these values in plugin listings and details, before and after install:
- For a field you set on the entry, users see the entry’s value, even when
plugin.jsonsets a different one. - For a field the entry leaves unset, users see the
plugin.jsonvalue.
plugin.json only for entries with a relative-path source, whose plugin files are inside the marketplace itself. For an entry with any other source type, users see only the entry’s own fields until they install the plugin.
Strict mode
strict decides what happens when the fetched plugin has its own plugin.json and the entry also declares any of the component fields: commands, agents, skills, hooks, outputStyles, or themes. With strict: true, the default, Claude Code appends the entry’s component fields to plugin.json, except hooks, whose matchers replace the manifest’s per event. With strict: false, an entry that declares any component field is a conflict, and the plugin fails to load. The table shows each combination of strict, plugin.json, and the entry’s component fields.
Plugin sources
A plugin entry’ssource says where Claude Code fetches that one plugin from. It’s either a relative path string or an object whose own source key names the type, so an entry looks like "source": { "source": "github", "repo": "your-org/formatter" }.
The table lists each plugin source type and its fields.
The names
url and github are also marketplace source types, where url means a direct link to a marketplace.json file rather than a git repository. git exists only as a marketplace source, and npm exists as both. git-subdir, archive, and command exist only as plugin sources.
Use a relative path for a plugin in a subdirectory of the marketplace repository itself. Use git-subdir for a subdirectory of some other repository.
github, url, and git-subdir sources share the ref and sha fields:
ref: a branch or tag. Defaults to the repository’s default branch.sha: a full 40-character lowercase commit SHA. When you set bothrefandsha, Claude Code checks outsha. On most git hosts, including GitHub, GitLab, and Bitbucket, this means installation succeeds even if the branch or tag named byrefhas since been deleted upstream, as long as the commit is still reachable from the repository. Some servers, such as AWS CodeCommit, don’t support fetching commits by SHA. On those servers therefmust still exist and the pinned commit must be reachable from it.
Relative path plugin source
The path resolves from the marketplace root../plugins/formatter is <root>/plugins/formatter even though the marketplace file is in <root>/.claude-plugin/.
A path containing .. fails validation. On macOS and Linux, Claude Code refuses an entry path that contains a backslash anywhere after the leading ./, so write the path with forward slashes.
github,git,file, anddirectory: Claude Code has the marketplace’s files.url: Claude Code fetches onlymarketplace.json, so relative paths can’t resolve. Give each plugin an object source instead, such asgithuborgit-subdir.settings: relative paths are rejected outright.
Bare names under pluginRoot
A bare name is a single directory name with no/, such as "formatter". To write bare names instead of ./ paths, set metadata.pluginRoot to the directory they resolve under. With "pluginRoot": "./plugins", "source": "formatter" resolves to ./plugins/formatter. Requires Claude Code v2.1.239 or later.
metadata.pluginRoot has these limits:
- It must itself be a relative path inside the marketplace.
- It has no effect on a source that already starts with
./. - A source that contains a
/, such asteam-a/formatter, isn’t a bare name and still needs the./prefix, even whenmetadata.pluginRootis set.
github plugin source
repo takes owner/repo. ref and sha are optional.
url plugin source
url is a full git URL: https://, http://, file://, or git@. A .git suffix isn’t required, so Azure DevOps and AWS CodeCommit URLs work as written. This type doesn’t take owner/repo shorthand.
git-subdir plugin source
url accepts a full git URL or GitHub owner/repo shorthand. path is the subdirectory that holds the plugin, and Claude Code downloads only that subdirectory.
npm plugin source
Annpm source takes these fields:
package: a package name, or a scoped name such as@your-org/formatterversion: a version or rangeregistry: a registry URL for a package that isn’t on the default registry
preinstall or postinstall, never run, and its dependencies aren’t installed during the fetch. If the package has a supported lockfile beside its package.json, Claude Code installs those Node.js package dependencies in a separate step, also with scripts disabled.
archive plugin source
url must use https:// and can’t point at a loopback, link-local, or cloud-metadata host.
The plugin root may be at the top of the zip or one directory down.
sha256 is the archive’s digest as 64 hex characters, uppercase or lowercase. When you set it, Claude Code refuses a download that doesn’t match.
command plugin source
Use acommand source when a tool installed on the user’s machine produces the plugin directory, such as an IDE that renders its plugin for the toolchain the user has selected. Claude Code runs the command when the user installs or updates the plugin, and again once per session, so users get the tool’s changed output without reinstalling.
A command source takes these fields:
command: a shell command that prints the plugin directory’s absolute path as one line and exits 0. Claude Code shows users the whole string for review before it runs. Write it as printable ASCII, at most 500 characters, with no run of four or more spaces.timeout: a whole number of seconds from 1 to 600. Defaults to 60.mode:copy, the default, orlink. See Copy mode and link mode.
disableCommandPluginSources.
What the command must do
Write the command to meet these requirements:- Shell and working directory: Claude Code runs the command through
sh, or throughcmd.exeon Windows, from the user’s home directory. Give an absolute path or a command onPATH. - Output: print exactly one line on stdout, the absolute path of the plugin directory, and exit 0 within
timeoutseconds. - Directory contents: the directory holds the complete plugin by the time the command exits. The path can differ from one run to the next.
Output that fails the install or update
The install or update fails when the command exits non-zero, runs longer thantimeout, or prints anything other than one absolute path. It also fails when the printed directory is one of these:
- No plugin content: the printed directory has no plugin content at its top level, such as a
.claude-plugin/directory or askills/,commands/,agents/, orhooks/directory. - The session’s own directory: the printed directory is the one Claude Code was started in, or one of its parents.
- A network path: on Windows, the printed path is a UNC path.
- Too large to copy: in copy mode, the directory is larger than 256 MiB or has more than 20,000 entries.
Copy mode and link mode
mode decides whether Claude Code copies the printed directory or uses it in place:
copy: Claude Code copies the directory into the plugin cache and derives the plugin version from a hash of the copied files. Your tool can delete or rewrite the directory after the command exits. A re-run that produces identical files counts as up to date.link: Claude Code fills the plugin’s cache entry with a link to each top-level entry of the printed directory and loads the files in place. Nothing is copied, file contents aren’t hashed, and the size limits don’t apply. Use it for a directory too large to copy, such as a rendered SDK export.
- Keep the directory in place: Claude Code loads the plugin through the links at every startup, so the printed directory must stay where it is for as long as the plugin stays installed.
- Print a different path to signal new content: the version comes from the printed directory’s real path and its top-level entries, not from the files inside them.
- Keep top-level symlinks inside the directory: the install fails if a top-level entry is a symlink that points outside the printed directory.
- Include
node_modules: Claude Code skips the Node.js package dependency install for a link-mode plugin, so print a directory that already contains the packages the plugin needs. - Sessions started inside the directory: a session started in the printed directory or anywhere below it doesn’t load the plugin.
- Not on Windows: Claude Code refuses to install a link-mode plugin on Windows. Declare
"mode": "copy"there.
Marketplace sources
A marketplace source says where Claude Code fetches amarketplace.json from. The CLI builds one for you when you add a marketplace, and you write one yourself in settings:
claude plugin marketplace add: Claude Code builds the source from the string you pass.extraKnownMarketplaces: you write the source yourself as thesourceobject.strictKnownMarketplacesandblockedMarketplaces: administrators write sources in these two policy lists.strictKnownMarketplacesis the allowlist andblockedMarketplacesis the blocklist.
url, git, and github mean something different in a marketplace source than in a plugin source:
The table lists every marketplace source type with its fields, the
claude plugin marketplace add input that produces it, and what it does in each of the three settings keys.
Fields by type
The table lists each marketplace source field that has a default, a constraint, or a meaning specific to its type.Source values valid only in policy lists
hostPattern, pathPattern, skills-dir, and the owner/* form of repo are valid only in the two policy lists, strictKnownMarketplaces and blockedMarketplaces:
hostPatternandpathPattern: regular expressions Claude Code tests against a source before it fetches from it.skills-dir: not a source. If you setstrictKnownMarketplacesat all, skills-directory plugins stop loading until you add{"source": "skills-dir"}to that list.owner/*: as agithubrepovalue, matches every repository under exactly that GitHub owner. Requires Claude Code v2.1.223 or later.
ref semantics, and recipes, see Manage plugins for your organization.
Source objects in settings
AnextraKnownMarketplaces value is a map from marketplace name to an object with source. This entry registers a marketplace from a git repository at its main branch:
strictKnownMarketplaces and blockedMarketplaces are arrays of source objects. This allowlist admits one GitHub owner and one internal host:
Validation messages
claude plugin validate <path> takes the marketplace root or the marketplace file itself. It prints errors and warnings. For exit codes and --strict, see plugin validate.
A message names a plugin entry by its index, written as plugins.1.source or plugins[1].source.
A message prefixed with an entry index and plugin.json →, such as plugins[2] plugin.json →, is about that plugin’s own files. claude plugin validate reports errors lists those messages with their fixes.
Warnings that mention Claude Desktop flag names that Claude Code accepts but Claude Desktop rejects, because Claude Desktop’s name rules are stricter.
The table maps marketplace-level messages to the field each is about.
Invalid input on a source
Invalid input on a source means the object matched no source type. Check for these causes:
- A relative path that doesn’t start with
./, other than"."or a bare name undermetadata.pluginRoot - An
npmpackagecontaining.. - A
sourcetype that isn’t one of the plugin sources - A known type with a required field missing or of the wrong type, such as
githubwithoutrepo
Failures that validation doesn’t catch
claude plugin validate doesn’t report every failure. An entry hooks written as a file path or array passes validation, and the error appears only when the plugin loads, as Hooks in an entry describes. Errors fetching a source also appear only after install, not in validation.
claude plugin list shows a plugin that failed to load with its error, and Troubleshoot plugins covers the load-time strings.
Next steps
- Create a marketplace: build a marketplace from these fields and install from it locally
- Host and maintain a marketplace: where to put the file and how users receive changes
- Plugin manifest reference: the
plugin.jsonfields an entry can override - Manage plugins for your organization: allowlist and blocklist recipes that use these source values