One read of Claude Code CLIclaude-code-20260925T000701Z
86 pages moved out of 210 read.
What this read moved
26-50 of 86, page 2 of 4This capture is too large to show at once. Changes 26-50 of 86 are below, significant first; the rest are on the following screens.
plugin-hints Page removed · 152 lines, page removed
# Recommend your plugin from your CLI ## How it works ## Emit the hint ## Choose where to emit ## What the user sees ## Hint format ## Requirements ## Get your plugin into the official marketplace ## See also
The page is gone upstream. What it last said is kept here.
plugin-marketplaces Page removed · 1547 lines, page removed
# Create and distribute a plugin marketplace ## Overview ## Walkthrough: create a local marketplace ## Create the marketplace file ## Marketplace schema ### Required fields ### Reserved marketplace names ### Owner fields ### Optional fields ## Plugin entries ### Required fields ### Optional plugin fields ## Plugin sources ### Relative paths ### GitHub repositories ### Git repositories ### Git subdirectories ### npm packages ### Zip archives #### Authenticate archive downloads ##### Add a headersHelper to a plugin entry #### Write the headersHelper command #### When Claude Code skips a headersHelper command or drops its output #### How users accept a headersHelper command ##### Installs and updates that refuse the command instead of asking ##### When a marketplace `url` source's command runs ### Command sources #### Copy mode and link mode #### How users accept the command #### When Claude Code re-runs the command ### Advanced plugin entries ### Strict mode ## Host and distribute marketplaces ### Host on GitHub (recommended) ### Host on other git services ### Private repositories #### Commands you run #### Background auto-updates ### Distribute through organization settings #### Sync a GitLab-hosted marketplace #### Keep executables out of the top-level bin directory ### Require marketplaces for your team ### Pre-populate plugins for containers ### Managed marketplace restrictions #### Common configurations #### How restrictions work ### Version resolution and release channels #### Set up release channels ##### Example ##### Assign channels to user groups #### Pin dependency versions ### Rename or remove a plugin ## Validation and testing ## Manage marketplaces from the CLI ### Plugin marketplace add ### Plugin marketplace list ### Plugin marketplace remove ### Plugin marketplace update ## Troubleshooting ### Marketplace not loading ### Marketplace validation errors #### Validate a plugin or a directory without a manifest ##### Pick the directory to name ##### Check a plugin whose skill is its root `SKILL.md` ##### Check files behind symlinks ##### Read the validation results ### Plugin installation failures ### Private repository authentication fails ### Marketplace updates fail in offline environments ### Git operations time out ### Plugins with relative paths fail in URL-based marketplaces ### Files not found after installation ## See also
The page is gone upstream. What it last said is kept here.
plugin-relevance Page removed · 166 lines, page removed
# Recommend plugins for your org ## How it works ## Add relevance to a plugin entry ## Field reference ### `relevance` ### `relevance.signals` ## Enable suggestions in managed settings ## What the user sees ## Validate your marketplace ## See also
The page is gone upstream. What it last said is kept here.
plugins Page removed · 481 lines, page removed
# Create plugins ## When to use plugins vs standalone configuration ## Quickstart ### Prerequisites ### Create your first plugin ## Develop a plugin in your skills directory ## Plugin structure overview ## Develop more complex plugins ### Add Skills to your plugin ### Add LSP servers to your plugin ### Add background monitors to your plugin ### Ship default settings with your plugin ### Organize complex plugins ### Test your plugins locally ### Debug plugin issues ### Share your plugins ### Submit your plugin to the community marketplace ## Convert existing configurations to plugins ### Migration steps ### What changes when migrating ## Next steps ### For plugin users ### For plugin developers
The page is gone upstream. What it last said is kept here.
plugins-reference Page removed · 1538 lines, page removed
# Plugins reference ## Plugin components reference ### Skills ### Agents #### Plugin agent frontmatter ### Hooks ### MCP servers ### LSP servers ### Monitors ### Themes ## Plugin installation scopes ## Skills-directory plugins ### Choose where the plugin loads from ### Edit, reload, and disable a skills-directory plugin ## Plugin manifest schema ### Complete schema ### Required fields ### Unrecognized fields ### Metadata fields ### Default enablement ### Component path fields ### Experimental components ### User configuration #### Limit a field to fixed options ### Channels ### Path behavior rules ### Environment variables #### Persistent data directory ## Plugin caching and file resolution ### Node.js package dependencies ### Path traversal limitations ### Share files within a marketplace with symlinks ## Plugin directory structure ### Standard plugin layout ### File locations reference ## CLI commands reference ### plugin init ### plugin install ### plugin uninstall ### plugin prune ### plugin enable ### plugin disable ### plugin update ### plugin list ### plugin details ### plugin validate ### plugin eval ### plugin eval init ### plugin tag ## Debugging and development tools ### Debugging commands ### Common issues ### Example error messages ### Hook troubleshooting ### MCP server troubleshooting ### Directory structure mistakes ## Distribution and versioning reference ### Version management ## See also
The page is gone upstream. What it last said is kept here.
plugins/anthropic-marketplaces New page · 85 lines, new page
# Anthropic's marketplaces ## Anthropic's marketplaces ### The demo marketplace in `anthropics/claude-code` ## Find plugins in the official marketplace ## Browse and install from Anthropic's marketplaces ### Add the community or demo marketplace ## Third-party marketplaces ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Anthropic's marketplaces > Anthropic's official, community, and demo plugin marketplaces for Claude Code: their names, repositories, how you add each, and where to browse their plugins. Anthropic publishes three general-purpose plugin marketplaces for Claude Code: [official](https://github.com/anthropics/claude-plugins-official), [community](https://github.com/anthropics/claude-plugins-community), and [demo](https://github.com/anthropics/claude-code). Each is a catalog of plugins in its own GitHub repository. When you install a plugin from one of them in a Claude Code session, you type the marketplace's name after `@`, as in `/plugin install commit-commands@claude-plugins-official`. Use this page to distinguish the three marketplaces and to find where to check whether the official one holds a given plugin. <Note> These cases are covered on other pages: * **How to install a plugin**: see [Install plugins](/docs/en/plugins/install) * **A failed install**: see [Troubleshoot plugins](/docs/en/plugins/troubleshooting) </Note> Go to the part of the page you need: * To distinguish the three marketplaces by repository, marketplace name, and how you get each one, see [Anthropic's marketplaces](#anthropic’s-marketplaces). * To find a plugin in the official marketplace, see [Find plugins in the official marketplace](#find-plugins-in-the-official-marketplace). ## Anthropic's marketplaces A marketplace is a catalog of plugins that a repository defines in its `.claude-plugin/marketplace.json` file. The official, community, and demo marketplaces each come from their own GitHub repository. Anthropic also publishes topic-specific marketplaces, such as `anthropics/skills` and `anthropics/knowledge-work-plugins`, which you add in a Claude Code session with `/plugin marketplace add <owner>/<repo>`. This table gives each marketplace's repository and marketplace name, which is what you type after `@` when you install a plugin from that marketplace. The community marketplace's name is `claude-community`, not its repository name. | | Official | Community | Demo | | :--------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------- | | Repository | [`anthropics/claude-plugins-official`](https://github.com/anthropics/claude-plugins-official) | [`anthropics/claude-plugins-community`](https://github.com/anthropics/claude-plugins-community) | [`anthropics/claude-code`](https://github.com/anthropics/claude-code/tree/main/plugins) | | Marketplace name | `claude-plugins-official` | `claude-community` | `claude-code-plugins` | | What's in it | Plugins Anthropic maintains, plus plugins from partners and other authors | Third-party plugins that their authors submitted to Anthropic | A small set of example plugins that show what a plugin can contain | | How you get it | Claude Code adds it the first time you start an interactive terminal session, unless a [managed policy](/docs/en/plugins/org#allow-the-official-marketplace-and-your-own) or `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL` blocks it. See [Marketplace `claude-plugins-official` not found](/docs/en/plugins/troubleshooting#marketplace-claude-plugins-official-not-found) if it's missing | You add it in a Claude Code session with `/plugin marketplace add anthropics/claude-plugins-community` | You add it in a Claude Code session with `/plugin marketplace add anthropics/claude-code` | If you wrote a plugin and want other people to install it, see [Publish a plugin](/docs/en/plugins/publish), which covers your own marketplace and submitting to the community marketplace. ### The demo marketplace in `anthropics/claude-code` If a tutorial or an older set of instructions tells you to run `/plugin marketplace add anthropics/claude-code`, that adds the demo marketplace, named `claude-code-plugins`. It isn't the official marketplace, which Claude Code already added for you. Most of the demo marketplace's plugins are also in the official marketplace under the same names. For example, `code-review`, `feature-dev`, `commit-commands`, and `security-guidance` are in both. Install those from `claude-plugins-official` so you don't have two copies installed. ## Find plugins in the official marketplace The official marketplace, `claude-plugins-official`, is the one Claude Code adds for you. Most of what it lists comes from partners and other authors rather than from Anthropic: tool vendors publish plugins that connect Claude Code to their services, and Anthropic maintains a smaller set of its own, such as `commit-commands`, `code-review`, `feature-dev`, and the [language server plugins](/docs/en/plugins/code-intelligence). The catalog changes often, so this page doesn't list it. To see what's in it, use the **Discover** tab of `/plugin` in a Claude Code session, which you can search, or browse [Claude Marketplace](https://claude.com/marketplace/plugins) on the web. ## Browse and install from Anthropic's marketplaces You can search Anthropic's marketplaces for a plugin in Claude Code, on the web, or on GitHub: * **In Claude Code, by browsing**: run `/plugin` in an interactive session. Its **Discover** tab lists the plugins from the marketplaces you've added. * **In Claude Code, by name**: run `/plugin install <name>` in a session, which looks the name up in the marketplaces you've added. If the plugin is in one of them, its details open in the `/plugin` panel, and nothing installs until you choose an [installation scope](/docs/en/plugins/install#install-a-plugin) and confirm there. If it isn't, you see `Plugin "<name>" not found in any marketplace`. * **On the web**: search the full catalog on [Claude Marketplace](https://claude.com/marketplace/plugins), which shows install counts and marks some plugins **Anthropic verified**. * **On GitHub**: open `.claude-plugin/marketplace.json` in the marketplace's repository, such as [`anthropics/claude-plugins-official`](https://github.com/anthropics/claude-plugins-official). That file is the catalog itself. To install from the desktop app or from a script, or to see what a cloud session loads, see [Install plugins](/docs/en/plugins/install). ### Add the community or demo marketplace The community and demo marketplaces aren't registered until you add them in a Claude Code session: * **Community**: run `/plugin marketplace add anthropics/claude-plugins-community`, then install with the `@claude-community` suffix. * **Demo**: run `/plugin marketplace add anthropics/claude-code`, then install with the `@claude-code-plugins` suffix. If `claude-plugins-official` isn't on the **Marketplaces** tab of `/plugin`, add it the same way with `/plugin marketplace add anthropics/claude-plugins-official`. For `not found` errors and marketplaces that won't add, see [Troubleshoot plugins](/docs/en/plugins/troubleshooting#install-a-plugin). ## Third-party marketplaces Many popular plugins aren't in any Anthropic marketplace. They're in their authors' own marketplaces, usually a GitHub repository with a `.claude-plugin/marketplace.json` at its root. Anthropic doesn't review third-party marketplaces, so read [Plugin security and trust](/docs/en/plugins/security) before you add one. To use a third-party marketplace, add its repository in a Claude Code session with `/plugin marketplace add <owner>/<repo>`, then install with `/plugin install <plugin>@<marketplace-name>`. The marketplace name is the `name` field of that `marketplace.json`, and Claude Code prints it once it has added the marketplace. For other ways to add a marketplace, see [Add a marketplace](/docs/en/plugins/install#add-a-marketplace). ## Next steps * [Install and manage plugins](/docs/en/plugins/install): install a plugin from one of these marketplaces and choose a scope * [Plugin security and trust](/docs/en/plugins/security): what a plugin can do on your machine and how to review one before you install it * [Code intelligence plugins](/docs/en/plugins/code-intelligence): install one of the official marketplace's language-server plugins * [Create a marketplace](/docs/en/plugins/create-marketplace): run your own marketplace alongside Anthropic's
plugins/cli-hints New page · 122 lines, new page
# Recommend your plugin from your CLI ## Emit the hint ## Hint format ## Check when the prompt appears ## Preview what the user sees ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Recommend your plugin from your CLI
> Prompt Claude Code users to install your official-marketplace plugin by emitting a claude-code-hint tag from your CLI or SDK.
If you maintain a CLI or SDK, your tool can prompt Claude Code users to install your plugin. When your CLI detects that it's running inside Claude Code, have it write a one-line `<claude-code-hint />` tag to stderr. Claude Code removes the line from Bash and PowerShell tool output before the model sees the output, then shows the user a one-time install prompt.
This page applies only if your plugin is listed in `claude-plugins-official` or another marketplace with one of Anthropic's [official marketplace names](/docs/en/plugins/security#official-marketplace-names). The community marketplace, `claude-community`, isn't one of them.
<Note>
To publish a plugin, see [Publish and distribute a plugin](/docs/en/plugins/publish).
</Note>
## Emit the hint
Emit the tag only when `CLAUDECODE` or `CLAUDE_CODE_CHILD_SESSION` is set, so it doesn't appear when a person runs your CLI directly.
Claude Code sets `CLAUDECODE=1` in the commands it runs through the Bash and PowerShell tools and in hook commands. On v2.1.172 and later it also sets `CLAUDE_CODE_CHILD_SESSION=1` there. The variables differ in which processes carry them:
* **`CLAUDECODE`**: set by every Claude Code version. IDE extensions also set it in their integrated terminals, so a gate on `CLAUDECODE` alone also emits the tag when a person runs your CLI themselves in one of those terminals
* **`CLAUDE_CODE_CHILD_SESSION`**: set only in subprocesses Claude Code itself starts. Use it when you can require v2.1.172 or later
The [environment variables reference](/docs/en/env-vars) has the details.
The following examples gate on `CLAUDECODE` for the widest reach and emit a hint for a plugin named `example-cli` in the official marketplace:
<CodeGroup>
```javascript Node.js theme={null}
if (process.env.CLAUDECODE) {
process.stderr.write(
'<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />\n',
)
}
```
```python Python theme={null}
import os, sys
if os.environ.get("CLAUDECODE"):
print(
'<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />',
file=sys.stderr,
)
```
```go Go theme={null}
if os.Getenv("CLAUDECODE") != "" {
fmt.Fprintln(os.Stderr,
`<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />`)
}
```
```shell Shell theme={null}
if [ -n "$CLAUDECODE" ]; then
printf '%s\n' '<claude-code-hint v="1" type="plugin" value="example-cli@claude-plugins-official" />' >&2
fi
```
</CodeGroup>
Replace `example-cli` with your plugin's name in the official marketplace.
You can emit the hint on every invocation, because Claude Code prompts for each plugin once.
To check the emitter, run `CLAUDECODE=1 example-cli` in a terminal and confirm the tag line appears on stderr, then run `example-cli` without the variable and confirm nothing extra prints.
## Hint format
The tag must occupy its own line; Claude Code ignores a tag embedded mid-line.
The tag takes three attributes, all required:
| Attribute | Description |
| :-------- | :------------------------------------------------ |
| `v` | Protocol version. `1` is the only supported value |
| `type` | Hint kind. `plugin` is the only supported value |
| `value` | Plugin identifier in `name@marketplace` form |
Values may be double-quoted or unquoted; an unquoted value can't contain whitespace.
Claude Code removes the line from the output even when `v` or `type` is unrecognized.
## Check when the prompt appears
The prompt appears only in interactive terminal sessions. In `claude -p` runs, in subagent runs, and in hook command output, the tag is stripped and no prompt is shown. All of these checks must also pass:
* **Official and installable**: `value` names a plugin that Claude Code finds in its local copy of an official marketplace, that isn't already installed, and that no policy blocks
* **Analytics on**: a session where Claude Code's analytics are off never prompts, for example one with `DISABLE_TELEMETRY`, `DO_NOT_TRACK`, or `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` set, or one on a third-party provider such as Amazon Bedrock, where the [automatic telemetry opt-out](/docs/en/data-usage#default-behaviors-by-api-provider) applies
* **Frequency limits**: one prompt per session, one prompt ever per plugin regardless of the user's answer, and none once 100 plugins have been prompted for on that machine
* **Not turned off**: the user hasn't chosen **No, and don't show plugin installation hints again**
* **Local, attended session**: the session's workspace is local rather than on a cloud or remote machine, and the session isn't running unattended. For example, a session started with `--cloud`, one serving Remote Control, or an agent-team teammate never prompts
## Preview what the user sees
When the checks in [Check when the prompt appears](#check-when-the-prompt-appears) pass, Claude Code shows a **Plugin recommendation** dialog like the following:
```text theme={null}
─────────────────────────────────────────────────────────────
Plugin recommendation
The example-cli command suggests installing a plugin.
Plugin: example-cli
Marketplace: claude-plugins-official
Description: Official integration for example-cli deployments
Would you like to install it?
❯ 1. Yes, install
2. No
3. No, and don't show plugin installation hints again
─────────────────────────────────────────────────────────────
```
The dialog names the first word of the shell command Claude ran, so users can spot a mismatch. Each answer has one effect:
* **Yes, install**: installs the plugin at [user scope](/docs/en/plugins/install)
* **No, and don't show plugin installation hints again**: turns off future hint prompts for that user
* **No answer for 30 seconds**: counts as **No**
## Next steps
* [Publish and distribute a plugin](/docs/en/plugins/publish): the routes into each marketplace, including the official marketplace, which the hint requires
* [Plugin commands reference](/docs/en/plugins/cli-reference#plugin-install): the shell command that installs the same plugin outside a session
plugins/cli-reference New page · 783 lines, new page
# Plugin commands reference ## claude plugin commands ### plugin init ### plugin install #### Accept a displayed install command ### plugin uninstall ### plugin enable ### plugin disable ### plugin update ### plugin list #### JSON output ### plugin details ### plugin prune ### plugin eval ### plugin eval init ### plugin tag ### plugin validate #### Validate a directory #### Output and exit codes ## claude plugin marketplace commands ### plugin marketplace add ### plugin marketplace list ### plugin marketplace remove ### plugin marketplace update ### Reload summary ### Reloads that change MCP tools ### Sessions without an interactive terminal ## Flags that load a plugin for one session ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Plugin commands reference
> Complete reference for the claude plugin shell commands, /plugin and /reload-plugins in a session, and the flags that load a plugin for one session.
You run plugin commands either as `claude plugin` from your shell or a script, or as `/plugin` and `/reload-plugins` inside a Claude Code session. This reference gives each command's flags, defaults, output, and exit codes, along with the two flags that load a plugin for one session.
Run `claude plugin --help` on your build to confirm which subcommands your version has.
<Note>
These cases are covered on other pages:
* **Install and manage steps, and where `/plugin` runs**: see [Install and manage plugins](/docs/en/plugins/install)
* **What a command changes on disk and which scope takes precedence**: see [Plugin loading reference](/docs/en/plugins/loading)
* **What an error message means**: see [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
</Note>
## claude plugin commands
Run `claude plugin <subcommand>` from your shell or a script, outside a Claude Code session. These subcommands install and manage plugins without opening the [`/plugin`](#plugin-in-a-session) panel.
`claude plugins` is an alias for `claude plugin`.
Every subcommand shares these exit codes, plugin arguments, and scope values:
* **Exit codes**: `0` on success and `1` on failure. `validate` adds exit `2` for an unexpected error, and `eval` adds the codes listed in [its section](#plugin-eval).
* **Plugin arguments**: a `<plugin>` argument is a plugin `name` or `name@marketplace`. When two marketplaces offer the same name, use the qualified form.
* **Scopes**: `--scope` takes `user`, `project`, or `local`, and names the settings file the command writes to. `update` also takes `managed`.
### plugin init
Scaffold a new plugin at `~/.claude/skills/<name>/`. It loads in your next session as `<name>@skills-dir` with no install step.
`new` is an alias for `init`.
For the create, test, and edit workflow that begins with this command, see [Create a plugin](/docs/en/plugins/create).
```bash theme={null}
claude plugin init <name> [options]
```
`<name>` becomes the directory name under `~/.claude/skills/` and the plugin's `name` in its manifest.
The command has no flag for another location. To scaffold inside a project instead, see [Create a plugin](/docs/en/plugins/create).
| Flag | Description |
| :----------------------- | :------------------------------------------------------------------------------------------------------ |
| `--description <text>` | Manifest description |
| `--author <name>` | Author name. Defaults to `git config user.name` |
| `--author-email <email>` | Author email. Defaults to `git config user.email` |
| `--with <components...>` | Also scaffold starter files for `skills`, `agents`, `hooks`, `mcp`, `lsp`, `output-style`, or `channel` |
| `-f, --force` | Overwrite an existing `.claude-plugin/` at the target |
Scaffold a plugin with starter skill and hook files:
```bash theme={null}
claude plugin init my-helper --with skills hooks
```
Claude Code validates what it wrote and prints `Created plugin "my-helper" at ~/.claude/skills/my-helper`, followed by the id it loads as and the `claude plugin disable` command that turns it off.
Claude Code exits `1` without writing when it can't scaffold safely, and the message names the reason. These are common reasons:
* An unknown `--with` value
* An existing scaffold at the target without `--force`
* A managed setting that blocks skills-directory plugins
### plugin install
Install a plugin from a marketplace you've added. `i` is an alias for `install`.
```bash theme={null}
claude plugin install <plugin> [options]
```
Most plugins install without a prompt. For a plugin whose marketplace entry [runs a command to install it](/docs/en/plugins/host-marketplace) or [sets a `headersHelper` for its download](/docs/en/plugins/host-marketplace#how-users-accept-a-headershelper-command), Claude Code first prints the command and asks `Run this command now? [y/N]`.
| Flag | Description |
| :-------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-s, --scope <scope>` | Installation scope: `user`, `project`, or `local`. Defaults to `user` |
| `--config <key=value>` | Set a [`userConfig`](/docs/en/plugins/manifest-reference) option the plugin's manifest declares. Repeat the flag for each option. Requires Claude Code v2.1.147 or later |
| `-y, --yes` | Accept the displayed install command without the `Run this command now?` prompt. Ignored when the command runs inside a Claude Code session, such as from the Bash tool or a hook. Requires Claude Code v2.1.229 or later |
| `--accept-command <sha256>` | Accept the displayed install command whose `sha256` a previous [`--json` run](#plugin-json-result) reported in `shownCommand`, in place of `-y`. Can't be combined with `-y`. See [Accept a displayed install command](#accept-a-displayed-install-command). Requires Claude Code v2.1.271 or later |
| `--json` | Print the result as one JSON object on the last line of stdout instead of the human-readable message, for use in scripts. See [JSON result format](#plugin-json-result). Requires Claude Code v2.1.268 or later |
Pass `-y` from your own terminal to accept the displayed command without the prompt. Here's what happens without a TTY and when Claude runs the command:
* **stdin or stdout isn't a TTY, and you pass neither `-y` nor `--accept-command`**: the install is refused. The output says the command was only displayed, and the exit code is `1`
* **Claude runs the command through its Bash tool**: `-y` is ignored. Run the command from your own terminal instead
Install a plugin for everyone who clones the project:
```bash theme={null}
claude plugin install formatter@my-marketplace --scope project
```
Claude Code prints `Successfully installed plugin: formatter@my-marketplace (scope: project)`. When nothing new is installed, the output says why:
* **Already installed at that scope**: the output is `Plugin "formatter@my-marketplace" is already installed (scope: project)` and the exit code is `0`
* **You decline a command-source prompt**: the output is `Aborted.` and the exit code is `1`
* **You decline a `headersHelper` prompt, or it can't be confirmed without a TTY**: the output is `Aborted — the command was not run.` and the exit code is `1`
<h4 id="plugin-json-result">
JSON result format
</h4>
When you pass `--json` to `plugin install`, the last line of stdout is one JSON object. Parse only that line, because Claude Code prints any command the marketplace declares ahead of it.
Three fields are always present:
* `command`: the subcommand that ran, such as `install`
* `outcome`: `ok` or `failed`
* `message`: a human-readable description of the result
Other fields, such as `pluginId`, `scope`, and `failureCode`, appear only when they apply.
The `--json` option on `plugin uninstall`, `plugin update`, `plugin enable`, and `plugin disable` prints the same object with that subcommand's own fields.
A usage error, such as an invalid `--scope`, prints no result line and exits `1` with the reason on stderr.
#### Accept a displayed install command
When a `--json` run displays a marketplace-declared command and doesn't run it, the `failed` result also carries a `shownCommand` object. Its fields include the command as displayed, the plugin it belongs to, and the command's `sha256`.
To accept exactly that command, re-run with that `sha256` as `--accept-command` from your own terminal, because the flag has no effect inside a Claude Code session. Requires Claude Code v2.1.271 or later.
The `sha256` counts as acceptance for exactly that command, plugin, and marketplace catalog. If any of them changed since the command was displayed, Claude Code doesn't accept the `sha256` and shows the command again. A change that the run's own marketplace refresh fetches also counts as such a change.
If `shownCommand.acceptCommandMatched` is `false`, the `sha256` you passed doesn't match the command now displayed. Review that command before re-running with its `sha256`.
### plugin uninstall
Remove an installed plugin from one scope. `remove` and `rm` are aliases for `uninstall`.
```bash theme={null}
claude plugin uninstall <plugin> [options]
```
| Flag | Description |
| :-------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-s, --scope <scope>` | Uninstall from scope: `user`, `project`, or `local`. Defaults to `user` |
| `--keep-data` | Preserve the plugin's persistent data directory, `~/.claude/plugins/data/<id>/` |
| `--prune` | Also remove auto-installed [dependencies](/docs/en/plugins/dependencies) that no remaining plugin needs |
| `-y, --yes` | Skip the `--prune` confirmation prompt. Required with `--prune` when stdin or stdout isn't a TTY |
| `--json` | Print the result as one JSON object on the last line of stdout, in the [same format as `plugin install --json`](#plugin-json-result). Can't be combined with `--prune`. Requires Claude Code v2.1.268 or later |
Uninstall a plugin from project scope:
```bash theme={null}
claude plugin uninstall formatter@my-marketplace --scope project
```
Claude Code prints `Successfully uninstalled plugin: formatter (scope: project)`. When the plugin isn't installed at that scope, the command prints a line that starts `Failed to uninstall plugin "formatter@my-marketplace":` and exits `1`.
### plugin enable
Enable a disabled plugin. For a [plugin synced from claude.ai](/docs/en/plugins/loading#synced-plugins), pass `<name>@synced` as the plugin.
```bash theme={null}
claude plugin enable <plugin> [options]
```
| Flag | Description |
| :-------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-s, --scope <scope>` | Scope to enable at: `user`, `project`, or `local`. Auto-detected when omitted |
| `--json` | Print the result as one JSON object on the last line of stdout, in the [same format as `plugin install --json`](#plugin-json-result). Requires Claude Code v2.1.268 or later |
Without `--scope`, the command checks your settings files in the order local, project, user, and uses the first scope that mentions the plugin.
If you pass a `--scope` where the plugin isn't declared, the command either writes an override or fails:
* **A scope that [takes precedence](/docs/en/plugins/loading) over the declaring one**: Claude Code writes an override at the scope you passed. For example, `claude plugin disable formatter --scope local` turns off a project-enabled plugin for you alone
* **Any other scope**: the command fails with `Plugin "formatter" is installed at project scope, not user. Use --scope project or omit --scope to auto-detect.`
If the plugin is already enabled at the resolved scope, the command prints `Plugin "formatter" is already enabled` and exits `1`. With `--json`, the result has `"failureCode": "already_in_goal_state"` and `"alreadyInGoalState": true`, so a script can treat that case as success.
When the plugin declares [dependencies](/docs/en/plugins/dependencies), Claude Code enables them too. The command fails in these cases:
* **A dependency is not installed**: enable fails and prints the `claude plugin install` command for each missing dependency
* **A dependency is blocked by your organization's plugin policy**: enable fails and names the blocked dependency
* **A dependency is set to `false` at a scope with higher precedence than the target scope**: enable fails. Enable the dependency at that scope, or pass `--scope` to write there
Re-enable a plugin wherever it's declared:
```bash theme={null}
claude plugin enable formatter
```
Claude Code prints `Successfully enabled plugin: formatter (scope: project)`, naming the scope it detected.
### plugin disable
Disable a plugin without uninstalling it. For a [plugin synced from claude.ai](/docs/en/plugins/loading#synced-plugins), pass `<name>@synced` as the plugin.
```bash theme={null}
claude plugin disable [plugin] [options]
```
| Flag | Description |
| :-------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-a, --all` | Disable every enabled plugin. Can't be combined with a plugin name or `--scope` |
| `-s, --scope <scope>` | Scope to disable at: `user`, `project`, or `local`. Auto-detected when omitted |
| `--json` | Print the result as one JSON object on the last line of stdout, in the [same format as `plugin install --json`](#plugin-json-result). Requires Claude Code v2.1.268 or later |
Without `--scope`, the scope is auto-detected in the same local, project, user order as [`plugin enable`](#plugin-enable).
If you pass neither a plugin name nor `--all`, Claude Code prints `Please specify a plugin name or use --all to disable all plugins` and exits `1`. Disabling a plugin that is already disabled prints `Plugin "formatter" is already disabled` and exits `1`, as [`plugin enable`](#plugin-enable) does for an already-enabled plugin.
The command fails for a plugin that is still required:
* **Another enabled plugin [depends on](/docs/en/plugins/dependencies) it**: the command fails and names the dependents to disable first
* **Your organization requires it as a synced plugin**: the command fails and saves nothing
Disable one plugin:
```bash theme={null}
claude plugin disable formatter
```
Claude Code prints `Successfully disabled plugin: formatter (scope: project)`.
### plugin update
Update a plugin to the latest version its marketplace offers. The new version loads in your next session, or after you run `/reload-plugins` in a running one.
```bash theme={null}
claude plugin update <plugin> [options]
```
| Flag | Description |
| :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-s, --scope <scope>` | Scope to update: `user`, `project`, `local`, or `managed`. Defaults to the scope the plugin is installed at |
| `-y, --yes` | Accept a changed install command from a [command-source](/docs/en/plugins/host-marketplace) plugin, without the prompt. Required when stdin or stdout isn't a TTY, unless you pass `--accept-command`. Requires Claude Code v2.1.229 or later |
| `--accept-command <sha256>` | Accept the marketplace-declared command whose `sha256` a previous [`--json` run](#plugin-json-result) reported in `shownCommand`, in place of `-y`. Can't be combined with `-y`. Requires Claude Code v2.1.271 or later |
| `--json` | Print the result as one JSON object on the last line of stdout, in the [same format as `plugin install --json`](#plugin-json-result). Requires Claude Code v2.1.268 or later |
`managed` is the one scope you can update but not install to. For admin-installed plugins, see [Manage plugins for your organization](/docs/en/plugins/org).
Update a plugin:
```bash theme={null}
claude plugin update formatter@my-marketplace
```
Claude Code prints `Checking for updates for plugin "formatter@my-marketplace"…`, then the result. When nothing is newer, it prints `formatter is already at the latest version (1.0.0).` and exits `0`.
You can pass a bare plugin name, which the command matches against your installed plugins. When installed plugins from different marketplaces share the name, the command refuses the update and lists the qualified `plugin-name@marketplace-name` commands to run instead. Updating by bare name requires Claude Code v2.1.246 or later.
### plugin list
List installed plugins with their version, scope, and status.
```bash theme={null}
claude plugin list [options]
```
| Flag | Description |
| :------------ | :--------------------------------------------------------------------------------------------------- |
| `--json` | Print the list as JSON |
| `--available` | Also list plugins your marketplaces offer that you haven't installed. Has no effect without `--json` |
Claude Code groups the human-readable output by how each plugin loads:
* **`Installed plugins:`**: plugins you installed from a marketplace
* **`Session-only plugins (--plugin-dir / --plugin-url):`**: plugins loaded by those flags in the same command, as in `claude --plugin-dir ./my-plugin plugin list`
* **`Skills-directory plugins (.claude/skills/*):`**: plugins Claude Code found in a skills directory
* **`Synced from claude.ai`**: [plugins synced from your claude.ai account](/docs/en/plugins/loading#synced-plugins)
With nothing in any group, Claude Code prints ``No plugins installed. Use `claude plugin install` to install a plugin.``
#### JSON output
With `--json`, Claude Code prints an array with one object per installation. Each object carries the fields below. `id`, `version`, `scope`, `enabled`, and `installPath` are always present, and the others appear only when they apply.
| Field | Type | Description |
| :------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | string | `name@marketplace` for installs, `name@inline` for session-only plugins, `name@skills-dir` for skills-directory plugins, `name@synced` for plugins synced from claude.ai |
| `version` | string | For a marketplace install, the [version Claude Code computed](/docs/en/plugins/loading#versions-and-updates) at install. For a session-only, skills-directory, or synced plugin, the manifest's `version`, or `unknown` when it declares none |
| `scope` | string | `user`, `project`, `local`, or `managed` for installs; `user` or `project` for skills-directory plugins; `session` for session-only plugins; `synced` for plugins synced from claude.ai |
| `enabled` | boolean | Whether the plugin is enabled in your merged settings |
| `installPath` | string | Directory the plugin loads from |
| `installedAt` | string | ISO timestamp of the install. Marketplace installs only |
| `lastUpdated` | string | ISO timestamp of the last update. Marketplace installs only |
| `projectPath` | string | Project the install belongs to. `project` and `local` scope only |
| `mcpServers` | object | The plugin's MCP server definitions, when a marketplace-installed plugin has any |
| `errors` | array of strings | Load errors, when the plugin failed to load |
| `notes` | array of strings | Authoring warnings for a plugin that loaded and works |
| `errorDetails` | array of objects | One object per `errors` entry, giving its diagnostic `type` and the names it refers to, such as the plugin, marketplace, server, or file. Requires Claude Code v2.1.268 or later |
| `noteDetails` | array of objects | The same detail objects for each `notes` entry. Requires Claude Code v2.1.268 or later |
With `--json --available`, Claude Code prints one object instead of an array. Its `installed` field holds the array of installed-plugin objects, and its `available` field holds one object per uninstalled marketplace plugin with the fields below.
| Field | Type | Description |
| :---------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------- |
| `pluginId` | string | `name@marketplace` |
| `name` | string | The plugin's name in the marketplace |
| `marketplaceName` | string | The marketplace that offers it |
| `source` | string or object | The marketplace entry's [source](/docs/en/plugins/marketplace-reference): a string for a relative path, an object otherwise |
| `description` | string | The entry's description, when it has one |
| `version` | string | The entry's version, when it declares one |
| `installCount` | number | Install count, when Claude Code has one for the plugin |
Cut at 300 lines. The page has the rest.
plugins/code-intelligence New page · 132 lines, new page
# Code intelligence plugins ## Install a code intelligence plugin ## See what Claude gains ### Read the diagnostics yourself ## Accept or dismiss the recommendation dialog ### When the recommendation dialog appears ### Respond to the recommendation dialog ### Turn recommendations back on ## Troubleshoot code intelligence ## Add a language without an official plugin ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Code intelligence plugins
> Install a language server plugin so Claude sees type errors after edits and navigates code by symbol, and answer the LSP plugin recommendation dialog.
A code intelligence plugin gives Claude the live diagnostics and go-to-definition that your editor has, so Claude catches type errors and missing imports that its own edits introduce before you run your build, and finds definitions and references by symbol instead of by text search.
Each plugin connects Claude Code to a language server for one language through the Language Server Protocol (LSP). You install the plugin from Anthropic's official marketplace and the language server binary on your machine.
<Note>
Code intelligence plugins work in terminal sessions. In [cloud sessions](/docs/en/claude-code-on-the-web), Claude Code doesn't start plugin language servers, so Claude gets no diagnostics or code navigation there. To write your own language server plugin, or to connect a language server that has no plugin, see [LSP servers in plugin components](/docs/en/plugins/components#lsp-servers).
</Note>
To get started, find your language in the table under [Install a code intelligence plugin](#install-a-code-intelligence-plugin). The plugins in that table come from Anthropic's [official plugin marketplace](/docs/en/plugins/anthropic-marketplaces).
If you already saw an **LSP plugin recommendation** dialog, see [Accept or dismiss the recommendation dialog](#accept-or-dismiss-the-recommendation-dialog) for what each choice does.
## Install a code intelligence plugin
A code intelligence plugin tells Claude Code which command starts the language server and which file extensions it handles. It doesn't include the language server. Install the language server binary first, then the plugin, then confirm the server starts.
<Steps>
<Step title="Install the language server binary">
Find your language in the table below and install the binary in its row. If your language isn't listed, see [Add a language without an official plugin](#add-a-language-without-an-official-plugin).
| Language | Plugin | Binary |
| :------------------------ | :--------------------------------------------------------------------------------------------------------------- | :------------------------------ |
| C/C++ | [`clangd-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/clangd-lsp) | `clangd` |
| C# | [`csharp-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/csharp-lsp) | `csharp-ls` |
| Go | [`gopls-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/gopls-lsp) | `gopls` |
| Java | [`jdtls-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/jdtls-lsp) | `jdtls` |
| Kotlin | [`kotlin-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/kotlin-lsp) | `kotlin-lsp` |
| Liquid | [`liquid-lsp`](https://github.com/Shopify/liquid-skills/tree/main/plugins/liquid-lsp) | `shopify`, from the Shopify CLI |
| Lua | [`lua-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/lua-lsp) | `lua-language-server` |
| PHP | [`php-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/php-lsp) | `intelephense` |
| Python | [`pyright-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/pyright-lsp) | `pyright-langserver` |
| Ruby | [`ruby-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/ruby-lsp) | `ruby-lsp` |
| Rust | [`rust-analyzer-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/rust-analyzer-lsp) | `rust-analyzer` |
| Swift | [`swift-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/swift-lsp) | `sourcekit-lsp` |
| TypeScript and JavaScript | [`typescript-lsp`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/typescript-lsp) | `typescript-language-server` |
Anthropic maintains every plugin in the table except `liquid-lsp`, which Shopify maintains and the official marketplace lists.
To find the command that installs the binary, follow the plugin's link in the table to its README. For TypeScript, that command is `npm install -g typescript-language-server typescript`.
After you install the binary, confirm it's on the `PATH` of the shell you start `claude` from, for example with `which typescript-language-server`, or `Get-Command typescript-language-server` in PowerShell.
</Step>
<Step title="Install the plugin">
To install the plugin listed for your language in the step 1 table, run `/plugin install` in a Claude Code session, replacing `typescript-lsp` with that plugin's name:
```
/plugin install typescript-lsp@claude-plugins-official
```
A confirmation message says whether the plugin is active now or needs `/reload-plugins`. If the install fails with `Marketplace "claude-plugins-official" not found`, see the [troubleshooting entry for that error](/docs/en/plugins/troubleshooting#marketplace-claude-plugins-official-not-found). To control where the plugin is installed, or to run the install from your shell instead of inside Claude Code, see [Install plugins](/docs/en/plugins/install).
</Step>
<Step title="Confirm the server starts">
The language server starts the first time Claude edits a file with one of the plugin's extensions. To see it work, ask Claude to introduce a type error in a file of that language and then fix it. Then check the conversation for a diagnostics line:
* **A diagnostics line appears**: `Found N new diagnostic issues in M files (ctrl+o to expand)` under the edit that introduced the error means the server started.
* **No diagnostics line appears**: run `/plugin` and open the **Errors** tab. A row reading `Executable not found in $PATH: "<binary>"` names the binary to install. If the tab has no such row, see [Troubleshoot code intelligence](#troubleshoot-code-intelligence).
After you install a missing binary, Claude Code tries again the next time Claude edits a matching file. If you installed the binary into a directory that isn't on the `PATH` of the shell you started `claude` from, start a new session from a shell where it is.
</Step>
</Steps>
## See what Claude gains
With a language server running, Claude gains diagnostics and code navigation:
* **Diagnostics after edits**: each time Claude edits or writes a file the server handles, Claude gets the errors and warnings the server reports. It sees a type error, missing import, or syntax error it introduced without running a compiler.
* **Code navigation**: Claude gets an `LSP` tool that looks up symbols through the server instead of searching text for them. The tool is read-only. For what Claude can look up with the tool and how permissions apply to it, see [LSP tool behavior](/docs/en/tools-reference#lsp-tool-behavior).
### Read the diagnostics yourself
After Claude edits a file the server handles, the conversation shows only the `Found N new diagnostic issues` summary. To read the issues themselves, press **Ctrl+O**.
## Accept or dismiss the recommendation dialog
If a language server binary is already on your `PATH` and the plugin that uses it isn't installed, Claude Code offers to install the plugin for you in a dialog titled **LSP plugin recommendation**.
### When the recommendation dialog appears
The **LSP plugin recommendation** dialog can appear after Claude edits a file. These conditions decide whether it appears and which plugin it offers:
* **A plugin matches the file**: one of the marketplaces you've added, or the official marketplace Claude Code registered for you, lists a code intelligence plugin for that file's extension, and the plugin's binary is installed.
* **Official first**: when more than one marketplace offers a plugin for the extension, the dialog offers the official marketplace's plugin.
* **Once per session**: the dialog appears at most once in a session, for the first matching file Claude edits.
* **Not for cloud sessions**: the dialog never appears when your terminal is attached to a cloud session, such as one you started with [`claude --cloud`](/docs/en/claude-code-on-the-web#from-terminal-to-cloud).
### Respond to the recommendation dialog
The **LSP plugin recommendation** dialog names the plugin and offers these choices:
* **Yes, install**: Claude Code installs the plugin for your user account and prints `<plugin> installed · restart to apply`. Start a new session to load the server.
* **No, not now**: the dialog closes, and a later session can offer the plugin again. Pressing **Esc** does the same.
* **Never for this plugin**: the dialog stops appearing for that plugin and still appears for others.
* **Disable all LSP recommendations**: the dialog stops appearing for every language.
If you don't choose an option, Claude Code closes it after 30 seconds and counts that as ignored. The count is kept across sessions. After five ignored dialogs, Claude Code stops recommending plugins, the same as if you'd chosen **Disable all LSP recommendations**.
### Turn recommendations back on
The **LSP plugin recommendation** dialog stops appearing after you choose **Disable all LSP recommendations** or ignore it five times.
* **Disabled or ignored five times**: to turn it back on in either case, remove the `lspRecommendationDisabled` and `lspRecommendationIgnoredCount` keys from `~/.claude.json`, Claude Code's own configuration file.
* **Never for this plugin**: if you chose **Never for this plugin** and want that plugin offered again, remove its `name@marketplace` id from the `lspRecommendationNeverPlugins` list in the same file.
## Troubleshoot code intelligence
The plugins troubleshooting page covers the symptoms specific to code intelligence plugins under [Language server doesn't start, uses too much memory, or reports wrong diagnostics](/docs/en/plugins/troubleshooting#language-server-doesnt-start):
* **The language server doesn't start**: you see `Executable not found in $PATH` in the **Errors** tab of `/plugin`, or Claude never reports diagnostics for the language.
* **High memory use**: memory use increases while the server indexes the project.
* **False positive diagnostics in a monorepo**: diagnostics report imports as unresolved when they aren't.
## Add a language without an official plugin
If your language isn't in the [table of official plugins](#install-a-code-intelligence-plugin), you can still connect a language server.
1. Write a plugin with an `.lsp.json` file that names the server command and the file extensions it handles.
2. Then load the plugin with [`--plugin-dir`](/docs/en/plugins/cli-reference#flags-that-load-a-plugin-for-one-session) or publish it to a marketplace.
For the file's fields and a worked example, see [LSP servers in plugin components](/docs/en/plugins/components#lsp-servers).
## Next steps
* [LSP servers in plugin components](/docs/en/plugins/components#lsp-servers): write the `.lsp.json` for a language server that has no official plugin
* [Install and manage plugins](/docs/en/plugins/install): scopes, updates, and uninstalling
* [Troubleshoot plugins](/docs/en/plugins/troubleshooting): load errors beyond the language-server ones on this page
* [Find plugins in the official marketplace](/docs/en/plugins/anthropic-marketplaces#find-plugins-in-the-official-marketplace): where to browse the rest of the official marketplace
plugins/components New page · 1077 lines, new page
# Add components to a plugin ## Explore the plugin directory ## Add each kind of component ### Skills ### Commands #### Define commands in the manifest ### Agents #### Organize agents in subfolders #### Frontmatter fields in plugin agents ### Hooks #### When plugin hooks fire #### Environment, quoting, and matching MCP tools ### MCP servers #### Reach users on claude.ai and Cowork #### Server names, tool names, and reloads #### Include a packaged MCPB server ### LSP servers ### Executables ### Default settings ### Themes and output styles ### Channels ### Monitors ### When the configuration dialog appears ### Install dependencies into the data directory ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Add components to a plugin
> Add skills, hooks, MCP servers, and every other component type to a Claude Code plugin, with an example that validates for each.
export const Piece = ({id, children}) => <div className="pe-piece" data-piece={id}>{children}</div>;
export const PluginExplorer = ({children}) => {
const PIECES = [{
id: 'manifest',
name: 'Manifest',
path: '.claude-plugin/plugin.json',
lines: [{
depth: 0,
kind: 'folder',
text: '.claude-plugin/'
}, {
depth: 1,
kind: 'file',
text: 'plugin.json'
}],
href: '/en/plugins/manifest-reference#manifest-file',
linkText: 'Go to the manifest reference'
}, {
id: 'skills',
name: 'Skills',
path: 'skills/review/SKILL.md',
lines: [{
depth: 0,
kind: 'folder',
text: 'skills/'
}, {
depth: 1,
kind: 'folder',
text: 'review/'
}, {
depth: 2,
kind: 'file',
text: 'SKILL.md'
}],
href: '/en/plugins/components#skills',
linkText: 'Go to the Skills section'
}, {
id: 'commands',
name: 'Commands',
path: 'commands/about.md',
lines: [{
depth: 0,
kind: 'folder',
text: 'commands/'
}, {
depth: 1,
kind: 'file',
text: 'about.md'
}],
href: '/en/plugins/components#commands',
linkText: 'Go to the Commands section'
}, {
id: 'agents',
name: 'Agents',
path: 'agents/security-reviewer.md',
lines: [{
depth: 0,
kind: 'folder',
text: 'agents/'
}, {
depth: 1,
kind: 'file',
text: 'security-reviewer.md'
}],
href: '/en/plugins/components#agents',
linkText: 'Go to the Agents section'
}, {
id: 'hooks',
name: 'Hooks',
path: 'hooks/hooks.json',
lines: [{
depth: 0,
kind: 'folder',
text: 'hooks/'
}, {
depth: 1,
kind: 'file',
text: 'hooks.json'
}],
href: '/en/plugins/components#hooks',
linkText: 'Go to the Hooks section'
}, {
id: 'monitors',
name: 'Monitors',
path: 'monitors/monitors.json',
lines: [{
depth: 0,
kind: 'folder',
text: 'monitors/'
}, {
depth: 1,
kind: 'file',
text: 'monitors.json'
}],
href: '/en/plugins/components#monitors',
linkText: 'Go to the Monitors section'
}, {
id: 'output-styles',
name: 'Output styles',
path: 'output-styles/terse.md',
lines: [{
depth: 0,
kind: 'folder',
text: 'output-styles/'
}, {
depth: 1,
kind: 'file',
text: 'terse.md'
}],
href: '/en/plugins/components#themes-and-output-styles',
linkText: 'Go to the Themes and output styles section'
}, {
id: 'themes',
name: 'Themes',
path: 'themes/dracula.json',
lines: [{
depth: 0,
kind: 'folder',
text: 'themes/'
}, {
depth: 1,
kind: 'file',
text: 'dracula.json'
}],
href: '/en/plugins/components#themes-and-output-styles',
linkText: 'Go to the Themes and output styles section'
}, {
id: 'workflows',
name: 'Workflows',
path: 'workflows/audit-routes.js',
lines: [{
depth: 0,
kind: 'folder',
text: 'workflows/'
}, {
depth: 1,
kind: 'file',
text: 'audit-routes.js'
}],
href: '/en/workflows#distribute-a-workflow-in-a-plugin',
linkText: 'Go to Distribute a workflow in a plugin'
}, {
id: 'bin',
name: 'Executables',
path: 'bin/hello-plugin',
lines: [{
depth: 0,
kind: 'folder',
text: 'bin/'
}, {
depth: 1,
kind: 'file',
text: 'hello-plugin'
}],
href: '/en/plugins/components#executables',
linkText: 'Go to the Executables section'
}, {
id: 'scripts',
name: 'Scripts',
path: 'scripts/format.sh',
lines: [{
depth: 0,
kind: 'folder',
text: 'scripts/'
}, {
depth: 1,
kind: 'file',
text: 'format.sh'
}],
href: '/en/plugins/components#hooks',
linkText: 'Go to the Hooks section'
}, {
id: 'settings',
name: 'Default settings',
path: 'settings.json',
lines: [{
depth: 0,
kind: 'file',
text: 'settings.json'
}],
href: '/en/plugins/components#default-settings',
linkText: 'Go to the Default settings section'
}, {
id: 'mcp',
name: 'MCP servers',
path: '.mcp.json',
lines: [{
depth: 0,
kind: 'file',
text: '.mcp.json'
}],
href: '/en/plugins/components#mcp-servers',
linkText: 'Go to the MCP servers section'
}, {
id: 'lsp',
name: 'LSP servers',
path: '.lsp.json',
lines: [{
depth: 0,
kind: 'file',
text: '.lsp.json'
}],
href: '/en/plugins/components#lsp-servers',
linkText: 'Go to the LSP servers section'
}];
const [selectedId, setSelectedId] = useState('manifest');
const [isFullscreen, setIsFullscreen] = useState(false);
const rootRef = useRef(null);
useEffect(() => {
const onFsChange = () => setIsFullscreen(!!document.fullscreenElement);
document.addEventListener('fullscreenchange', onFsChange);
return () => document.removeEventListener('fullscreenchange', onFsChange);
}, []);
const toggleFullscreen = () => {
if (!rootRef.current) return;
if (document.fullscreenElement) document.exitFullscreen(); else rootRef.current.requestFullscreen().catch(() => {});
};
const selected = PIECES.find(p => p.id === selectedId) || PIECES[0];
const onTreeKeyDown = e => {
const keys = ['ArrowDown', 'ArrowUp', 'Home', 'End'];
if (keys.indexOf(e.key) === -1) return;
const i = PIECES.findIndex(p => p.id === selectedId);
let next = i;
if (e.key === 'ArrowDown') next = Math.min(PIECES.length - 1, i + 1);
if (e.key === 'ArrowUp') next = Math.max(0, i - 1);
if (e.key === 'Home') next = 0;
if (e.key === 'End') next = PIECES.length - 1;
e.preventDefault();
if (next === i) return;
const id = PIECES[next].id;
setSelectedId(id);
const el = document.getElementById('pe-node-' + id);
if (el) el.focus();
};
const FolderIcon = () => <svg className="pe-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" aria-hidden="true">
<path d="M1.5 4.5a1 1 0 0 1 1-1h3.2l1.3 1.5h6a1 1 0 0 1 1 1V12a1 1 0 0 1-1 1h-10.5a1 1 0 0 1-1-1z" />
</svg>;
const FileIcon = () => <svg className="pe-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinejoin="round" aria-hidden="true">
<path d="M4 1.5h5.5L13 5v9.5H4z" />
<path d="M9.5 1.5V5H13" />
</svg>;
return <div ref={rootRef} className={isFullscreen ? 'pe-root pe-fullscreen not-prose' : 'pe-root not-prose'} data-selected={selected.id}>
<style>{`
.pe-root {
--pe-mono: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
--pe-accent: #D97757;
--pe-accent-text: #A8502F;
--pe-accent-bg: rgba(217,119,87,0.10);
--pe-bg: #FFFFFF;
--pe-surface: #FAFAF7;
--pe-hover: #F0EEE6;
--pe-border: #E8E6DC;
--pe-text: #141413;
--pe-text-2: #3D3D3A;
--pe-text-3: #5E5D59;
font-family: inherit;
background: var(--pe-bg);
color: var(--pe-text);
border: 1px solid var(--pe-border);
border-radius: 12px;
margin: 1.5rem 0;
overflow: hidden;
box-sizing: border-box;
}
.dark .pe-root {
--pe-accent-text: #EBA98F;
--pe-accent-bg: rgba(217,119,87,0.18);
--pe-bg: #1A1918;
--pe-surface: #232221;
--pe-hover: #2E2D2B;
--pe-border: #3A3936;
--pe-text: #F1EFE9;
--pe-text-2: #D6D4CA;
--pe-text-3: #B8B5AD;
}
.pe-root *, .pe-root *::before, .pe-root *::after { box-sizing: border-box; }
.pe-head { display: flex; align-items: flex-start; gap: 12px; padding: 18px 24px 16px; border-bottom: 1px solid var(--pe-border); }
.pe-head-text { flex: 1; min-width: 0; }
.pe-fs-btn { flex-shrink: 0; width: 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--pe-border); border-radius: 6px; background: var(--pe-surface); color: var(--pe-text-2); font-size: 15px; line-height: 1; cursor: pointer; }
.pe-fs-btn:hover { background: var(--pe-hover); }
.pe-fs-btn:focus-visible { outline: 2px solid var(--pe-accent); outline-offset: 2px; }
.pe-fullscreen { border-radius: 0; height: 100vh; display: flex; flex-direction: column; overflow: auto; }
.pe-fullscreen .pe-body { flex: 1; }
.pe-title { font-size: 19px; font-weight: 600; line-height: 1.3; color: var(--pe-text); margin: 0; }
.pe-sub { font-size: 15px; line-height: 1.5; color: var(--pe-text-3); margin: 4px 0 0; }
.pe-sub code { font-family: var(--pe-mono); font-size: 0.88em; padding: 1px 5px; border-radius: 4px; background: var(--pe-surface); border: 1px solid var(--pe-border); }
.pe-body { display: flex; align-items: stretch; }
.pe-tree-pane { width: 270px; flex-shrink: 0; background: var(--pe-surface); border-right: 1px solid var(--pe-border); padding: 16px 0 12px; }
.pe-panel { flex: 1; min-width: 0; padding: 16px 24px 24px; }
.pe-caption { font-size: 13px; font-weight: 600; color: var(--pe-text-3); margin: 0 0 10px; }
.pe-tree-pane .pe-caption { padding: 0 16px; }
.pe-rootline { display: flex; align-items: center; gap: 7px; padding: 3px 16px; font-family: var(--pe-mono); font-size: 13.5px; color: var(--pe-text-3); }
.pe-node {
display: block; width: 100%; margin: 0; padding: 3px 16px 3px 30px; text-align: left; cursor: pointer;
background: transparent; color: var(--pe-text-2);
Cut at 300 lines. The page has the rest.
plugins/create New page · 390 lines, new page
# Create a Claude Code plugin ## Decide when to use a plugin ## Create your first plugin ### Plugin layout ## Develop without a marketplace #### From a directory or `.zip` #### From an environment variable #### Scaffold the plugin with `claude plugin init` #### Stop loading the plugin ## Test and debug ### A component path isn't found ### `--plugin-dir` at a marketplace root doesn't load the plugins under `plugins/` ### The plugin loads but its skills are missing ### The `userConfig` dialog never appears ### Check that the plugin changes Claude's behavior ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Create a Claude Code plugin
> Build your first Claude Code plugin from an empty directory, test it without a marketplace, and convert an existing .claude/ setup.
A plugin is a directory of skills, agents, hooks, and MCP servers, plus a `plugin.json` file, called the manifest, that names the plugin. Claude Code loads the directory as one unit, so you can share it with teammates, install it in several projects, or publish it to a marketplace.
This page is for people writing their own plugins.
<Note>
These cases are covered on other pages:
* **Installing someone else's plugin**: see [Install plugins](/docs/en/plugins/install)
* **Not sure you need a plugin**: see [Decide whether you need a plugin](/docs/en/plugins/overview#decide-whether-you-need-a-plugin) on the overview
* **Your plugin's users are on claude.ai or in Cowork**: the same folder installs there with a different subset of components. See [Plugins on claude.ai and in Cowork](https://claude.com/docs/plugins/overview)
</Note>
Start from the section that matches what you already have:
* **Nothing yet**: follow [Create your first plugin](#create-your-first-plugin), then [Develop without a marketplace](#develop-without-a-marketplace) and [Test and debug](#test-and-debug).
* **Files under `.claude/` already**: do the first-plugin walkthrough once to learn the layout, then follow [Convert an existing `.claude/` setup](#convert-an-existing-claude-setup).
## Decide when to use a plugin
Skills, agents, hooks, and MCP servers all work standalone in your project or home directory. Keep that standalone setup while it serves one project or only you. Make a plugin when you want to share the setup with teammates, install it in several projects, or publish versioned releases.
When you move standalone skills, agents, hooks, and MCP config into a plugin, their location and names change:
* **Where the files go**: under the plugin's own directory, called the plugin root, as `skills/`, `agents/`, `hooks/hooks.json`, and `.mcp.json`.
* **How they're named**: plugin skills and agents get the plugin name as a prefix, such as `/my-plugin:hello`, so two plugins can each provide a `hello` skill without colliding.
To move an existing setup into a plugin, see [Convert an existing `.claude/` setup](#convert-an-existing-claude-setup).
## Create your first plugin
In this walkthrough, you create a plugin whose only component is one skill, a greeting, and run it with `--plugin-dir`, which loads a plugin for one session without installing it. A plugin can hold any mix of [components](/docs/en/plugins/components), such as skills, agents, hooks, and MCP servers, and none is required; one skill is the smallest example that shows the layout.
You need Claude Code [installed and signed in](/docs/en/quickstart#step-1-install-claude-code).
Open a terminal in the directory where you want to keep the plugin, such as `~/projects`, and run the commands in these steps from it. You can keep a plugin anywhere, because you pass its path to Claude Code when you start a session.
<Steps>
<Step title="Create the plugin directory">
Create the plugin directory, with a `.claude-plugin/` folder inside it to hold the manifest:
```bash theme={null}
mkdir -p my-first-plugin/.claude-plugin
```
</Step>
<Step title="Write the manifest">
The [manifest](/docs/en/plugins/manifest-reference) is a JSON file named `plugin.json` that tells Claude Code the plugin's name and describes it. Save this one as `my-first-plugin/.claude-plugin/plugin.json`:
```json my-first-plugin/.claude-plugin/plugin.json theme={null}
{
"name": "my-first-plugin",
"description": "A greeting plugin to learn the basics",
"version": "1.0.0",
"author": {
"name": "Your Name"
}
}
```
The four fields do this:
* **`name`**: required. It identifies the plugin and becomes the prefix on every skill and agent the plugin provides. Don't put spaces in it.
* **`description`**: the text users see for the plugin in `/plugin`.
* **`version`**: optional. Setting it keeps users on that version until you change it; [Release a new version](/docs/en/plugins/host-marketplace#release-a-new-version) says when to set or omit it.
* **`author`**: who to credit. `name` is required inside it; `email` and `url` are optional.
Every other field is on the [manifest reference](/docs/en/plugins/manifest-reference#fields).
Only `plugin.json` goes inside `.claude-plugin/`. The skill you add next goes directly under `my-first-plugin/`, next to that folder.
</Step>
<Step title="Add a skill">
This plugin's one component is a skill. Each skill is a directory under `skills/` that contains a `SKILL.md` file. Create the skill's directory:
```bash theme={null}
mkdir -p my-first-plugin/skills/hello
```
Then create `my-first-plugin/skills/hello/SKILL.md` with this content:
```markdown my-first-plugin/skills/hello/SKILL.md theme={null}
---
name: hello
description: Greet the user with a friendly message
disable-model-invocation: true
---
Greet the user warmly and ask how you can help them today.
```
The `disable-model-invocation: true` line means Claude doesn't run the skill on its own, so only you trigger it. Remove that line from a skill you want Claude to run on its own. The skill's command combines the plugin name and the skill's name, so you run this one as `/my-first-plugin:hello`. For the other frontmatter fields, see the [skill frontmatter reference](/docs/en/skills#frontmatter-reference).
</Step>
<Step title="Validate the plugin">
Check the manifest and the skill's frontmatter before you run anything:
```bash theme={null}
claude plugin validate ./my-first-plugin
```
The command prints the manifest path it checked and `✔ Validation passed`. If it prints `✘ Validation failed` instead, each line above that result line names the field to fix. Look up each message under [`claude plugin validate` reports errors](/docs/en/plugins/troubleshooting#claude-plugin-validate-reports-errors).
</Step>
<Step title="Run Claude Code with the plugin">
Start a session with the plugin loaded:
```bash theme={null}
claude --plugin-dir ./my-first-plugin
```
Once Claude Code starts, run the skill:
```text theme={null}
/my-first-plugin:hello
```
Claude replies with a greeting.
</Step>
</Steps>
The plugin loads only in sessions you start with `--plugin-dir`. To keep working on it without the flag, or to test a `.zip` build, see [Develop without a marketplace](#develop-without-a-marketplace).
<h3 id="share-the-plugin">
Share your plugin
</h3>
A plugin you built with [Create your first plugin](#create-your-first-plugin) exists only on your machine. When it's ready for other people, there are three ways to get it to them:
* **Send it to a few people directly**: give them the plugin's directory or a `.zip` of it, and nothing needs to be published. See [Share a plugin without a marketplace](/docs/en/plugins/publish#share-a-plugin-without-a-marketplace).
* **List it in your own marketplace**: teammates add your marketplace once and install the plugin by name, and they receive your updates. See [Publish through your own marketplace](/docs/en/plugins/publish#publish-through-your-own-marketplace).
* **Submit it to Anthropic's community marketplace**: once it's listed, anyone who adds that marketplace can install it. See [Submit to the community marketplace](/docs/en/plugins/publish#submit-to-the-community-marketplace).
### Plugin layout
Each kind of [component](/docs/en/plugins/components), such as skills, agents, hooks, and MCP servers, goes in a fixed directory under the plugin root, which is the directory you pass to `--plugin-dir`. Add only the directories you use. To click through a complete plugin directory and read what each file does, open the [plugin explorer](/docs/en/plugins/components#explore-the-plugin-directory).
The table lists the directories most plugins start with, and the [full layout](/docs/en/plugins/manifest-reference#standard-layout) lists the rest.
| Location | Contents |
| :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- |
| `.claude-plugin/plugin.json` | The manifest. When you load a plugin with `--plugin-dir` and it has no manifest, Claude Code names the plugin after its directory |
| `skills/` | One `<name>/SKILL.md` directory per skill |
| `commands/` | Flat Markdown files, the older form of skills. Use `skills/` for new plugins |
| `agents/` | One Markdown file per subagent |
| `hooks/hooks.json` | Hook configuration: a top-level `"hooks"` key whose value has the same shape as `hooks` in a settings file |
| `.mcp.json` | MCP server definitions |
<Warning>
Only `plugin.json` goes inside `.claude-plugin/`. Components saved there don't load.
The plugin root is the plugin's own directory, not `~/.claude/` itself. A `.mcp.json` saved at `~/.claude/.mcp.json` doesn't load.
</Warning>
## Develop without a marketplace
You don't need a [marketplace](/docs/en/plugins/overview#get-plugins-from-a-marketplace) to run a plugin you're writing. Load it directly from disk or a URL instead:
* [`--plugin-dir`](#load-a-directory-or-archive-for-one-session): loads a directory or `.zip` archive for one session.
* [`--plugin-url`](#fetch-an-archive-from-a-url-for-one-session): fetches a `.zip` archive from a URL for one session.
* [`claude plugin init`](#scaffold-a-plugin-that-loads-every-session): scaffolds a plugin under `~/.claude/skills/` that loads every session.
If two plugins loaded in different ways share a name, see [Name conflicts](/docs/en/plugins/loading#name-conflicts) for which one Claude Code keeps.
<h3 id="load-a-directory-or-archive-for-one-session">
Load a plugin for one session
</h3>
You can load a plugin for a single session in three ways: from a directory or `.zip` archive on disk with `--plugin-dir`, from a URL with `--plugin-url`, or from an environment variable when you can't add a flag. Each plugin loads for that session only, and nothing is written to your settings for it. When you edit the plugin's files during the session, run `/reload-plugins` to load the changes.
#### From a directory or `.zip`
When you start `claude` from your shell, pass `--plugin-dir` with the plugin's root directory or a `.zip` archive of it. Repeat the flag to load several plugins:
```bash theme={null}
claude --plugin-dir ./my-first-plugin --plugin-dir ./other-plugin.zip
```
<h4 id="load-a-folder-of-plugins">
From a folder of plugins
</h4>
To load several plugins from one place, pass a folder that holds them, such as `--plugin-dir ./plugins`. Loading a folder of plugins requires Claude Code v2.1.265 or later.
If the folder has no `.claude-plugin/` directory and no plugin components at its top level, Claude Code treats it as a folder of plugins. Each immediate subfolder that has a `.claude-plugin/plugin.json` manifest then loads as a separate plugin. Everything else in the folder is skipped without an error, including a subfolder that has no manifest. If a plugin in the folder doesn't load, check that its subfolder has a `.claude-plugin/plugin.json`.
In an interactive session, you can also add and remove plugins in the folder after startup:
* A subfolder you add loads as a new plugin once its manifest exists.
* When you remove a subfolder, its plugin unloads.
A message appears in the session for each of these changes. If loading or unloading a plugin mid-conversation would [invalidate the prompt cache](/docs/en/prompt-caching#enabling-or-disabling-a-plugin), the change is held instead, and the message tells you to run `/reload-plugins` to apply it.
<h4 id="fetch-an-archive-from-a-url-for-one-session">
From a URL
</h4>
When you start `claude` from your shell, pass `--plugin-url` with the address of a `.zip` archive, such as a build artifact your CI publishes:
```bash theme={null}
claude --plugin-url https://example.com/my-first-plugin.zip
```
Claude Code downloads the archive at startup. To load several, repeat the flag or pass the URLs space-separated in one quoted argument.
Point the flag only at archives you control or trust.
If Claude Code can't fetch the archive, or the archive is invalid, it starts without the plugin and records a plugin load error that you can review in the `/plugin` manager's **Errors** tab.
#### From an environment variable
To load plugins in a session where you can't add the `--plugin-dir` flag, list their absolute paths in the [`CLAUDE_CODE_PLUGIN_DIRS`](/docs/en/env-vars#variables) environment variable instead. Claude Code loads each path as it loads a `--plugin-dir` path. These plugins load in addition to any you pass with `--plugin-dir`. [Project and local settings can't set this variable](/docs/en/settings-reference#variables-claude-code-ignores-in-env). `CLAUDE_CODE_PLUGIN_DIRS` requires Claude Code v2.1.280 or later.
Managed settings can turn off `--plugin-dir` and `CLAUDE_CODE_PLUGIN_DIRS`. See [Flags that load a plugin for one session](/docs/en/plugins/cli-reference#flags-that-load-a-plugin-for-one-session). To test a plugin together with a plugin it depends on, see [Test a plugin and its dependency locally](/docs/en/plugins/dependencies#test-a-plugin-and-its-dependency-locally).
<h3 id="scaffold-a-plugin-that-loads-every-session">
Make a plugin load in every session
</h3>
Your personal skills directory is `~/.claude/skills/`. Claude Code loads any folder there that contains a `.claude-plugin/plugin.json` as a plugin in every session, with no flag and no install step. `claude plugin init` scaffolds one of these plugins for you.
#### Scaffold the plugin with `claude plugin init`
`claude plugin init` writes a starter plugin under `~/.claude/skills/`. Requires Claude Code v2.1.157 or later. Scaffold one from your shell:
```bash theme={null}
claude plugin init my-tool
```
The command creates `~/.claude/skills/my-tool/` with a `.claude-plugin/plugin.json` and a root `SKILL.md`. It prints `✔ Created plugin "my-tool" at ~/.claude/skills/my-tool` followed by `It will auto-load next session as my-tool@skills-dir. Run /reload-plugins to load it now.`
Pass `--with skills` to have `claude plugin init` scaffold a skill under `skills/` for you. The other `--with` values are on the [plugin commands reference](/docs/en/plugins/cli-reference#plugin-init).
<h4 id="skill-names-in-a-scaffolded-plugin">
Name the plugin's skills
</h4>
The root skill at `~/.claude/skills/my-tool/SKILL.md` is also a personal skill, so you invoke it as `/my-tool`, not `/my-tool:my-tool`. Skills you add under `skills/` inside the plugin get the plugin-name prefix, such as `/my-tool:example`.
#### Stop loading the plugin
To stop loading a scaffolded plugin, delete its directory, or run `claude plugin disable my-tool@skills-dir` in your shell with the `my-tool@skills-dir` name that `claude plugin init` printed. In the ID `my-tool@skills-dir`, `skills-dir` stands where a marketplace name would, because the plugin loads from your skills directory rather than from a marketplace.
<h4 id="load-a-plugin-for-everyone-in-one-repository">
Share the plugin through a repository
</h4>
`claude plugin init` writes the plugin to your personal skills directory at `~/.claude/skills/`, so it loads for you in every project. To make a plugin load for everyone in one repository, create the same layout yourself at `<project>/.claude/skills/<name>/`, including its `.claude-plugin/plugin.json`. See [Plugins shared through a repository](/docs/en/plugins/loading#plugins-shared-through-a-repository) for the conditions under which Claude Code loads it.
## Test and debug
When a change to your plugin doesn't show up, work through these checks in order. Each one tells you what Claude Code did with the plugin:
1. In your shell, run `claude plugin validate <path>`. It checks the manifest and the frontmatter of every skill, agent, and command file, and exits `0` on `Validation passed`. Add `--strict` to fail on warnings too. Exit codes and directory handling are on the [plugin commands reference](/docs/en/plugins/cli-reference#plugin-validate).
2. In the running session, run `/reload-plugins` to apply edits you made on disk. It prints one `Reloaded:` line with counts. Then confirm a skill loaded by typing its `/plugin-name:skill` command, or by finding the plugin in the `/plugin` **Installed** tab.
3. In the same session, run `/plugin`. The **Installed** tab lists your plugin and, in the plugin's details, the components Claude Code found. The **Errors** tab lists what failed to load and why, such as a path in your manifest that doesn't exist.
4. Back in your shell, run `claude plugin list`. It prints session-only and skills-directory plugins in their own sections with `Status: ✔ loaded` or the load error. To include the plugin you're developing, pass `--plugin-dir` with its path before `plugin list`.
To check an MCP server, run `/mcp` in the session to see the server's status. When the server is healthy, `/mcp` lists it as connected. If it isn't, see [MCP servers that don't start](/docs/en/plugins/troubleshooting#invalid-mcp-server-config-for-and-mcp-servers-that-dont-start).
To check a hook, trigger the event it matches. For example, ask Claude to edit a file to trigger a `PostToolUse` hook. Then read the [debug log](/docs/en/hooks#debug-hooks), which shows which hooks matched, their exit codes, and their output.
The next sections cover the failures you're most likely to hit while developing, and the [troubleshooting page](/docs/en/plugins/troubleshooting#build-a-plugin) has the full entry for each.
### A component path isn't found
The **Errors** tab of `/plugin` shows `<component> path not found: <path>`, for example `commands path not found`. A component path in your manifest, such as `commands`, `skills`, `agents`, or `hooks`, points at nothing. Fix the path or create the directory, then run `/reload-plugins` in the session. See [`commands path not found`](/docs/en/plugins/troubleshooting#commands-path-not-found).
### `--plugin-dir` at a marketplace root doesn't load the plugins under `plugins/`
`--plugin-dir` takes the plugin's root directory, the one that contains `.claude-plugin/plugin.json` and the component directories such as `skills/`. If you point it at a marketplace root instead, Claude Code doesn't read `marketplace.json`, so a plugin under `plugins/` doesn't load, and you see no error. Point the flag at one plugin's folder, or add the marketplace. See [the troubleshooting entry](/docs/en/plugins/troubleshooting#plugin-dir-loads-a-plugin-with-no-components).
### The plugin loads but its skills are missing
The `skills/` directory is inside `.claude-plugin/`, or a `skills` entry in the manifest points at a file. Move `skills/` to the plugin root, point each `skills` entry at a directory that contains `SKILL.md`, and run `/reload-plugins` in the session. See [Plugin loads but its skills are missing](/docs/en/plugins/troubleshooting#plugin-loads-but-its-skills-are-missing).
### The `userConfig` dialog never appears
The dialog for your plugin's [`userConfig`](/docs/en/plugins/components#user-configuration) options is part of installing through `/plugin` in a session. Loading with `--plugin-dir` doesn't show it, and neither does `claude plugin install` in the shell. With the plugin loaded, run `/plugin configure <plugin-name>` in the session to open it. See [The `userConfig` dialog never appears](/docs/en/plugins/troubleshooting#the-userconfig-dialog-never-appears).
### Check that the plugin changes Claude's behavior
A plugin that loads without errors can still fail to steer Claude the way you intend. `claude plugin eval`, which you run in your shell, runs your test cases with and without the plugin and scores the difference. See [Test plugins with evals](/docs/en/plugin-evals), starting with [Create your first eval suite](/docs/en/plugin-evals#create-your-first-eval-suite).
<h2 id="convert-an-existing-claude-setup">
Convert an existing `.claude/` setup
</h2>
If you already have skills, agents, or hooks under a project's `.claude/` directory, you can move them into a plugin without rewriting them.
Run the commands in these steps from the project root, which is the directory that contains `.claude/`, because the `cp` paths are relative to it.
<Steps>
<Step title="Create the plugin structure">
Create the plugin directory and its `.claude-plugin/` folder alongside `.claude/`. You can move the plugin anywhere afterwards.
```bash theme={null}
Cut at 300 lines. The page has the rest.
plugins/create-marketplace New page · 221 lines, new page
# Create a marketplace ## Create a marketplace ## Add plugin entries ## Rules for plugin entries ### Write relative paths from the marketplace root ### Keep the entry name and the manifest name the same ## Choose a plugin source ## Validate and test ### Problems that validation reports ### Problems that surface when you add or install ### Test an edit to a plugin ### Remove the marketplace to start over ## Host your marketplace ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Create a marketplace
> Build a plugin marketplace from a marketplace.json file and test it locally before you host it.
A plugin marketplace is a directory or repository with a `.claude-plugin/marketplace.json` file that lists your plugins and where to fetch each one. You push the directory to a git host, and anyone with access registers it in Claude Code with one command and installs your plugins from it.
Create your own marketplace when you want a group you choose, such as your team or your organization, to install your plugins and keep receiving your updates from a catalog you control. The repository can be private, it can list as many plugins as you like, and an administrator can [require it on every machine](/docs/en/plugins/org).
<Note>
These cases are covered on other pages:
* **Sharing one plugin with a few people**: send them the plugin's directory or a `.zip` of it. See [Share a plugin without a marketplace](/docs/en/plugins/publish#share-a-plugin-without-a-marketplace).
* **Offering a plugin to everyone**: submit it to Anthropic's community marketplace. See [Submit to the community marketplace](/docs/en/plugins/publish#submit-to-the-community-marketplace).
* **Using a plugin yourself**: load it with `--plugin-dir` or save it in your skills directory. See [Develop without a marketplace](/docs/en/plugins/create#develop-without-a-marketplace).
</Note>
Start with [Create a marketplace](#create-a-marketplace) to build one on your own machine and install a plugin from it, then [add more plugin entries](#add-plugin-entries).
## Create a marketplace
The following steps create a marketplace on your machine, add a plugin to it, register it in Claude Code, and install the plugin from it. That is the whole loop, and it's the same loop your users go through once you host the marketplace somewhere they can reach. Run every command in your shell, from the directory where you want `my-marketplace/` created.
You need a plugin to list. The example uses `my-first-plugin` from [Create your first plugin](/docs/en/plugins/create#create-your-first-plugin), a plugin with one skill that you run as `/my-first-plugin:hello`; build it first if you don't have a plugin yet. To use a plugin of your own instead, substitute its directory and its `name` wherever the steps say `my-first-plugin`. For what a plugin directory can contain, see the [plugin directory explorer](/docs/en/plugins/components#explore-the-plugin-directory).
<Steps>
<Step title="Set up the marketplace directory">
A marketplace is a directory with a `.claude-plugin/marketplace.json` file, plus the plugins it lists. Create the marketplace directory and its `.claude-plugin/` folder, then copy your plugin in under `plugins/`:
```bash theme={null}
mkdir -p my-marketplace/.claude-plugin my-marketplace/plugins
cp -r my-first-plugin my-marketplace/plugins/
```
Check that the plugin is valid where it now sits, so that any later error is about the marketplace and not the plugin:
```bash theme={null}
claude plugin validate ./my-marketplace/plugins/my-first-plugin
```
The last line of the output reads `✔ Validation passed`.
</Step>
<Step title="Create the marketplace file">
Save `marketplace.json` at `my-marketplace/.claude-plugin/marketplace.json`. The file requires a `name`, an `owner`, and a `plugins` array.
Each object in `plugins` is a plugin entry and needs a `name` and a `source`. Write the entry's `source` as a path from the marketplace root. The root is `my-marketplace/`, the directory that contains `.claude-plugin/`.
```json my-marketplace/.claude-plugin/marketplace.json theme={null}
{
"name": "my-marketplace",
"description": "Plugins for my team",
"owner": {
"name": "Your Name"
},
"plugins": [
{
"name": "my-first-plugin",
"source": "./plugins/my-first-plugin",
"description": "A greeting plugin to learn the basics"
}
]
}
```
</Step>
<Step title="Validate the marketplace">
Run `claude plugin validate` on the marketplace directory to check the JSON syntax, the required fields, and each plugin entry in its `.claude-plugin/marketplace.json`.
```bash theme={null}
claude plugin validate ./my-marketplace
```
For the file as written in step 2, the last line of the output reads `✔ Validation passed`.
</Step>
<Step title="Add the marketplace and install the plugin">
Register the directory as a marketplace.
```bash theme={null}
claude plugin marketplace add ./my-marketplace
```
The command prints `✔ Successfully added marketplace: my-marketplace (declared in user settings)`, which means the marketplace is recorded in your user settings file.
Install the plugin. The install id is the entry's `name`, an `@`, and the marketplace `name`.
```bash theme={null}
claude plugin install my-first-plugin@my-marketplace
```
The command prints `✔ Successfully installed plugin: my-first-plugin@my-marketplace (scope: user)`.
Inside a session, `/plugin marketplace add ./my-marketplace` registers the marketplace the same way. `/plugin install my-first-plugin@my-marketplace` opens the plugin's details in the `/plugin` panel, where you install it. For that flow, see [Install and manage plugins](/docs/en/plugins/install).
</Step>
<Step title="Confirm the plugin loaded">
List installed plugins.
```bash theme={null}
claude plugin list
```
The output lists `my-first-plugin@my-marketplace` with `Status: ✔ enabled`.
To see what the plugin loaded, show its details.
```bash theme={null}
claude plugin details my-first-plugin
```
The `Component inventory` section reads `Skills (1) hello`.
To run the skill, start a session and enter `/my-first-plugin:hello`. Claude greets you. The command has the plugin's name as a prefix, as every plugin skill's name does.
</Step>
</Steps>
## Add plugin entries
Every plugin you distribute is one object in the `plugins` array of `marketplace.json`. To add a second plugin, add a second object. These fields cover most entries:
* `name`: the identifier people type before `@` when they install. It can't contain spaces.
* `source`: where Claude Code fetches the plugin from. Write a relative path string for a plugin inside the marketplace directory, as in [the walkthrough](#create-a-marketplace), or a source object for a plugin outside it. See [Choose a plugin source](#choose-a-plugin-source).
* `description`: the line people see next to the plugin when they browse your marketplace in `/plugin`.
For the full field list, see [Plugin entries](/docs/en/plugins/marketplace-reference#plugin-entries).
An entry can also set any [`plugin.json`](/docs/en/plugins/manifest-reference) field. For when an entry's `plugin.json` fields apply to a plugin that has its own `plugin.json`, see [Entry and plugin.json](/docs/en/plugins/marketplace-reference#entry-and-plugin-json).
## Rules for plugin entries
Most failed installs from a new marketplace come from a relative path written from the wrong directory, or from an entry name that differs from the `name` in the plugin's `plugin.json`.
### Write relative paths from the marketplace root
The marketplace root is the directory that contains `.claude-plugin/`. In [the walkthrough](#create-a-marketplace), that's `my-marketplace/`, so the entry's `source` is `"./plugins/my-first-plugin"`. The path doesn't start inside `.claude-plugin/`, so don't use `..` to leave it.
A path with `..` and a path to a missing directory fail at different commands:
* **A path with `..`**: `claude plugin validate` reports the entry as invalid. The message begins `Path contains "..": ./../plugins/my-first-plugin`.
* **A path to a directory that doesn't exist**: `claude plugin validate` passes. `claude plugin install` fails with `Source path does not exist: <path>`, and `<path>` is the absolute location Claude Code checked.
### Keep the entry name and the manifest name the same
A marketplace plugin has an entry `name` in `marketplace.json` and a `name` in its own `plugin.json`, called the manifest name. Each name appears in different places:
* **Entry name**: the install id, `<entry-name>@<marketplace>`. It's what people type to install, what `claude plugin list` shows, and the key Claude Code writes under [`enabledPlugins`](/docs/en/settings-reference#enabledplugins) in their settings file.
* **Manifest name**: the prefix on the plugin's skills, and the name `claude plugin details` takes.
When the two names differ and someone installs by the manifest name, Claude Code reports `Plugin "<manifest-name>" not found in marketplace "<marketplace>"`. Keep the two names the same. For more on how Claude Code uses the two names, see [Plugin loading reference](/docs/en/plugins/loading#find-where-a-plugin-came-from).
## Choose a plugin source
Each plugin entry in `marketplace.json` has a `source` that tells Claude Code where to fetch that one plugin. Pick the source by where the plugin's files are stored. The table lists the sources most marketplace owners use.
| Source | Use it when | Minimal `source` value |
| :------------ | :------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------- |
| Relative path | The plugin's files are inside the marketplace directory itself | `"./plugins/my-first-plugin"` |
| `github` | The plugin is a GitHub repository of its own | `{ "source": "github", "repo": "your-org/my-first-plugin" }` |
| `git-subdir` | The plugin is a subdirectory of some other repository, such as a monorepo | `{ "source": "git-subdir", "url": "your-org/monorepo", "path": "tools/my-first-plugin" }` |
In a `git-subdir` source, `url` takes a git URL or an `owner/repo` GitHub shorthand.
A plugin can also come from one of these source types:
* `url`: a git repository by URL, on any host
* `archive`: a zip file downloaded over HTTPS
* `npm`: an npm package
* `command`: a directory produced by running a command on the machine where the plugin is installed
For the fields of every source type, and for pinning a git-based source to a `ref` or `sha`, see [Plugin sources](/docs/en/plugins/marketplace-reference#plugin-sources).
## Validate and test
As you add plugins, run `claude plugin validate ./my-marketplace` in your shell after every edit, and install from the marketplace on your own machine before you share it. Validation and installation catch different problems.
### Problems that validation reports
`claude plugin validate` reads only files inside the marketplace directory. It reports:
* JSON syntax errors, as `json: Invalid JSON syntax: <reason>`
* Missing required fields, such as `owner: Invalid input`
* A marketplace name with spaces, non-ASCII characters, or a form that imitates an official Anthropic marketplace, such as `claude-official`
* A relative `source` that contains `..`
* Unknown fields at the top level or in a plugin entry, as warnings
* Problems in the `plugin.json` of each relative-path plugin, as `plugins[N] plugin.json → <field>: <message>`
For every message `validate` can print, see [Validation messages](/docs/en/plugins/marketplace-reference#validation-messages). For its flags and exit codes, see [`plugin validate`](/docs/en/plugins/cli-reference#plugin-validate).
### Problems that surface when you add or install
Problems that `claude plugin validate` doesn't report appear when you add the marketplace or install from it:
* **When you add the marketplace**: the exact [official marketplace names](/docs/en/plugins/marketplace-reference#reserved-names), such as `claude-plugins-official`, pass validation. When you add a marketplace with one of those names, Claude Code refuses it with a message that starts `The name '<name>' is reserved for official Anthropic marketplaces`.
* **When you install a plugin**:
* Claude Code first fetches a `github`, `git-subdir`, or other remote source when you install the plugin, so a wrong `repo` or `path` appears then.
* A relative `source` whose directory doesn't exist also fails at install, with `Source path does not exist: <path>`.
### Test an edit to a plugin
In [the walkthrough](#create-a-marketplace), you added `my-marketplace` from a local directory with a relative-path `source`. With that setup, Claude Code reads the plugin's files directly from `my-marketplace/plugins/`. Your edits take effect at the next session start or when you run `/reload-plugins` in a session, with no change to the plugin's `version`.
People who install from your hosted marketplace get a copy in the plugin cache instead. For how they receive a new version, see [Keep users up to date](/docs/en/plugins/host-marketplace#keep-users-up-to-date).
### Remove the marketplace to start over
To remove everything and start over, run `claude plugin marketplace remove my-marketplace` in your shell. The command removes the marketplace and uninstalls its plugins.
## Host your marketplace
Once you can install a plugin from the marketplace on your own machine, as in [Create a marketplace](#create-a-marketplace), push the marketplace directory to a git host.
Your teammates then run `claude plugin marketplace add <owner>/<repo>` in their shell for a GitHub repository, or the same command with the repository URL. They then install a plugin by name as in [the walkthrough](#create-a-marketplace).
For private-repository access, updates, versioning, and renaming or removing entries, see [Host and maintain a marketplace](/docs/en/plugins/host-marketplace).
## Next steps
* [Host and maintain a marketplace](/docs/en/plugins/host-marketplace): pick a host, keep users up to date, and rename or remove plugins safely
* [Marketplace reference](/docs/en/plugins/marketplace-reference): `marketplace.json` fields and source types
* [Manage plugins for your organization](/docs/en/plugins/org): require your marketplace and its plugins on every machine
* [Suggest plugins by relevance](/docs/en/plugins/relevance): have Claude Code suggest a plugin from your marketplace when a session matches
plugins/dependencies New page · 217 lines, new page
# Plugin dependencies ## Declare dependencies ### Declare a dependency with a version constraint ### Bundle plugins for a team ### Depend on a plugin from another marketplace ### Test a plugin and its dependency locally ### Create a release tag ### Constrain a dependency that has a non-git source ## How dependencies behave for your users ### How a constraint resolves against tags ### Confirm the resolved version ### Combine constraints from several plugins ## See also
A whole new page. There's nothing to diff it against, so here is what it says.
# Plugin dependencies
> Declare the plugins your plugin depends on, with version ranges such as ^1.2, and see how Claude Code installs, resolves, and prunes them.
A plugin dependency is another plugin that your plugin relies on, such as one whose MCP server or skill it calls. Each dependency tracks the latest version its marketplace provides unless you declare a version constraint, a semantic-version range such as `^2.0` or `~2.1.0` that you've tested against.
This page is for plugin authors who declare dependencies in `plugin.json` and for marketplace maintainers who tag releases.
<Note>
These cases are covered on other pages:
* **Installing a plugin that has dependencies**: see [Manage installed plugins](/docs/en/plugins/install#manage-installed-plugins)
* **Reading a dependency error**: see [Dependency errors](/docs/en/plugins/troubleshooting#dependency-errors)
* **Declaring the npm and Bun packages that your plugin's own code needs**: see [Node.js package dependencies](/docs/en/plugins/loading#node-js-package-dependencies)
</Note>
To add a constraint, start at [Declare a dependency with a version constraint](#declare-a-dependency-with-a-version-constraint). If you maintain a plugin that others depend on, [tag your releases](#tag-plugin-releases-for-version-resolution) so their constraints can resolve.
## Declare dependencies
<span id="decide-whether-to-constrain-dependency-versions" />Without a version constraint, a dependency moves to each new release its marketplace publishes the next time users update. If that release renames an MCP tool your plugin calls, your plugin breaks for everyone who updates.
With a constraint such as `~2.1.0` on a dependency from a git-backed source, users who have your plugin installed keep receiving `2.1.x` patches of the dependency and never move to `2.2`. To upgrade on your own schedule, test against a newer release and then publish a new version of your plugin with a wider constraint.
### Declare a dependency with a version constraint
List dependencies in the `dependencies` array of your plugin's `.claude-plugin/plugin.json`. The following manifest declares one unversioned dependency and one constrained dependency:
```json .claude-plugin/plugin.json theme={null}
{
"name": "deploy-kit",
"version": "3.1.0",
"dependencies": [
"audit-logger",
{ "name": "secrets-vault", "version": "~2.1.0" }
]
}
```
An entry can be a string: the plugin name alone, such as `"audit-logger"` in this manifest, or `"name@marketplace"` to resolve it in another marketplace. With a bare string, your plugin depends on whatever version that plugin's marketplace provides.
To set a version constraint, use an object with these fields, each a string:
| Field | Description |
| :------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | The dependency's plugin name, as it appears in its marketplace entry. Claude Code looks it up in the same marketplace as the declaring plugin unless you set `marketplace`. Required. |
| `version` | A [semantic-version range](https://github.com/npm/node-semver#ranges) such as `~2.1.0`, `^2.0`, `>=1.4`, or `=2.1.0`. The dependency installs at the highest git tag that satisfies this range, so the dependency's maintainer must [tag releases](#tag-plugin-releases-for-version-resolution). |
| `marketplace` | A different marketplace to resolve `name` in. An allowlist controls cross-marketplace dependencies, described in [Depend on a plugin from another marketplace](#depend-on-a-plugin-from-another-marketplace). |
A range doesn't match pre-release versions such as `2.0.0-beta.1` unless you opt in with a pre-release suffix such as `^2.0.0-0`.
### Bundle plugins for a team
To let engineers install a curated set of plugins with one command, publish a plugin whose manifest contains a `name` and a `dependencies` array. A plugin manifest needs only `name`, so this is a valid plugin, and installing it installs every dependency.
For example, a platform team can publish role-specific bundles in an internal marketplace so engineers run one `claude plugin install` instead of installing each plugin separately:
```json .claude-plugin/plugin.json theme={null}
{
"name": "backend-standard",
"version": "1.0.0",
"description": "Standard plugin set for backend engineers",
"dependencies": [
"secrets-vault",
"deploy-kit",
{ "name": "db-migrate", "version": "^3.0" },
"oncall-runbook"
]
}
```
To add a plugin to the standard set later, publish a new `backend-standard` version with the extra dependency. When the marketplace doesn't [auto-update by default](/docs/en/plugins/loading#which-marketplaces-and-plugins-auto-update), engineers either turn on auto-update for the marketplace or update manually:
* **Turn on auto-update for the marketplace**: the next auto-update moves the bundle to the new version and installs any dependencies it adds.
* **Update manually**: run `claude plugin update backend-standard` in a shell, then `/reload-plugins` in an open session to install the newly added dependencies.
For the engineer-side steps, see [Keep plugins updated](/docs/en/plugins/install#keep-plugins-updated).
To deploy a bundle to everyone in an organization, an administrator adds it to `enabledPlugins` in managed settings. See [Pre-install and require plugins](/docs/en/plugins/org#pre-install-and-require-plugins).
### Depend on a plugin from another marketplace
By default, Claude Code doesn't install a dependency from a different marketplace than the declaring plugin's own, unless the user already has that dependency installed and enabled at the same scope. This default prevents one marketplace from silently installing plugins from a source the user hasn't reviewed.
To allow the install, add the target marketplace's name to `allowCrossMarketplaceDependenciesOn` in the root marketplace's `marketplace.json`. The root marketplace is the one that hosts the plugin the user is installing. Only the root marketplace's allowlist applies.
The following `marketplace.json` allows `deploy-kit` to depend on a plugin from `your-shared-marketplace`:
```json .claude-plugin/marketplace.json theme={null}
{
"name": "your-marketplace",
"owner": { "name": "Your Org" },
"allowCrossMarketplaceDependenciesOn": ["your-shared-marketplace"],
"plugins": [
{
"name": "deploy-kit",
"source": "./deploy-kit",
"dependencies": [
{ "name": "audit-logger", "marketplace": "your-shared-marketplace" }
]
}
]
}
```
If `allowCrossMarketplaceDependenciesOn` is missing or doesn't include the target marketplace, Claude Code doesn't install the dependency. When the dependency is declared in the marketplace entry, the install itself is refused with a message that starts `Dependency "audit-logger@your-shared-marketplace" (required by deploy-kit@your-marketplace) is in marketplace "your-shared-marketplace", which is not in the allowlist` and names the field to set. When it's declared in `plugin.json`, the install completes without the dependency and your plugin then fails to load.
The allowlist check doesn't apply to a dependency that is already enabled. If a user installs `audit-logger` from `your-shared-marketplace` themselves first, at the same scope, `deploy-kit` then installs without any change to the allowlist.
### Test a plugin and its dependency locally
If you're developing a plugin and the plugin it depends on at the same time, start Claude Code from your shell and load both with [`--plugin-dir`](/docs/en/plugins/cli-reference#flags-that-load-a-plugin-for-one-session):
```bash theme={null}
claude --plugin-dir ./my-dependency --plugin-dir ./my-plugin
```
The local copy of the dependency satisfies your plugin's dependency entry, so you don't need to install the dependency from its marketplace.
* **No `version` needed**: the local `plugin.json` doesn't need a `version` either, because a [version constraint](#declare-a-dependency-with-a-version-constraint) isn't checked against a local copy.
* **Entries that name a marketplace**: an entry that names a marketplace also matches the local copy on Claude Code v2.1.242 or later.
Until you install the dependency from its marketplace, your plugin stops loading whenever the local copy is disabled or absent:
* **You disabled the local copy**: your plugin is disabled at the next plugin load, with an error that ends `is disabled — enable it or remove the dependency`. When the error names the dependency as `<name>@inline`, that identifier refers to the `--plugin-dir` copy.
* **You started a session without the dependency's `--plugin-dir` flag**: the error reports the dependency as not installed. Pass the flag again, or install the dependency from its marketplace.
When both plugins are in one parent folder, you can pass that folder to `--plugin-dir` once. If the folder isn't itself a plugin, Claude Code loads each child folder that has a `.claude-plugin/plugin.json`. Requires Claude Code v2.1.265 or later.
<h2 id="tag-plugin-releases-for-version-resolution">
Release a plugin that others depend on
</h2>
If you maintain a plugin that other plugins depend on with a version constraint, tag its releases so those constraints can resolve. A constraint resolves against git tags on the repository that hosts the plugin. Tag the repository that the plugin's [plugin source](/docs/en/plugins/marketplace-reference#plugin-sources) in `marketplace.json` points at:
* **`github`, `url`, or `git-subdir` source**: the plugin's own repository, so the plugin's author creates the tags
* **Relative path such as `./plugins/secrets-vault`**: the marketplace repository, so the marketplace maintainer creates the tags
### Create a release tag
Tag each release as `<plugin-name>--v<version>`, where `<version>` matches the `version` field in that commit's `plugin.json`. The plugin-name prefix lets one marketplace repository host several plugins with independent version histories.
Create the tag from the plugin directory, with an `origin` remote configured to receive the pushed tag, using [`claude plugin tag`](/docs/en/plugins/cli-reference#plugin-tag):
```bash theme={null}
claude plugin tag --push
```
The command builds the tag name from the plugin's manifest. Before creating the tag, it runs these checks:
* Validates the plugin
* Checks that `plugin.json` and the marketplace entry agree on the version, when the plugin directory is inside a marketplace checkout
* Requires a clean working tree under the plugin directory
* Refuses if the tag already exists
A successful run prints `Created tag secrets-vault--v2.1.0`. With `--push`, it also prints `Pushed to origin`. Without `--push`, it prints the `git push` command to run yourself.
Pass `--dry-run` to see the plan without creating anything.
The [`claude plugin tag` reference](/docs/en/plugins/cli-reference#plugin-tag) lists the remaining flags.
You can also run `git tag secrets-vault--v2.1.0` directly, as long as you keep the `version` in `plugin.json` and in the marketplace entry in sync yourself.
### Constrain a dependency that has a non-git source
Tag-based resolution applies only to git-backed sources. For a dependency with an `npm`, `archive`, or `command` [plugin source](/docs/en/plugins/marketplace-reference#plugin-sources), the constraint doesn't control which version is fetched. It's still checked when the plugin loads, and the dependent plugin is disabled if the installed version doesn't satisfy it.
For `npm`, `archive`, and `command` sources, the version checked is the `version` in the dependency's `plugin.json`. Set one there before you constrain that dependency, because a `plugin.json` that sets no version satisfies no constraint.
Claude Code never installs a dependency with a `command` source itself, so users [install it first](/docs/en/plugins/marketplace-reference#command-plugin-source). It also never runs a dependency's [`headersHelper`](/docs/en/plugins/host-marketplace#authenticate-archive-downloads), so users also install a dependency whose marketplace entry sets one before they install your plugin.
Besides `claude plugin install`, these operations also install any missing declared dependency, and the `command` and `headersHelper` limits apply to them too:
* `/reload-plugins`
* Auto-update of the dependent plugin's marketplace
* Re-running `claude plugin install` on the dependent plugin
* `claude plugin marketplace add`
## How dependencies behave for your users
These sections describe how Claude Code resolves, checks, and combines the constraints you declare once your plugin is installed alongside others.
### How a constraint resolves against tags
When a user installs a plugin that declares `{ "name": "secrets-vault", "version": "~2.1.0" }`, the dependency installs from the highest `secrets-vault--v` tag that satisfies `~2.1.0` on the repository that hosts `secrets-vault`. When no tag satisfies the range, the install either fails or uses the marketplace's current copy:
* **Plugin with its own repository**: the install fails with a message containing `Dependency "secrets-vault@your-marketplace" has no git tag satisfying`.
* **Plugin referenced by a relative path**: the install uses the marketplace's current copy instead, and the constraint is checked when the plugin loads. If that copy is outside the range, the dependent plugin stays disabled and `claude plugin list` shows `Requires "secrets-vault@your-marketplace" ~2.1.0, installed 3.0.0`.
For a plugin the marketplace references by a relative path, a marketplace you added as a local folder path also resolves constraints against that folder's git tags, when the folder is a git repository. This requires Claude Code v2.1.196 or later. A local folder that isn't a git repository has no tags, so Claude Code installs the dependency from the folder's current contents instead.
### Confirm the resolved version
To confirm which version a constraint resolved to, run `claude plugin list` in your shell. A tag-resolved dependency shows its version with a 12-character commit suffix, such as `2.1.0-8713c5b11005`.
Constraint checks use the tag's version rather than the `version` in `plugin.json`, even if `plugin.json` at that commit lags behind.
If you force-move a tag to a different commit, the next install fetches that commit's content instead of reusing a stale cached copy. See [Versions and updates](/docs/en/plugins/loading#versions-and-updates) for how a plugin's version becomes its cache key.
### Combine constraints from several plugins
When several installed plugins constrain the same dependency, the dependency resolves to the highest version that satisfies all of their ranges. Common combinations resolve like this:
| Plugin A requires | Plugin B requires | Result |
| :---------------- | :---------------- | :------------------------------------------------------------------------------------------------------------------------------ |
| `^2.0` | `>=2.1` | One install at the highest `2.x` tag at or above `2.1.0`. Both plugins load. |
| `~2.1` | `~3.0` | Installing plugin B fails with a `has conflicting version requirements` message. Plugin A and the dependency stay as they were. |
| `=2.1.0` | none | The dependency stays at `2.1.0`. Auto-update skips newer versions while plugin A is installed. |
Auto-update fetches a constrained dependency at the highest git tag that satisfies every installed plugin's range, rather than at the marketplace's latest version. If the installed plugins' ranges don't overlap, auto-update leaves that dependency at its current version, and the `/plugin` **Errors** tab shows an entry naming the constraining plugin. If they overlap but no tag falls in the range, auto-update fetches the marketplace's current copy and skips the update when that copy's `version` falls outside any installed plugin's range.
When a user uninstalls the last plugin that constrains a dependency, the dependency is no longer constrained to a version range and resumes tracking its marketplace entry on the next update.
## See also
* [`claude plugin prune`](/docs/en/plugins/cli-reference#plugin-prune): remove auto-installed dependencies no plugin needs anymore
* [Host a marketplace](/docs/en/plugins/host-marketplace): release channels and recommending other plugins
plugins/host-marketplace New page · 398 lines, new page
# Host and maintain a marketplace ## Host your marketplace ### Register the marketplace for everyone in a repository ### Avoid relative-path entries in a URL-hosted marketplace ### Edit plugins in place on a shared directory ### Keep plugin files out of Git LFS ### Share files within a marketplace with symlinks ## Distribute through organization settings ## Grant access to a private marketplace ### Serve users who have no git-host account ### What background auto-update does with credentials ## Roll out to a whole company ## Keep users up to date ### Turn on auto-update ### Release a new version ### Hold users on one version ### Change the command of a command source ## Run release channels ## Rename or remove a plugin ### Migrate users with a renames map ### Uninstall removed plugins from users' machines ## Authenticate archive downloads ### Add a headersHelper to a plugin entry ### Write the headersHelper command ### When Claude Code skips a headersHelper command or drops its output ### How users accept a headersHelper command ## Depend on and recommend other plugins ## Work around what a marketplace can't do ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Host and maintain a marketplace
> Publish a plugin marketplace where users can reach it, grant access to a private one, and release updates and renames without breaking installs.
Hosting a marketplace means putting your `marketplace.json` catalog where other people can add it with `/plugin marketplace add`, install its plugins, and keep receiving your changes after you push.
This page is for the person who operates a marketplace.
<Note>
These cases are covered on other pages:
* **You haven't written the catalog file yet**: start with [Create a marketplace](/docs/en/plugins/create-marketplace)
* **You're an admin requiring, restricting, or pre-installing marketplaces across your organization's machines**: read [Manage plugins for your organization](/docs/en/plugins/org)
</Note>
Start with [Host your marketplace](#host-your-marketplace) to pick a host and the command your users run. Read [Keep users up to date](#keep-users-up-to-date) before your first release. Read [Rename or remove a plugin](#rename-or-remove-a-plugin) before you change a plugin's `name`.
## Host your marketplace
You can host the marketplace on GitHub, on another git host, as a hosted `marketplace.json` URL, or in a directory on a shared filesystem. Send your users the add command for your host and tell them what they need on their machine:
| Host | Users run, in a Claude Code session | What users need |
| :--------------------------------------------------------------- | :--------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- |
| GitHub | `/plugin marketplace add your-org/your-marketplace` | `git`, and for a private repository the access described under [Grant access to a private marketplace](#grant-access-to-a-private-marketplace) |
| GitLab, Bitbucket, GitHub Enterprise Server, or another git host | `/plugin marketplace add https://gitlab.example.com/team/plugins.git` | `git`, and access to the host from their machine. Send the full URL, because `owner/repo` shorthand always means github.com |
| A hosted `marketplace.json` URL | `/plugin marketplace add https://plugins.example.com/marketplace.json` | HTTPS access to the URL. Users don't need `git` for the catalog itself |
| A directory on a shared filesystem | `/plugin marketplace add /Volumes/shared/claude-plugins` | Read access to the path |
To pin a branch or tag of a GitHub or git-URL marketplace, tell users to append `#<ref>`, as in `your-org/your-marketplace#stable`. The [plugin commands reference](/docs/en/plugins/cli-reference#plugin-marketplace-add) lists every form the command accepts.
A successful add prints `Successfully added marketplace: your-marketplace`. Claude Code takes that name from the `name` field in your `marketplace.json`, not from the repository name.
Users then install a plugin by its entry's `name` and the marketplace's `name`, as in `/plugin install code-formatter@your-marketplace`.
### Register the marketplace for everyone in a repository
To share the marketplace with everyone who works in one repository, run `claude plugin marketplace add your-org/your-marketplace --scope project` there once from your shell and commit the `.claude/settings.json` it writes. Claude Code then registers the marketplace for each teammate who [trusts the folder](/docs/en/plugins/org#require-plugins-per-repository).
### Avoid relative-path entries in a URL-hosted marketplace
When users add your marketplace as a bare `marketplace.json` URL, Claude Code downloads only that file. An entry in your `plugins` array whose `source` is a relative path such as `./plugins/formatter` then fails at install with [`its marketplace entry path does not stay inside the marketplace directory`](/docs/en/plugins/troubleshooting#plugins-with-relative-paths-fail-in-url-based-marketplaces). Give every entry a source that can be fetched on its own, such as a `github` repository or an `archive` URL, or host the marketplace in a git repository so Claude Code clones the whole tree.
### Edit plugins in place on a shared directory
When users add your marketplace from a shared directory, Claude Code reads plugins with relative-path sources directly from that directory instead of copying them. Users see your edits when they next start a session or run `/reload-plugins`, without an update step or a version bump.
### Keep plugin files out of Git LFS
Keep the files your plugins need out of [Git LFS](https://git-lfs.com). When users add a marketplace hosted in a git repository, or install a git-based plugin it lists, Claude Code clones that marketplace or plugin repository onto their machine. The clone never downloads LFS content, so LFS-tracked files arrive as pointer files.
### Share files within a marketplace with symlinks
To share files between your plugin and other parts of the same marketplace, create symbolic links inside your plugin directory. When Claude Code copies the plugin into its cache, it handles each symlink by where the target resolves:
* **Within the plugin's own directory**: the symlink is preserved as a relative symlink in the cache, so it keeps resolving to the copied target at runtime.
* **Elsewhere within the same marketplace**: the symlink is dereferenced. The target's content is copied into the cache in its place. This lets a meta-plugin's `skills/` directory link to skills defined by other plugins in the marketplace.
* **Outside the marketplace**: the symlink is skipped for security.
For plugins installed from a local path, or from a [`command` source](/docs/en/plugins/marketplace-reference#command-plugin-source) whose `mode` is the default `copy`, Claude Code preserves only symlinks that resolve within the plugin's own directory and skips all others.
The following command creates a link from inside a marketplace plugin to a shared skill defined by a sibling plugin. On Windows, use `mklink /D` from an elevated Command Prompt or enable Developer Mode:
```bash theme={null}
ln -s ../../shared-plugin/skills/foo ./skills/foo
```
## Distribute through organization settings
On a Team or Enterprise plan, you can also distribute the marketplace through [**Organization settings > Plugins & skills**](https://claude.ai/admin-settings/skills?tab=inventory) on claude.ai instead of hosting it somewhere users add it themselves. Organization sync reads the repository through your organization's GitHub or GitLab connection on claude.ai, so your users' git credentials aren't involved.
Organization sync is stricter about the repository than `/plugin marketplace add` is:
* **Marketplace repository**: on github.com and gitlab.com, it must be private or internal
* **Plugin sources**: each plugin source must be of type `github`, `url`, or `git-subdir`, or a [relative path](/docs/en/plugins/marketplace-reference#relative-path-plugin-source) that starts with `./`
* **Top-level `bin/` directory**: claude.ai rejects a plugin that has one and syncs the rest of the marketplace. The error message starts with `Plugin contains a top-level bin/ directory`. Keep executables in another directory, such as `scripts/`, and reference them as `${CLAUDE_PLUGIN_ROOT}/scripts/<name>` from your hooks or MCP server configs
See [Manage plugins for your organization](https://support.claude.com/en/articles/13837433) for the admin workflow.
## Grant access to a private marketplace
When a user adds, installs from, or updates your marketplace, Claude Code runs `git` on their machine with interactive prompts turned off and relies on whatever credentials that machine already holds. Claude Code has no git token of its own, and `marketplace.json` has no field for one.
You choose whether the clone runs over SSH or HTTPS by the form of the add command you send users:
* **GitHub `owner/repo`**: Claude Code probes `ssh -T [email protected]` and clones over SSH when the probe succeeds. If the probe fails, or the SSH clone itself fails, it clones over HTTPS. Users on machines without a GitHub SSH key can set `CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1` to skip the probe and clone over HTTPS.
* **`git@host:path.git`**: SSH.
* **`https://example.com/repo.git`**: HTTPS.
Tell users what each protocol needs on their machine:
* **SSH**: the key must work without a passphrase prompt, for example because it's loaded in `ssh-agent`. The host must already be in `known_hosts`.
* **HTTPS**: Claude Code leaves the user's git credential helper enabled but forbids it from prompting. A credential the helper already stores works; one it would have to ask for fails. On GitHub, `gh auth login` followed by `gh auth setup-git` stores one.
For a GitHub Enterprise Server host, users need git access to that host from their machine. See [Plugin marketplaces on GHES](/docs/en/github-enterprise-server#plugin-marketplaces-on-ghes) for what each Claude Code surface needs to reach a GHES-hosted marketplace.
If you distribute through **Organization settings > Plugins & skills** on claude.ai instead, your users' git credentials aren't involved. See [Distribute through organization settings](#distribute-through-organization-settings) for which plugin sources can be private there.
### Serve users who have no git-host account
Users without a git-host account can add a marketplace you serve as a `marketplace.json` URL or from a shared directory, but they can install only the plugins whose entry sources they can also reach. An entry that points at a private `github` repository still fails at install for them, because Claude Code fetches it with the same non-interactive `git` it uses for a git-hosted marketplace.
These entry sources need no git account:
* **`archive`**: a zip downloaded over HTTPS. Users need neither `git` nor an account, only network access to the URL. Requires Claude Code v2.1.224 or later. Pin each archive with `sha256` so Claude Code refuses a changed download. To send credentials with the download, see [Authenticate archive downloads](#authenticate-archive-downloads).
* **A public git repository**: Claude Code clones a public `url` or `git-subdir` source over HTTPS without credentials when the entry gives an `https://` URL. For a `github` source, or a `git-subdir` source written as `owner/repo`, users without a GitHub SSH key set `CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1`.
For a team on one network, a `directory` marketplace on a shared filesystem also works without git accounts. Users need only read access to the path.
### What background auto-update does with credentials
Background auto-update is Claude Code's unattended refresh of marketplaces and installed plugins after a session starts. It's off for your marketplace until a user or admin turns it on, as covered under [Keep users up to date](#keep-users-up-to-date).
When it's on for a private marketplace, the background check for new commits uses the user's configured git credential helpers and never prompts. Each kind of remote and helper gives a different result:
* **SSH remotes**: a key loaded in `ssh-agent` authenticates the check.
* **HTTPS remotes with a stored credential**: a helper that can supply a stored credential without prompting authenticates the check. Git Credential Manager, the macOS Keychain helper, and `git-credential-store` work this way once they hold a credential for the host.
* **HTTPS remotes with a helper that needs to prompt**: the helper can't answer in the background. The update fails quietly and the existing checkout stays in place, so the user's plugins keep working from the last synced state.
After the check, Claude Code does one of the following:
* **The checkout is up to date**: Claude Code leaves it as it is.
* **The check finds new commits, or fails because it can't reach or authenticate to the remote**: Claude Code clones the marketplace again and replaces the existing checkout with the new clone. If that clone fails, the existing checkout stays in place. The re-clone can [time out on large repositories](/docs/en/plugins/troubleshooting#git-clone-timed-out-after-120s).
To keep a private marketplace current, a user can do either of the following:
* **Store a credential**: sign in to the credential helper first so it holds a credential for the host. For GitHub, run `gh auth login`, then `gh auth setup-git`.
* **Keep the checkout on failure**: if the user sets `CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1`, Claude Code keeps the existing checkout without attempting the re-clone when the background check can't reach or authenticate to the remote. Plugins keep working from the last synced state.
If a user sets `GITHUB_TOKEN` or another provider token in the environment, that alone doesn't authenticate the background check. A token takes effect through a credential helper, such as the `gh` CLI's helper, which reads `GH_TOKEN` and `GITHUB_TOKEN`.
## Roll out to a whole company
Rolling a plugin out to a company involves you as the marketplace owner, an administrator who controls managed settings, and each person who uses Claude Code. You can run the rollout without the administrator, in which case each person adds the marketplace and installs the plugin themselves.
| Who | What they do | Where it's covered |
| :------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
| You, the marketplace owner | Keep the catalog in a repository only the company can read, send the add command for your host, and say what each person needs on their machine | [Host your marketplace](#host-your-marketplace) and [Grant access to a private marketplace](#grant-access-to-a-private-marketplace) |
| An administrator | Registers the marketplace and turns its plugins on for everyone with `extraKnownMarketplaces` and `enabledPlugins` in managed settings, and sets `autoUpdate` there | [Require a marketplace and its plugins](/docs/en/plugins/org#require-a-marketplace-and-its-plugins) and [Set update policy](/docs/en/plugins/org#set-update-policy) |
| Each person | Needs read access to a private git repository, with credentials already stored on their machine. Without an administrator, they also run the add and install commands | [Add a private marketplace](/docs/en/plugins/install#add-a-private-marketplace) |
For people who have no git-host account, these sections each cover one way to reach them:
* **Entry sources that need no git account**: [Serve users who have no git-host account](#serve-users-who-have-no-git-host-account)
* **A pre-populated plugins directory**: [Seed containers and CI](/docs/en/plugins/org#seed-containers-and-ci), which also serves users who have no git-host account
* **claude.ai organization settings**: [Distribute through organization settings](#distribute-through-organization-settings), where your users' git credentials aren't involved
## Keep users up to date
Your changes reach users through background auto-update, once it's turned on for your marketplace, or when users update the plugin themselves. In both cases a user gets a new copy of a plugin only when its computed version changes, as described under [Release a new version](#release-a-new-version).
### Turn on auto-update
Background auto-update is off for your marketplace by default, and `marketplace.json` has no field to turn it on. A user or an admin turns it on:
* **Tell users to turn it on**: each user goes to **Marketplaces** in `/plugin`, selects your marketplace, and selects **Enable auto-update**.
* **Ask an admin to set it**: if an admin sets `"autoUpdate": true` on your marketplace's `extraKnownMarketplaces` entry in managed settings, it's on for everyone who receives those settings. See [Set update policy](/docs/en/plugins/org#set-update-policy).
Without auto-update, users receive your changes when they run `/plugin marketplace update <name>` in a session or `claude plugin update <plugin>@<name>` in the shell.
For what users see when an update reaches them, see [When auto-update runs](/docs/en/plugins/loading#when-auto-update-runs).
### Release a new version
To release a new version to users, change the plugin's `version`. Users get a new copy only when the plugin's computed version differs from the one they have. That version comes from `plugin.json` first, then from the marketplace entry, per [Versions and updates](/docs/en/plugins/loading#versions-and-updates).
A plugin that users [load in place](/docs/en/plugins/loading#find-plugins-on-disk) from a marketplace they added as a local directory isn't controlled by `version`. It loads your current files at every session start, whatever its version string says.
For every install other than an in-place load or one from a `command` source, either increase `version` on each release or omit it:
* **Bump `version` on each release**: users stay on their cached copy until the string changes. If you set `"version": "1.0.0"` and push new commits without changing it, users don't receive them.
* **Omit `version`**: users track your commits instead. Leave `version` out of both `plugin.json` and the marketplace entry.
Don't set `version` in both `plugin.json` and the marketplace entry. If you do, Claude Code uses the `plugin.json` value without warning, and `claude plugin validate` reports the mismatch as `Entry declares version "<a>" but <path>/plugin.json says "<b>"`.
### Hold users on one version
One marketplace serves one version of each plugin at a time, so you hold users on a version by choosing what each entry points at:
* **`ref` and `sha` on the plugin entry**: `ref` names a branch or tag and `sha` names a commit for a `github`, `url`, or `git-subdir` source. See [Plugin sources](/docs/en/plugins/marketplace-reference#plugin-sources).
* **`#<ref>` on the add command**: users who add `your-org/your-marketplace#stable` get that branch or tag of the catalog. For two release lines at once, see [Run release channels](#run-release-channels).
* **`<plugin>--v<version>` tags**: a dependency's version range resolves against these tags. See [Release a plugin that others depend on](/docs/en/plugins/dependencies#tag-plugin-releases-for-version-resolution).
[Release a new version](#release-a-new-version) says when a changed entry reaches users.
### Change the command of a command source
If you change the `command` of a [`command` source](/docs/en/plugins/marketplace-reference#command-plugin-source), or switch its `mode`, each user has to accept the new command before Claude Code runs it. Claude Code runs only the exact command a user accepted when they installed or last updated the plugin.
After a user's copy of your marketplace picks up the change, that user sees the following:
* **No more background runs**: the [once-per-session run](/docs/en/plugins/loading#when-a-command-source-re-runs) of the command stops for that user, so the tool's new output doesn't reach them.
* **An entry in the `/plugin` Errors tab**: the entry shows the new command and the `claude plugin update` command to run.
Tell users to run the `claude plugin update` command that entry shows, in a terminal. Claude Code shows them the new command and asks them to accept it.
## Run release channels
To offer stable and early-access tracks, host two marketplaces whose entries point at different refs of the same plugin, and let each user add the one they want. Claude Code has no release-channel concept, and one marketplace serves one version of each plugin at a time.
Give the two `marketplace.json` files different `name` values. Claude Code identifies a marketplace by its `name`, so a user can't have two marketplaces with the same name registered at once.
With these two catalogs, users who add `stable-tools` install `code-formatter` from the `stable` branch, and users who add `latest-tools` install it from `latest`:
```json theme={null}
{
"name": "stable-tools",
"owner": { "name": "Your Org" },
"plugins": [
{ "name": "code-formatter", "source": { "source": "github", "repo": "your-org/code-formatter", "ref": "stable" } }
]
}
```
```json theme={null}
{
"name": "latest-tools",
"owner": { "name": "Your Org" },
"plugins": [
{ "name": "code-formatter", "source": { "source": "github", "repo": "your-org/code-formatter", "ref": "latest" } }
]
}
```
Give the two refs different `plugin.json` versions, or omit `version` so the commit SHA distinguishes them. Updates are detected by comparing versions, so a ref that moves without a version change leaves users on the cached copy.
To assign the channels to user groups instead of letting users choose, an admin gives each group the matching `extraKnownMarketplaces` entry, as described under [Set update policy](/docs/en/plugins/org#set-update-policy).
## Rename or remove a plugin
A plugin's `name` is its identifier. Users reference it in the `enabledPlugins` and `pluginConfigs` settings keys and in `/plugin install`, so changing it breaks every existing install.
To change the label users see in `/plugin` without breaking anything, set `displayName` in `plugin.json` and keep `name` unchanged.
### Migrate users with a renames map
When you must change a `name`, add a top-level `renames` map to `marketplace.json` so Claude Code migrates existing users instead of reporting [`Plugin "<name>" not found in marketplace`](/docs/en/plugins/troubleshooting#plugin-not-found-in-marketplace). Do the same when you remove an entry from `plugins`. Automatic migration requires Claude Code v2.1.193 or later.
Map each former name to its current name, or to `null` when the plugin is gone. This marketplace renames `formatter` to `code-formatter` and records that `legacy-linter` was removed:
```json theme={null}
{
"name": "your-marketplace",
"owner": { "name": "Your Org" },
"plugins": [
{ "name": "code-formatter", "source": "./plugins/code-formatter" }
],
"renames": {
"formatter": "code-formatter",
"legacy-linter": null
}
}
```
After you push, a user who still has the old name enabled sees one of these results:
* **Renamed entry**: the plugin loads under its new name. `claude plugin list` and the plugin's details under `/plugin` show `Renamed to "code-formatter" in the "your-marketplace" marketplace` once, and Claude Code rewrites the old key to the new one in `enabledPlugins` and `pluginConfigs` in the user, project, and local settings scopes.
* **`null` entry**: the old key is dropped from those scopes and the user sees `Removed from the "your-marketplace" marketplace`.
* **Enabled in managed settings**: the plugin still loads under its new name, but Claude Code can't rewrite managed settings, so the notice recurs until an admin updates `enabledPlugins` there.
For a marketplace users added from a git repository or URL, a renamed plugin reports [`Plugin "<name>" not cached at <path>`](/docs/en/plugins/troubleshooting#plugin-not-cached-at) until the user runs `/plugin install code-formatter@your-marketplace` once in a session.
Treat `renames` as append-only history. Keep old entries after everyone has migrated. When you rename again, add a second entry rather than editing the first, because Claude Code follows the chain from the oldest name.
In your shell, run `claude plugin validate .` after editing the map. It rejects a chain that cycles or that ends anywhere other than `null` or a name in `plugins`, with `renames.<name>: chain does not resolve`.
### Uninstall removed plugins from users' machines
To uninstall a removed plugin from users' machines rather than leave a copy behind, set `"forceRemoveDeletedPlugins": true` at the top level of `marketplace.json`. Without the field, a removed plugin stays installed and reports `Plugin "<name>" not found in marketplace` when a session loads it. With it, Claude Code does the following at each session start:
1. Compares what users installed from your marketplace against the entries and the `renames` map, and treats any plugin that is neither listed nor renamed as removed.
2. Uninstalls each removed plugin from the user, project, and local scopes. Plugins that only managed settings installed stay in place.
3. Lists each removed plugin under a **Flagged** heading in `/plugin` with the status `Removed from marketplace`.
## Authenticate archive downloads
To authenticate an [`archive`](/docs/en/plugins/marketplace-reference#archive-plugin-source) download, such as a download from a private registry, set the HTTP headers Claude Code sends with it. You can set `headers` in either of these places:
* **The marketplace's `url` source**: the `url` source you registered the marketplace from, such as an [`extraKnownMarketplaces`](/docs/en/settings-reference#extraknownmarketplaces) entry.
* **The plugin's entry**: on Claude Code v2.1.238 or later, you can set it on the plugin's `marketplace.json` entry instead, beside `source`.
In either place, set a `headersHelper` command instead of `headers` when the value is short-lived, such as a token your registry generates on request. Claude Code runs the command and sends the JSON object it prints as that place's headers. Requires Claude Code v2.1.238 or later.
The [marketplace reference](/docs/en/plugins/marketplace-reference#plugin-entries) lists the `headers` and `headersHelper` entry fields.
The place you choose decides which downloads get the headers and when Claude Code runs the command:
| Place | Downloads that get the headers | When Claude Code runs a `headersHelper` set there |
| :----------------------- | :----------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Marketplace `url` source | Archive downloads on the marketplace URL's origin, meaning the same scheme, host, and port | Before each fetch of the marketplace's `marketplace.json` and before each archive download on that origin. Claude Code reuses one run's output for up to 60 seconds |
| Plugin entry | That entry's download only | Only when a user installs or updates that one plugin by itself and [accepts the command](#how-users-accept-a-headershelper-command) |
Where both places set a header of the same name, Claude Code sends the entry's value. Within one place, a header the command prints overrides a header of the same name listed in `headers`.
### Add a headersHelper to a plugin entry
This entry sets `headersHelper` beside `source`. It also sets [`"strict": false`](/docs/en/plugins/marketplace-reference#strict-mode), which Claude Code requires of a `marketplace.json` entry that sets `headersHelper`:
```json theme={null}
{
"name": "my-plugin",
Cut at 300 lines. The page has the rest.
plugins/install New page · 376 lines, new page
# Install and manage plugins ## Install a plugin ### Choose an install scope ### Install from your shell ## Add a marketplace ### Add a marketplace and install in one command ### Add a private marketplace ## Manage installed plugins ### Manage plugins synced from claude.ai ### Uninstall a plugin the project enables ### See what an installed plugin adds to your sessions ### Find plugins you no longer use ### Plugins with dependencies ### Manage plugins from your shell ## Keep plugins updated ### Turn auto-update on or off for a marketplace ### Update one plugin now ### Auto-update from a private marketplace ## Manage marketplaces ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Install and manage plugins
> Install Claude Code plugins from a marketplace on any surface you use, choose an install scope, and update or remove them later.
Installing a plugin adds its skills, agents, hooks, and MCP servers to Claude Code on your machine.
This page is for anyone using plugins on their own machine or account, whether in the terminal, the desktop app, an IDE, or a cloud session: it covers installing, choosing a scope, adding marketplaces, and keeping plugins updated.
<Note>
These cases are covered on other pages:
* **You use claude.ai chat or Cowork, not Claude Code**: see [Plugins on claude.ai and in Cowork](https://claude.com/docs/plugins/overview)
* **Claude Code printed an error**: find it in [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
</Note>
Start with [Install a plugin](#install-a-plugin). If someone sent you an install command whose `@` name isn't `claude-plugins-official`, [add that marketplace](#add-a-marketplace) first.
## Install a plugin
As an example, this section installs [`commit-commands`](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/commit-commands) from [Anthropic's official marketplace](/docs/en/plugins/anthropic-marketplaces), which adds commands for committing, pushing, and opening pull requests.
The same steps install any other plugin: substitute its name and its marketplace's name wherever `commit-commands` and `claude-plugins-official` appear. If that plugin comes from a different marketplace, [add the marketplace](#add-a-marketplace) first.
Pick the tab for where you run Claude Code.
<Tabs>
<Tab title="Terminal">
Start Claude Code with `claude` in your project, then:
<Steps>
<Step title="Open the plugin's details with the install command">
Run `/plugin install` with the plugin's name and marketplace. In a session, this command doesn't install right away: it opens the `/plugin` panel on that plugin's details so you can review it and choose a scope first.
```text theme={null}
/plugin install commit-commands@claude-plugins-official
```
To browse instead, run `/plugin` with no plugin name: the panel opens on the **Discover** tab, which lists plugins from every marketplace you've added, and you can type to search, then press **Enter** on a plugin to open its details.
</Step>
<Step title="Review what the plugin adds">
The details pane shows the plugin's description. It can also show:
* **Will install**: the commands, agents, skills, hooks, and MCP and LSP servers the plugin adds.
* **Last updated**: shown for a plugin in Anthropic's official marketplace.
* **Context cost**: for a plugin in Anthropic's official marketplace, two token estimates. **Every turn** is what the plugin adds to each message you send, and **When invoked** is what its skills and agents add once Claude loads them. The estimates appear when you open the plugin by naming its marketplace, as the step 1 command does, or from the **Marketplaces** tab. The details pane you reach from the **Discover** list doesn't show them.
Plugins from a local or custom marketplace can show `Components will be discovered at installation` instead.
A plugin can run hooks and MCP servers, so read the pane before you install. See [Plugin security and trust](/docs/en/plugins/security).
</Step>
<Step title="Choose a scope">
Select one of the three install options:
* **Install for you (user scope)**: you get the plugin in every project on this machine
* **Install for all collaborators on this repository (project scope)**: it's enabled for everyone who works in this repository
* **Install for you, in this repo only (local scope)**: you get it in this repository only
[Choose an install scope](#choose-an-install-scope) says which settings file each one writes to and which applies when the same plugin is set at more than one.
After you select a scope, Claude Code installs the plugin along with any dependencies it declares, then prints an install summary.
</Step>
<Step title="Read the install summary">
The last sentence of the summary tells you whether the plugin is usable in this session yet:
* **Active now**: `Plugin is now active.` No reload is needed.
* **Reload needed**: `Run /reload-plugins to activate.` The panel closes and Claude Code runs that reload for you. If the reload would [invalidate the prompt cache](/docs/en/prompt-caching#enabling-or-disabling-a-plugin), it warns and leaves the plugin pending instead. Run `/reload-plugins --force` to activate it anyway, which costs one uncached request.
* **Load failed**: `The plugin couldn't be loaded`. Open the **Errors** tab in `/plugin` for the reason, then see [After install: plugin not working](/docs/en/plugins/troubleshooting#plugin-installed-but-not-working).
</Step>
<Step title="Confirm the plugin works">
Type `/` and look for the plugin's skills under its name, in the form `/<plugin>:<skill>`. For `commit-commands`, `/commit-commands:commit` appears. Two other places list the plugin too:
* Open the **Installed** tab in `/plugin`, which lists the plugin with its scope.
* In your shell, run `claude plugin list`, which prints the same list with `Version`, `Scope`, and `Status` lines.
If `/commit-commands:commit` doesn't appear, see [After install: plugin not working](/docs/en/plugins/troubleshooting#plugin-installed-but-not-working).
</Step>
</Steps>
Installing from any other marketplace requires one extra step first: [add the marketplace](#add-a-marketplace). Claude Code adds Anthropic's official marketplace for you the first time you start an interactive terminal session, which is why the example skips that step. If you found a plugin on [claude.com/marketplace](https://claude.com/marketplace), its **Claude Code** button copies the install command in its [shell form](#install-from-your-shell), `claude plugin install <name>@claude-plugins-official`.
</Tab>
<Tab title="Desktop app">
In a local or SSH session in the desktop app's **Code** tab:
<Steps>
<Step title="Open the plugin browser">
Click the **+** button next to the prompt box and select **Plugins**, then **Add plugin**. The plugin browser opens with the plugins from your marketplaces.
</Step>
<Step title="Select the plugin">
Find `commit-commands` and select it.
</Step>
<Step title="Choose a scope">
Choose a [scope](#choose-an-install-scope): your user account, this project, or local-only.
</Step>
</Steps>
To enable, disable, or uninstall later, use **+ > Plugins > Manage plugins**. The plugin browser isn't available in the desktop app's cloud sessions. See [Install plugins in the desktop app](/docs/en/desktop#install-plugins).
</Tab>
<Tab title="VS Code">
In the Claude Code panel in VS Code:
<Steps>
<Step title="Open Manage plugins">
Type `/plugins` in the prompt box to open **Manage plugins**.
</Step>
<Step title="Install the plugin">
On the **Plugins** tab, search for `commit-commands` and click **Install**. If the tab lists no plugins, add `anthropics/claude-plugins-official` on the **Marketplaces** tab first.
</Step>
<Step title="Choose a scope">
Choose a [scope](#choose-an-install-scope): **Install for you**, **Install for this project**, or **Install locally**.
</Step>
</Steps>
Your changes apply to open sessions without a restart. See [Manage plugins in VS Code](/docs/en/vs-code#manage-plugins).
</Tab>
<Tab title="Cloud session">
A [cloud session](/docs/en/cloud-environments), including [the browser at claude.ai/code](/docs/en/claude-code-on-the-web), has no plugin browser and doesn't load the plugins you installed on your own machine or the ones your repository's `.claude/settings.json` turns on. For plugins your organization distributes through managed settings, see [Manage plugins for your organization](/docs/en/plugins/org).
See [which parts of your setup are also available in a cloud session](/docs/en/cloud-environments#what-carries-over-from-your-setup) for the rest of your setup.
</Tab>
</Tabs>
### Choose an install scope
A plugin's install scope decides who gets the plugin and which settings file records it as enabled:
* **User scope**: the plugin is enabled for you in every project on this machine. The entry goes in `enabledPlugins` in `~/.claude/settings.json`.
* **Project scope**: the plugin is enabled for everyone who works in this repository. The entry goes in `.claude/settings.json`, which you commit.
* **Local scope**: the plugin is enabled for you in this repository only. The entry goes in `.claude/settings.local.json`.
Some plugins are set by their author to start turned off, through the [`defaultEnabled`](/docs/en/plugins/manifest-reference#defaultenabled) field. Such a plugin is installed but stays off until you turn it on with `claude plugin enable <name>` in your shell, or from the **Installed** tab of `/plugin` in a session.
When the same plugin is set at several scopes, the local setting overrides the project setting, and the project setting overrides the user setting. See [Find where a plugin is enabled](/docs/en/plugins/loading#find-where-a-plugin-is-enabled) for the full rule.
The terminal, the desktop app's local sessions, and the VS Code extension on one computer read the same settings files, so a plugin you install at user scope in any of them is available in the other two.
<h3 id="other-places-you-run-claude-code">
JetBrains, non-interactive runs, and the Agent SDK
</h3>
Some places you run Claude Code have no plugin browser of their own:
* **JetBrains IDEs**: the JetBrains plugin runs Claude Code in the IDE's terminal, so use the **Terminal** tab's steps there.
* **`claude -p` and other non-interactive runs**: `/plugin` doesn't run, and Claude replies `/plugin isn't available in this environment.` Plugins you already installed do load. Install and manage them from your shell with [`claude plugin` commands](#install-from-your-shell).
* **Agent SDK**: load plugins through the SDK's plugin option. See [Load plugins in the Agent SDK](/docs/en/agent-sdk/plugins).
If Claude Code reports that a plugin enabled in the repository's `.claude/settings.json` isn't installed, see [Enabled in project settings but not installed](/docs/en/plugins/loading#enabled-in-project-settings-but-not-installed).
<Tip>
If you're a plugin author testing a copy of your plugin on disk, start Claude Code from your shell with `--plugin-dir` to load it for one session instead of installing it. See [Flags that load a plugin for one session](/docs/en/plugins/cli-reference#flags-that-load-a-plugin-for-one-session).
</Tip>
<h3 id="plugins-from-your-claude-ai-account">
Plugins from your claude.ai account
</h3>
Your claude.ai account is a separate source of plugins, alongside the marketplaces you install from:
* **What arrives**: every plugin you turn on for your claude.ai account, and every plugin your organization turns on for its members. In a terminal session they sync in the background each time you start Claude Code while signed in with that account; in Cowork sessions they download when the session starts.
* **Where you see them**: in `/plugin` and `claude plugin list` under the ID `<name>@synced`. You can turn one off at your own scope unless your organization requires it.
* **What doesn't go the other way**: plugins you install with `/plugin` or `claude plugin install` stay on this machine and aren't added to your claude.ai account.
For sync timing, sign-in requirements, and turning sync off, see [Plugins synced from claude.ai](/docs/en/plugins/loading#synced-plugins).
### Install from your shell
Run `claude plugin install` in your shell to install a plugin without starting a Claude Code session, for example from a setup script.
* **Scope**: user scope by default. Pass `--scope project` or `--scope local` to change it.
* **When the plugins load**: plugins it installs load the next time you start Claude Code, or when you run `/reload-plugins` in a session that's already open.
* **The marketplace must be added first**: on a machine where no one has opened an interactive Claude Code session yet, the official marketplace isn't registered, so a script that installs from it runs `claude plugin marketplace add anthropics/claude-plugins-official` before the install.
```bash theme={null}
claude plugin install formatter@your-org --scope project
```
The command prints `Successfully installed plugin: formatter@your-org (scope: project)` when it finishes.
Some plugins install by running a command that their marketplace names, called a [`command` source](/docs/en/plugins/marketplace-reference#command-plugin-source). Claude Code shows you that command and asks you to accept it before it runs. A script has no one to answer that prompt, so pass `--yes` there to accept it.
For every `claude plugin install` flag, see [plugin install](/docs/en/plugins/cli-reference#plugin-install).
## Add a marketplace
You only need this section when the plugin you want isn't in Anthropic's official marketplace, for example one a coworker published or one from Anthropic's community marketplace.
A marketplace is a catalog of plugins, and Claude Code has to know about a marketplace before you can install from it. You add a marketplace once. After that, its plugins appear on the **Discover** tab and install with `/plugin install <plugin>@<marketplace>` in a session or `claude plugin install <plugin>@<marketplace>` in your shell, where `<marketplace>` is the name the marketplace registered under. To do both in one step, see [Add a marketplace and install in one command](#add-a-marketplace-and-install-in-one-command).
In a Claude Code session, run `/plugin marketplace add` followed by the marketplace's source: a GitHub repository, a git repository on any host, a local directory or file, or a hosted `marketplace.json`.
| Source | What you type | Example |
| :------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------- |
| GitHub repository | `owner/repo`. Add `#ref` to pin a branch or tag. | `/plugin marketplace add anthropics/claude-code`, or `/plugin marketplace add your-org/plugins#v1.2.0` to pin the `v1.2.0` tag |
| Git repository on any host | The full clone URL. Add `#ref` to pin a branch or tag. | `/plugin marketplace add https://gitlab.example.com/your-group/your-marketplace.git#v1.0.0` |
| Local directory or file | A relative or absolute path to a directory that holds `.claude-plugin/marketplace.json`, or to the JSON file itself. Start a relative path with `./` or `../`, because Claude Code reads a bare `name/name` as a GitHub repository. | `/plugin marketplace add ./my-marketplace` |
| Hosted `marketplace.json` | Its `https://` URL | `/plugin marketplace add https://example.com/marketplace.json` |
From your shell, `claude plugin marketplace add` takes the same sources.
<Tip>
`/plugin market` also works as a shorter form of `/plugin marketplace`.
</Tip>
Include the `https://` prefix on every URL, or use the `git@host:path` form for SSH. If you type a bare `gitlab.example.com/your-group/your-marketplace.git`, Claude Code reads it as GitHub `owner/repo` shorthand and rejects it.
When the command succeeds, it prints `Successfully added marketplace: <name>`, and the marketplace's plugins appear on the **Discover** tab the next time you open `/plugin`, with no reload needed. If it fails, match the error message in [Troubleshoot plugins](/docs/en/plugins/troubleshooting#add-a-marketplace).
### Add a marketplace and install in one command
To install a plugin from a marketplace you haven't added yet, run `/plugin install` in a Claude Code session and name the marketplace source with `--marketplace`. Requires Claude Code v2.1.275 or later.
```text theme={null}
/plugin install deploy-helper --marketplace your-org/plugins
```
The source takes [the same forms as `/plugin marketplace add`](#add-a-marketplace), such as GitHub `owner/repo`, a git URL, or a local path, except that it can't contain spaces. Give the plugin name by itself, without an `@marketplace` suffix.
If you haven't added that marketplace yet, Claude Code shows the source it resolved and asks you to confirm before adding it. Once the marketplace is added, the plugin's details open and you choose an [installation scope](#install-a-plugin). If the source matches a marketplace you've already added, Claude Code skips the confirmation and opens the plugin's details in that marketplace.
### Add a private marketplace
A private marketplace is one in a repository you need credentials to clone, on GitHub or any other git host. You add it with the same `/plugin marketplace add` or `claude plugin marketplace add` command as a public one. Claude Code clones it with the git credentials already on your machine and never prompts, so each way of connecting has a requirement:
* **HTTPS**: your git credential helpers apply, so access you set up with `gh auth login`, the macOS Keychain, or `git-credential-store` works. Interactive prompts are suppressed, so a host you have never authenticated to fails instead of asking for a password.
* **SSH**: the host must already be in your `known_hosts` file and the key must work without a passphrase prompt, because the host-fingerprint and passphrase prompts are suppressed too.
* **GitHub `owner/repo` shorthand**: Claude Code checks whether your SSH key authenticates to `github.com`, then clones over SSH if it does and over HTTPS if it doesn't. Set [`CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1`](/docs/en/env-vars#variables) to skip that check and always clone over HTTPS.
The same credentials apply when you run `/plugin install`, `/plugin marketplace update`, and `claude plugin update`.
On a GitHub Enterprise Server host, see [Plugin marketplaces on GHES](/docs/en/github-enterprise-server#plugin-marketplaces-on-ghes) for the credentials each operation needs.
If your organization registers the marketplace for you through managed settings, you don't add it yourself. See [Pre-install and require plugins](/docs/en/plugins/org#pre-install-and-require-plugins).
<h3 id="add-from-claude-ai">
Add a marketplace from claude.ai
</h3>
In terminal sessions where [plugins sync from your claude.ai account](/docs/en/plugins/loading#synced-plugins), claude.ai can also list plugin marketplaces for you, such as your organization's plugin library and your own claude.ai uploads. You add one of these by its name rather than by a source. Adding a marketplace from claude.ai requires Claude Code v2.1.273 or later.
Add a claude.ai marketplace from the `/plugin` panel or from your shell:
* **Inside a session**: run `/plugin` and go to the **Marketplaces** tab, which lists the marketplaces from claude.ai. Select one there to add it.
* **From your shell**: run `claude plugin marketplace list`, which prints them in a `From claude.ai:` section. Then run `claude plugin marketplace add` with the `--claudeai` flag and the name shown in the list.
For example, this command adds a marketplace named `claudeai-organization-library`:
```bash theme={null}
claude plugin marketplace add --claudeai claudeai-organization-library
```
Claude Code registers the marketplace under a local name that starts with `claudeai-`, derived from the name that claude.ai lists it under. For example, a marketplace listed as "Organization library" becomes `claudeai-organization-library`. Install its plugins by that name, for example with `claude plugin install <plugin>@claudeai-organization-library`.
If you sign out, or sign in to a different claude.ai organization, the marketplace stays configured but shows no plugins, and the plugins you already installed from it keep loading.
The `From claude.ai:` section can also list git-based marketplaces shared through claude.ai, and it prints a source for each of those. Add them by that source as in [Add a marketplace](#add-a-marketplace), not with `--claudeai`.
## Manage installed plugins
The **Installed** tab in `/plugin` lists your plugins with actions to enable, disable, update, or uninstall each one. In a Claude Code session, run `/plugin` and press **Tab** to reach it, or run `/plugin enable`, `/plugin disable`, or `/plugin uninstall` to open the panel and make that change there. Disabled plugins are grouped under a collapsed header at the bottom of the list. Use these keys on the list:
* Type to filter by name or description.
* Press **Space** to enable or disable the selected plugin, and **f** to favorite it.
* Press **Enter** to open a plugin's details. The menu there offers **Disable plugin** or **Enable plugin**, **Update now**, and **Uninstall**. Plugins that take settings also offer **Configure options**.
The tab can also show plugins at **Managed** scope. Your organization installed those through [managed settings](/docs/en/settings#settings-files), and you can't enable, disable, or uninstall them here.
For a synced plugin that your organization requires on claude.ai, see [Manage plugins synced from claude.ai](#manage-plugins-synced-from-claude-ai).
When you close the `/plugin` panel with pending changes you made in it, Claude Code runs `/reload-plugins` for you to apply them. If the reload would [invalidate the prompt cache](/docs/en/prompt-caching#enabling-or-disabling-a-plugin), it warns and leaves the changes pending instead. Run `/reload-plugins --force` to apply them anyway.
### Manage plugins synced from claude.ai
The **Installed** tab in `/plugin` also lists the [plugins synced from your claude.ai account](/docs/en/plugins/loading#synced-plugins), with `synced` as their source. Synced plugins appear in terminal sessions on Claude Code v2.1.273 or later.
* **Enable or disable**: use the **Installed** tab, unless your organization marked the plugin as required.
* **Remove**: turn the plugin off on claude.ai.
When Claude Code syncs an added, updated, or removed plugin into an interactive session, you see `Plugins changed. Run /reload-plugins to activate.` Run `/reload-plugins` to load the change in that session, or leave it for the next time you start Claude Code.
### Uninstall a plugin the project enables
When you choose **Uninstall** for a plugin that this repository's `.claude/settings.json` enables, whether from the **Installed** tab or with `/plugin uninstall`, Claude Code asks whether to disable it for you or uninstall it for everyone:
* **Disable for me**: press **y**. Claude Code writes `false` for the plugin in your `.claude/settings.local.json` and leaves it installed for the project.
* **Uninstall for everyone**: press **u**. Claude Code removes the plugin from the shared `.claude/settings.json`.
### See what an installed plugin adds to your sessions
In your shell, run `claude plugin details <name>` for an installed plugin. The `Always-on` line is the number of tokens the plugin adds to every session where it's enabled, and the per-component rows show which skill or agent contributes most. For the full output and what each figure means, see [Measure what a plugin costs](/docs/en/plugins/measure#measure-what-a-plugin-costs).
Cut at 300 lines. The page has the rest.
plugins/loading New page · 364 lines, new page
# Plugin loading reference ## Check which stage a plugin reached ### Plugins and marketplaces that aren't on disk at session start ## Find where a plugin came from ### Entry name and manifest name ### Plugins shared through a repository #### Sync timing in terminal sessions #### Sign-in requirements for terminal sync #### Control which synced plugins load ## Find where a plugin is enabled ### Disabled in user settings but still loads ### Enabled in project settings but not installed ## Find plugins on disk ### In-place and copied plugins ### Paths that escape the plugin directory ### Cleanup of previous versions ### Node.js package dependencies #### When the dependency install runs #### Limits on the dependency install #### When the dependency install fails or is skipped ## Versions and updates ### How Claude Code computes the version ### When Claude Code refreshes a marketplace before an install ### When auto-update runs #### Which marketplaces and plugins auto-update ### When a command source re-runs ## Name conflicts ### Keep a session-only plugin from loading ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Plugin loading reference
> Trace where Claude Code loads each plugin from, which settings file decides whether it loads, and why an update changed nothing.
Use this page when a plugin didn't load, loaded a different copy than you expected, or didn't pick up an update, and you want to see which source, settings scope, or file on disk decided that. It gives the rules Claude Code applies when a session starts and each time you run `/reload-plugins`. You can also ask Claude to read this page and diagnose your setup.
<Note>
These cases are covered on other pages:
* **Install, enable, disable, and update steps**: see [Install and manage plugins](/docs/en/plugins/install)
* **You have a specific error message**: see [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
</Note>
Start with [Check which stage a plugin reached](#check-which-stage-a-plugin-reached) for the three stages an installed plugin passes through, or go to the section that matches what you're seeing:
* A plugin you turned off still loads: [Find where a plugin is enabled](#find-where-a-plugin-is-enabled)
* An update changed nothing: [Versions and updates](#versions-and-updates)
* You're looking at the files under `~/.claude/plugins/`: [Find plugins on disk](#find-plugins-on-disk)
* A `--plugin-dir` plugin didn't load, or a same-named plugin loaded instead: [Name conflicts](#name-conflicts)
## Check which stage a plugin reached
An `enabledPlugins` entry becomes a plugin you can use in stages: your settings declare it, Claude Code fetches it to disk, and the running session loads it. When a plugin doesn't behave as a settings file suggests, check which stage it reached:
* **Declared, in settings**: `enabledPlugins` says which plugins should be on, and `extraKnownMarketplaces` says which marketplaces should exist. When you run `claude plugin marketplace add`, Claude Code writes the marketplace to `extraKnownMarketplaces` in your user settings as well as to disk
* **Fetched, on disk under `~/.claude/plugins/`**: the records of what Claude Code has fetched, and the fetched files themselves:
* `known_marketplaces.json` records each marketplace Claude Code has fetched, with its `source`, `installLocation`, `lastUpdated`, and `autoUpdate`. There is one `known_marketplaces.json` per user, so a marketplace you add in one project is available in every project
* `installed_plugins.json` records each install with its `scope`, `installPath`, and `version`
* `cache/` holds the plugin files
* **Loaded, in the running session**: the plugin set Claude Code loaded at startup or at the last `/reload-plugins`. Changes to settings or to disk don't reach this layer until you run `/reload-plugins` or start a new session. That is why `claude plugin update` ends with `Restart to apply changes.` and background updates prompt you with `Run /reload-plugins to apply`
### Plugins and marketplaces that aren't on disk at session start
Plugins load at session start from `installed_plugins.json` and the cache without using the network. After the session starts, Claude Code checks the declared marketplaces in the background:
* **A marketplace that settings declare but `known_marketplaces.json` lacks**: Claude Code clones it, then reloads plugins and downloads enabled plugins that aren't cached yet
* **A declared marketplace whose source changed in settings**: Claude Code re-fetches it from the new source and shows `Plugins changed. Run /reload-plugins to activate.`
An enabled plugin that neither path fetched and that has no usable cache directory shows `Plugin "<name>" not cached at <path>` in the `/plugin` **Errors** tab, and `claude plugin list` adds `— run /plugin to refresh` to the same line. For the fix, see [`Plugin "<name>" not cached at <path>`](/docs/en/plugins/troubleshooting#plugin-not-cached-at).
## Find where a plugin came from
Every plugin has an id of the form `<name>@<origin>`, which is what you see in settings files and in `claude plugin list --json`. The part after `@` tells you where Claude Code found the plugin:
| ID ends in | How the plugin got there | How you turn it on or off |
| :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `@<marketplace>` | You installed it from a marketplace you added | `"<name>@<marketplace>": true` or `false` under `enabledPlugins` in a settings file |
| `@inline` | You started Claude Code with `--plugin-dir` or `--plugin-url`, set [`CLAUDE_CODE_PLUGIN_DIRS`](/docs/en/env-vars#variables), or an Agent SDK app passed the `plugins` option. It loads for that session only | On for the session unless the manifest sets `defaultEnabled: false` or a settings file sets `"<name>@inline": false` |
| `@skills-dir` | You saved a plugin directory that has a `.claude-plugin/plugin.json` under `~/.claude/skills/` or the project's `.claude/skills/` | The manifest's `defaultEnabled`, unless a settings file sets `"<name>@skills-dir"` to `true` or `false` |
| `@synced` | You or your organization turned it on for your claude.ai account, and Claude Code [downloaded it](#synced-plugins) | On unless the manifest sets `defaultEnabled: false` or a settings file sets `"<name>@synced": false`. A plugin your organization marks as required loads regardless |
For a marketplace plugin, `<name>` is the entry name in `marketplace.json`; for `@inline` and `@skills-dir` it's the `name` in the plugin's manifest.
The origin names in this table are reserved, so no marketplace can be named `inline`, `skills-dir`, or `synced`.
### Entry name and manifest name
A marketplace plugin has two names, and they can differ:
* **The entry name in `marketplace.json`**: the install and enable key. It's what you write in `enabledPlugins`, what the cache directory is named after, and what `claude plugin list` shows
* **The `name` in the manifest**: what the plugin's components are namespaced under, and what [name conflicts](#name-conflicts) compare
### Plugins shared through a repository
To share a plugin through a repository, list it under `enabledPlugins` in `.claude/settings.json` or place it under `.claude/skills/`. Claude Code doesn't scan a project's `.claude/plugins/` directory.
A cloud session doesn't add the marketplaces a repository lists under [`extraKnownMarketplaces`](/docs/en/settings-reference#extraknownmarketplaces), because that requires the workspace trust dialog, which a cloud session never shows.
A project-scope skills-directory plugin loads only from the `.claude/skills/` of the session's [primary working directory](/docs/en/permissions#working-directories), and only after you accept the [workspace trust dialog](/docs/en/permissions#what-runs-before-you-trust-a-folder) for that folder. It doesn't [search parent directories up to the repository root](/docs/en/skills#discovery-from-parent-and-nested-directories) the way plain skills and commands do. If you launch from a subdirectory, a plugin at the repository root doesn't load. Launch from the repository root instead, or [move the session there with `/cd`](/docs/en/permissions#move-the-session-to-another-directory) on v2.1.246 or later.
A project-scope plugin is checked into the repository and reaches every collaborator who clones it. Because that content comes from the repository rather than from you, it loads only after the same trust check that applies to project allow rules in `.claude/settings.json`. Trusting a parent folder or running with `-p` isn't enough. Components that run code are restricted further:
* MCP servers it declares go through the [same per-server approval](/docs/en/mcp) as a project `.mcp.json`
* MCP servers it declares as an [MCP bundle](/docs/en/plugins/manifest-reference#mcpservers), a `.mcpb` or `.dxt` file, or from a file outside the plugin directory are skipped. Declare them inline or in a `.mcp.json` inside the plugin directory
* [Background monitors](/docs/en/plugins/components#monitors) do not load
Personal-scope plugins have none of these restrictions.
For how to write `--plugin-dir` and skills-directory plugins, see [Create plugins](/docs/en/plugins/create).
<h3 id="synced-plugins">
Plugins synced from claude.ai
</h3>
A plugin you turn on for your claude.ai account also loads in Claude Code, alongside the plugins you install from marketplaces. That includes plugins your organization turns on for its members. Each of these plugins loads as `<name>@synced`, with no marketplace and no [install record](#check-which-stage-a-plugin-reached).
In terminal sessions, a synced plugin's skills, agents, hooks, MCP servers, and LSP servers all load, with the same trust as a marketplace plugin you installed.
For the components Cowork loads, see [Plugins on claude.ai and in Cowork](https://claude.com/docs/plugins/overview) on claude.com.
Synced plugins load in Cowork sessions and in terminal sessions where you sign in with your claude.ai account:
* **[Cowork](https://claude.com/product/cowork)**: Claude Code downloads them into the session's own environment when the session starts
* **Terminal sessions**: each time you start Claude Code, it syncs once in the background, downloading new and updated plugins and removing the ones that you or your organization turned off. Syncing in terminal sessions requires Claude Code v2.1.273 or later
#### Sync timing in terminal sessions
Because the terminal sync runs in the background, it can finish after your session has started. When it adds, updates, or removes a synced plugin in an interactive session, you see `Plugins changed. Run /reload-plugins to activate.` Run `/reload-plugins` to load the change in that session, or leave it for the next time you start Claude Code.
If you enable a plugin on claude.ai while a session is running, the plugin downloads the next time you start Claude Code.
#### Sign-in requirements for terminal sync
In your terminal, plugins sync only in sessions where you sign in with your claude.ai account.
If you signed in on an earlier version of Claude Code, that sign-in doesn't cover plugins until Claude Code renews it in the background. To get access sooner, run `/login` again. Plugin sync then starts the next time you start Claude Code.
#### Control which synced plugins load
You can turn synced plugins off one at a time, except a plugin your organization requires, or turn off every synced plugin on the machine:
* **One plugin**: `claude plugin disable <name>@synced` in your shell and the `/plugin` **Installed** tab in a session both save `"<name>@synced": false` in your user-level [`enabledPlugins`](/docs/en/settings-reference#enabledplugins). To keep the plugin out of a project in every environment, set the same key in the project's committed `.claude/settings.json`
* **Every synced plugin on a machine**: set [`syncClaudeAiPlugins`](/docs/en/settings-reference#syncclaudeaiplugins) to `false` in your user settings, or your organization sets it in [managed settings](/docs/en/managed-settings). Claude Code stops downloading, and the next time you start it, it moves the plugins it already synced to `~/.claude/plugins/.trash/` and no longer loads them. If your organization turns off Skills on claude.ai, plugins stop syncing too
* **A plugin your organization requires**: a plugin that your organization marks as required on claude.ai loads even if you disabled it earlier. `claude plugin disable` refuses it with `Plugin "<name>@synced" is required by your organization and can't be disabled here. Contact your admin to change it.`, and `claude plugin list` marks it `required by your org`
For removing a plugin on claude.ai, see [Manage installed plugins](/docs/en/plugins/install#manage-installed-plugins).
## Find where a plugin is enabled
You can set an `enabledPlugins` entry in any of six sources. The table lists them from lowest precedence to highest, and who each one applies to. For the settings files themselves, see [Settings files and who they affect](/docs/en/settings#where-settings-live).
| Source | Where you set it | Reaches |
| :---------- | :------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------- |
| `--add-dir` | `.claude/settings.json` or `.claude/settings.local.json` in a directory you pass with `--add-dir` | This session only. Only a `true` value has an effect, and every other source overrides it |
| `user` | `~/.claude/settings.json` | You, in every project |
| `project` | `.claude/settings.json` | Everyone who clones the repository |
| `local` | `.claude/settings.local.json` | You, in this repository only |
| `flag` | The `--settings` value you pass at launch | This session only |
| `managed` | [Managed settings](/docs/en/managed-settings) | Every user the policy covers. `true` force-enables and `false` blocks, and no other source overrides them |
These sources merge key by key. For each plugin id, the value that applies is the one from the highest-precedence source that mentions the id. A source that doesn't mention the id leaves the value from the lower-precedence source in effect.
### Disabled in user settings but still loads
If you set a plugin to `false` in `~/.claude/settings.json` and it still loads, a `true` in a higher-precedence source is overriding it. The plugin's row in `claude plugin list` and in `/plugin` shows `Disabled in ~/.claude/settings.json but still loads — project settings enable it, which overrides your user setting`. The message names the source that overrode you: `project`, `project, gitignored` for `.claude/settings.local.json`, `cli flag`, or `managed`.
To opt out of a project-enabled plugin on your machine, set the id to `false` in `.claude/settings.local.json`, which has higher precedence than the project file.
### Enabled in project settings but not installed
When a plugin's only `true` is in the project's `.claude/settings.json`, Claude Code doesn't fetch it onto a machine where it isn't installed, unless its marketplace entry has a [relative-path source](/docs/en/plugins/marketplace-reference#plugin-sources) or a [seed directory](/docs/en/plugins/org#seed-containers-and-ci) already holds it. Instead, the `/plugin` **Errors** tab shows `Plugin "<name>" is enabled in project settings but isn't installed here`.
A relative-path plugin needs no install record because it loads from the marketplace itself.
Claude Code fetches a plugin with an external source only when one of these sources sets it to `true`:
* Your user settings
* A `.claude/settings.local.json` that git doesn't track
* The `--settings` flag
* Managed settings
## Find plugins on disk
Claude Code keeps plugin files and state records under one plugins root, which is `~/.claude/plugins` unless you set [`CLAUDE_CODE_PLUGIN_CACHE_DIR`](/docs/en/env-vars). Every path in the table is relative to that root.
| Path | What it holds |
| :----------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cache/<marketplace>/<plugin>/<version>/` | One directory per installed version of a marketplace plugin. `<plugin>` is the marketplace entry name and `<version>` is the [resolved version](#versions-and-updates). `${CLAUDE_PLUGIN_ROOT}` points at this directory |
| `data/<plugin-id>/` | The plugin's persistent directory, exposed as `${CLAUDE_PLUGIN_DATA}`. For how `<plugin-id>` is formed, see [Path variables and persistent data](/docs/en/plugins/components#path-variables-and-persistent-data). Claude Code creates it when a plugin component first uses it and keeps it across updates. Claude Code deletes it when you uninstall the plugin from its last scope, unless you pass `--keep-data` |
| `marketplaces/<name>/` | The clone or download of a marketplace added from GitHub, another Git host, or a URL. A marketplace added from a local `file` or `directory` source has no copy here, and its `installLocation` in `known_marketplaces.json` is the path you gave |
| `synced/` | The plugins Claude Code [synced from your claude.ai account](#synced-plugins) |
| `.trash/` | Plugins that the claude.ai sync removed, such as after you turn one off on claude.ai or stop syncing |
| `installed_plugins.json` and `known_marketplaces.json` | The records of what Claude Code has installed and which marketplaces it has fetched, described under [Check which stage a plugin reached](#check-which-stage-a-plugin-reached). A [marketplace hosted on claude.ai](/docs/en/plugins/install#add-from-claude-ai) is recorded in `known_marketplaces_claudeai.json` instead |
| `flagged-plugins.json` | Plugins Claude Code uninstalled because their marketplace delisted them. They appear in the **Flagged** section of `/plugin`; see [Host a marketplace](/docs/en/plugins/host-marketplace) |
Because `${CLAUDE_PLUGIN_ROOT}` points at a version directory, a plugin's root path changes with every version. Keep a plugin's durable files in `${CLAUDE_PLUGIN_DATA}` instead.
### In-place and copied plugins
Claude Code loads some plugins in place from where you keep them and copies the rest into the cache, according to their origin:
* **`--plugin-dir` and skills-directory plugins**: the directory loads in place and is never copied. A `--plugin-url` archive or a `--plugin-dir` `.zip` is extracted into a session temp directory first
* **Relative-path plugins in a marketplace you added from a local directory**: the plugin loads in place from its path inside the marketplace folder. Your edits to the source directory take effect at the next session start or `/reload-plugins`, and you don't need to increase the version. The plugin's hook processes and MCP and LSP servers receive a `CLAUDE_PLUGIN_ROOT` that points at the source directory. For its Node.js package dependencies, see [When the dependency install runs](#when-the-dependency-install-runs)
* **`command`-source plugins in [link mode](/docs/en/plugins/marketplace-reference#command-plugin-source)**: the directory the command printed loads in place, through links in the cache entry
* **Every other marketplace plugin**: Claude Code copies the plugin into `cache/<marketplace>/<plugin>/<version>/` at install and loads that copy. Files outside the plugin directory aren't copied, so when a script inside a copied plugin reads a path above the plugin root, such as `../shared`, it doesn't find them
### Paths that escape the plugin directory
Whether a plugin loads in place or from a cached copy, Claude Code doesn't let it declare components outside its own directory. It rejects a component path that resolves outside the plugin root, whether the path is declared in `plugin.json` or in a marketplace entry:
* **A path that points outside the plugin as written**, such as `../shared-utils`
* **A symlink that leads outside the plugin**, other than [links between plugins within one marketplace](/docs/en/plugins/host-marketplace#share-files-within-a-marketplace-with-symlinks)
* **On macOS and Linux, a path that contains a backslash anywhere in it**, even when the path stays inside the plugin. Components declared with backslash paths therefore load on Windows only, so write component paths with forward slashes, such as `./commands/deploy.md`
A rejected path appears as a [`path escapes plugin directory`](/docs/en/errors#path-escapes-plugin-directory) error, and the plugin loads without that component.
### Cleanup of previous versions
When you update or uninstall a plugin, Claude Code writes an `.orphaned_at` marker into the previous version directory. It removes that directory in a background cleanup 14 days later, so a session that already loaded the old version keeps running.
The sweep runs only while `installed_plugins.json` records at least one install. After you uninstall your last plugin, orphaned directories stay until you install another.
### Node.js package dependencies
When Claude Code copies a plugin into the cache, it also installs the plugin's Node.js package dependencies there, so the plugin's hooks and MCP servers can load them.
This section covers the npm and Bun packages a plugin declares in its own `package.json`. For plugins that depend on other plugins, see [plugin dependency versions](/docs/en/plugins/dependencies).
#### When the dependency install runs
Claude Code runs the install inside the copied version directory each time it creates one:
* When you install a plugin
* When Claude Code updates a plugin to a new version
* At session start when an enabled plugin isn't cached yet, such as on a new machine
For a relative-path plugin [loaded in place](#in-place-and-copied-plugins) from a local-directory marketplace, Claude Code doesn't install the dependencies into the source directory. Install them there yourself, or from a hook into [`${CLAUDE_PLUGIN_DATA}`](/docs/en/plugins/components#path-variables-and-persistent-data).
The install runs only when the plugin's root directory contains both a `package.json` and a supported lockfile. The lockfile decides which command Claude Code runs:
| Lockfile | Command |
| :------------------------------------------- | :----------------------------------------------- |
| `bun.lock` or `bun.lockb` | `bun install --frozen-lockfile --ignore-scripts` |
| `npm-shrinkwrap.json` or `package-lock.json` | `npm ci --ignore-scripts` |
If a plugin contains more than one of these lockfiles, Claude Code uses the first match, checking in order: `bun.lock`, `bun.lockb`, `npm-shrinkwrap.json`, `package-lock.json`.
Claude Code skips the install for Yarn and pnpm lockfiles and for a `bunfig.toml` beside the Bun lockfile:
* If your plugin has only a `yarn.lock` or `pnpm-lock.yaml`, replace it with an npm lockfile
* If a `bunfig.toml` is in the same directory as the Bun lockfile, remove the `bunfig.toml`, or replace the Bun lockfile with an npm lockfile
Include an npm lockfile to reach the most users. Claude Code runs the matched lockfile's package manager from the user's PATH and doesn't try the other lockfile instead if that package manager is missing.
For a plugin distributed through an npm source, use `npm-shrinkwrap.json`, because npm excludes `package-lock.json` from published packages.
#### Limits on the dependency install
Claude Code constrains this dependency install so that no code from the plugin or its packages executes during it, and bounds how long it can run:
* **Frozen resolution**: Bun and npm install exactly what the lockfile pins, and fail rather than re-resolve versions when `package.json` and the lockfile disagree
* **No lifecycle scripts**: `--ignore-scripts` keeps `preinstall`, `install`, and `postinstall` scripts from running, so dependencies that build native modules in those scripts download but don't compile during this install
* **60-second timeout**: Claude Code stops an install that runs longer and treats it as failed
Claude Code fetches an npm-source plugin before this dependency install, and none of the package's own install scripts run during the fetch. See [npm plugin source](/docs/en/plugins/marketplace-reference#npm-plugin-source).
You can't turn the automatic install off. No setting or environment variable disables it.
In restricted networks, see the [network access requirements](/docs/en/network-config#network-access-requirements) for the hosts to allow.
#### When the dependency install fails or is skipped
A failed or skipped install never blocks the plugin, and each case leaves a different sign:
* A failed install, or one skipped because of a Yarn or pnpm lockfile or a `bunfig.toml`, appears as a warning in the `claude --debug` output
* A plugin with a `package.json` and no lockfile is skipped without a log entry
* A timed-out install can leave a partial `node_modules` tree in the cached copy
When the automatic install can't provide a dependency, install it from a hook into the [persistent data directory](/docs/en/plugins/components#path-variables-and-persistent-data). That includes packages that need their lifecycle scripts to build, Python dependencies, and plugins locked with Yarn or pnpm.
## Versions and updates
If a plugin's author pushed new commits and `claude plugin update` prints `<name> is already at the latest version (<version>).`, the version Claude Code computes for the plugin is unchanged, so nothing changes on disk.
Claude Code computes a version for every plugin it installs, and that version is how it detects an update. `claude plugin update` and background auto-update compute the version again and skip the plugin when it matches what `installed_plugins.json` records.
The version also names the plugin's cache directory.
A manifest that pins `"version"` is one way the computed version stays the same across commits. See [How Claude Code computes the version](#how-claude-code-computes-the-version) for the resolution order.
A plugin [loaded in place](#in-place-and-copied-plugins) from a local-directory marketplace loads its current source files at every session start, whatever its version string says. For a plugin from a [marketplace hosted on claude.ai](/docs/en/plugins/install#add-from-claude-ai), the version claude.ai records for the plugin is its version, and the manifest's `version` isn't read.
### How Claude Code computes the version
For a marketplace you added by source, Claude Code picks the rule by the `source` type of the plugin's marketplace entry. The [marketplace reference](/docs/en/plugins/marketplace-reference#plugin-sources) lists the source types. For every source type in that list except `command`:
1. The `version` field in the plugin's manifest comes first
2. Then the `version` field in the plugin's marketplace entry
3. When neither is set, the version comes from the source type:
| Source type | Version when no `version` field is set |
| :----------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- |
| `github`, `url`, or `git-subdir` | The commit SHA of the source, shortened to 12 characters. A `git-subdir` version also carries a hash of the subdirectory path |
| `archive` | The SHA-256 digest, shortened to 12 characters: the `sha256` pin in the marketplace entry, or the digest of the downloaded file when there is no pin |
| Relative path inside a Git-hosted marketplace | The commit SHA of the installed directory |
| Local directory, when neither the plugin directory nor its marketplace is a git repository | `unknown` |
| `npm` | `unknown` |
Claude Code doesn't take the version from a repository that encloses the install path, such as a git-managed `~/.claude`.
For a `command` source, Claude Code always derives the version from what the command produced: a 12-character hash on its own, or `<manifest version>-<hash>` when the manifest sets one. The marketplace entry's `version` is ignored for command sources. For what the hash covers, see [Copy mode and link mode](/docs/en/plugins/marketplace-reference#copy-mode-and-link-mode).
Because the manifest comes first, a manifest that pins `"version": "1.0.0"` keeps every user on the cached copy until its author changes the string, however many commits they push. To let users track commits instead, leave `version` out of both the manifest and the entry. [Host a marketplace](/docs/en/plugins/host-marketplace) covers which choice fits which release setup.
### When Claude Code refreshes a marketplace before an install
When you install a plugin, Claude Code looks it up in its local copy of the marketplace catalog. You can run `/plugin install` in a session or `claude plugin install` in your shell, and name the plugin with or without its marketplace. The table shows which of those combinations refresh the local copy.
| Plugin name | Command | What Claude Code refreshes |
| :----------------- | :------------------------------------------- | :--------------------------------------------------------------------------- |
| `name@marketplace` | `/plugin install` or `claude plugin install` | The named marketplace, before the lookup |
| `name` alone | `/plugin install` | Only marketplaces that have auto-update on, and only after the lookup misses |
| `name` alone | `claude plugin install` | Nothing. It reads the cached catalogs without refreshing |
The refresh before a `name@marketplace` install doesn't depend on the marketplace's auto-update setting or on `DISABLE_AUTOUPDATER`.
When the refresh fails, the install proceeds from the cached catalog and `claude plugin install` reports `marketplace not refreshed`.
Claude Code skips the refresh before a `name@marketplace` install when:
Cut at 300 lines. The page has the rest.
plugins/manifest-reference New page · 636 lines, new page
# Plugin manifest reference ## Manifest file ### Unrecognized fields ### Validate the manifest ## Fields ### `name` ### `displayName` ### `version` ### `metadata` ### `defaultEnabled` ### `dependencies` ### `settings` ## Component path forms ### Path-only fields ### `commands` ### `hooks` ### `mcpServers` ### `lspServers` ### `monitors` ## Path rules ### Containment and existence ### How each key combines with its default location ## User configuration ### Limit a field to fixed options ### Where values are stored ### Reference a saved value ### Fields that run through a shell ## Channels ## Environment variables ### Where each variable resolves ### Quoting and path separators ## Standard layout ## Marketplace entries and the manifest ### How entry fields combine with `plugin.json` ### Metadata precedence ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Plugin manifest reference
> Complete reference for plugin.json: every field with its type and default, accepted path forms, and the userConfig and environment variable schemas.
A plugin manifest is the `plugin.json` file in a plugin's `.claude-plugin/` directory. It carries the plugin's metadata and the [`userConfig`](#user-configuration) values that Claude Code prompts the user for. It also declares any component that you define inline or keep outside its [default location](#standard-layout).
This reference is for plugin creators, and for marketplace owners who put component fields in a marketplace entry.
<Note>
These cases are covered on other pages:
* **Learning to build a plugin**: start with [Create a plugin](/docs/en/plugins/create)
* **What each component does at runtime**: see [Plugin components](/docs/en/plugins/components)
</Note>
Start at the section that matches what you're looking up:
* A field: the [Fields table](#fields) gives each field's type, whether it's required, its default, and what it accepts. [Path rules](#path-rules) covers the `./` prefix and containment for every component path
* A `userConfig` option or a `channels` entry: the [User configuration](#user-configuration) and [Channels](#channels) schemas
* `${CLAUDE_PLUGIN_ROOT}` or another variable a plugin can reference: [Environment variables](#environment-variables)
* Where each component's files go: [Standard layout](#standard-layout)
* A message from `claude plugin validate`: the [troubleshooting page](/docs/en/plugins/troubleshooting) lists each message with its fix and links to the relevant sections on this page
## Manifest file
The manifest is optional. Without it, Claude Code loads the components it finds in the [standard layout](#standard-layout). The plugin name then comes from the marketplace entry, or from the directory name when you load the plugin with `--plugin-dir`.
Write a manifest when you want metadata, a component outside its default directory, `userConfig`, or an inline component definition.
Save the manifest at `.claude-plugin/plugin.json` under the plugin root. Put every other plugin file at the plugin root, not inside `.claude-plugin/`. That includes `skills/`, `commands/`, and `hooks/`.
The following example sets most of the keys in the [Fields table](#fields). It passes validation in a plugin directory that contains each referenced path.
```json theme={null}
{
"name": "deploy-tools",
"displayName": "Deploy Tools",
"version": "1.2.0",
"description": "Deployment commands, a review agent, and a status monitor",
"author": {
"name": "Example Team",
"email": "[email protected]",
"url": "https://example.com"
},
"homepage": "https://example.com/docs/deploy-tools",
"repository": "https://github.com/example/deploy-tools",
"license": "MIT",
"keywords": ["deployment", "ci"],
"defaultEnabled": true,
"dependencies": ["secrets-vault"],
"metadata": { "catalogId": "cat-123" },
"skills": ["./extra-skills/"],
"commands": {
"status": {
"source": "./commands/status.md",
"description": "Show the current deployment status"
},
"about": {
"content": "Explain what the deploy-tools plugin provides.",
"description": "Describe this plugin"
}
},
"agents": ["./agents/reviewer.md"],
"hooks": "./config/extra-hooks.json",
"mcpServers": {
"deploy-api": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/server.js"]
}
},
"lspServers": "./.lsp.json",
"outputStyles": "./styles/",
"experimental": {
"themes": "./themes/",
"monitors": "./config/monitors.json"
},
"userConfig": {
"api_token": {
"type": "string",
"title": "API token",
"description": "Token for the deployment API",
"sensitive": true
}
}
}
```
### Unrecognized fields
An unrecognized top-level key is stripped, and an unrecognized key inside a `userConfig` option, `channels` entry, `lspServers` config, or `monitors` entry is rejected:
* **Top-level fields**: the field is stripped and the plugin loads. `claude plugin validate` reports each unrecognized top-level field as a warning
* **Strict objects**: `userConfig` options, `channels` entries, `lspServers` configs, and `monitors` entries are strict. An unknown key inside one is an error, and the plugin doesn't load
### Validate the manifest
`claude plugin validate` is the authoritative check for a manifest. Run it from your shell against the plugin directory:
```bash theme={null}
claude plugin validate ./my-plugin
```
The command reports one of these results:
* **`Validation passed`**: the manifest loads
* **`Validation passed with warnings`**: the manifest loads, but the validator found something to fix, such as an unknown top-level field that Claude Code strips, a `name` that isn't kebab-case, or a missing `version`, `description`, or `author`. Pass `--strict` to turn warnings into failures in CI
* **`Validation failed`**: the manifest has a type mismatch, a path that is missing or escapes the plugin root, or an unknown key inside a `userConfig` option, `channels` entry, `lspServers` config, or `monitors` entry. Claude Code reports the same problem when it loads the plugin
## Fields
The table lists the top-level keys in `plugin.json`. `name` is the only required key. Where a field name is a link, the linked section has its full rules.
For component keys such as `commands` and `hooks`, [Component path forms](#component-path-forms) shows each accepted shape with an example, and every path follows the [path rules](#path-rules) for the `./` prefix, extensions, and containment.
| Field | Type | Description |
| :----------------------------------- | :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `$schema` | String | JSON Schema URL for editor autocomplete. Claude Code ignores it at load time |
| [`name`](#name) | String | Plugin identifier, required. Use kebab-case. Every component is namespaced under it |
| [`displayName`](#displayname) | String | Name shown in UI in place of `name` |
| [`version`](#version) | String | Version string. Setting it keeps users on that version until you change it |
| `description` | String | Short explanation of what the plugin provides |
| `author` | Object | `name`, which is required, plus optional `email` and `url` |
| `homepage` | String | Documentation URL. Must parse as a URL, or the plugin fails to load |
| `repository` | String | Source repository URL. Not validated |
| `license` | String | SPDX identifier such as `MIT` or `Apache-2.0` |
| `keywords` | Array of strings | Discovery tags |
| [`metadata`](#metadata) | Object | Free-form object for your own data. Claude Code doesn't read it |
| [`defaultEnabled`](#defaultenabled) | Boolean | Whether the plugin starts enabled when the user hasn't set it. Defaults to `true` |
| [`dependencies`](#dependencies) | Array of strings or objects | Plugins that must be enabled for this one to work |
| [`settings`](#settings) | Object | Settings Claude Code applies while the plugin is enabled. Only `agent` and `subagentStatusLine` take effect |
| [`userConfig`](#user-configuration) | Object | Values Claude Code prompts the user for when the plugin is enabled |
| [`channels`](#channels) | Array of objects | Message channels the plugin provides, each bound to one of its MCP servers |
| `skills` | Path, or array of paths | Directories to scan for skills, each a directory of `<name>/SKILL.md` folders or one folder holding `SKILL.md` directly. `"."` names the plugin root. Adds to the default `skills/` scan |
| [`commands`](#commands) | Path, array of paths, or object | Flat `.md` command files, directories of them, or an object map of command name to `source` or `content`. Replaces the default `commands/` scan |
| `agents` | Path, or array of paths | Agent `.md` files. Directories aren't accepted. Replaces the default `agents/` scan |
| [`hooks`](#hooks) | Path, object, or array of either | `.json` hook files or inline hook config. Loaded together with `hooks/hooks.json` |
| [`mcpServers`](#mcpservers) | Path, object, or array of either | `.json` MCP config files, `.mcpb` or `.dxt` bundles, or inline server configs keyed by name. Loaded together with `.mcp.json`; a server name declared later replaces an earlier one |
| [`lspServers`](#lspservers) | Path, object, or array of either | `.json` LSP config files or inline server configs keyed by name. Loaded together with `.lsp.json` |
| `outputStyles` | Path, or array of paths | Output style files or directories. Replaces the default `output-styles/` scan |
| `workflows` | Path, or array of paths | [Workflow](/docs/en/workflows#distribute-a-workflow-in-a-plugin) `.js` files or directories. Replaces the default `workflows/` scan |
| `experimental` | Object | Container for `themes`, `monitors`, and `evals`, whose manifest shape may still change |
| `experimental.themes` | Path, or array of paths | Theme files or directories. Replaces the default `themes/` scan. A top-level `themes` key still loads, with a `claude plugin validate` warning |
| [`experimental.monitors`](#monitors) | Path, or inline array | A `.json` file holding the monitors array, or the array itself. Defaults to `monitors/monitors.json`. A top-level `monitors` key still loads, with a `claude plugin validate` warning. Monitors run only in interactive sessions, and not on Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry |
| `experimental.evals` | Path, or array of paths | Directory that holds the plugin's [eval cases](/docs/en/plugin-evals#use-a-different-eval-directory) when it isn't the default `evals/`. `claude plugin eval --eval-dir` overrides it |
In the Type column, a path is a string relative to the plugin root, such as `"./custom/commands"`.
### `name`
The plugin identifier. It must be non-empty, with no spaces, `@`, `:`, path separators, control characters, or bidirectional-formatting characters; use kebab-case.
Claude Code namespaces every component under it, so an agent `reviewer` in plugin `deploy-tools` appears as `deploy-tools:reviewer`.
### `displayName`
The name shown in UI in place of `name`. It may contain spaces and any casing, and it isn't used for namespacing or lookup.
For a marketplace-installed plugin, a `displayName` on the [marketplace entry](/docs/en/plugins/marketplace-reference#plugin-entries) takes precedence over this value.
### `version`
A version string, not checked against semver. Setting it pins the plugin to that version until you change it; see [Versions and updates](/docs/en/plugins/loading#versions-and-updates). A plugin with a [`command` source](/docs/en/plugins/marketplace-reference), a plugin from a [marketplace hosted on claude.ai](/docs/en/plugins/install#add-from-claude-ai), and a plugin [loaded in place](/docs/en/plugins/loading#find-plugins-on-disk) from a marketplace added as a local directory aren't pinned by this field.
### `metadata`
A free-form object for your own data, such as catalog or entitlement fields. Claude Code doesn't read it. Requires Claude Code v2.1.222 or later.
### `defaultEnabled`
Whether the plugin starts enabled when the user hasn't set it in [`enabledPlugins`](/docs/en/settings-reference#enabledplugins). Defaults to `true`. A plugin that an enabled plugin depends on starts enabled regardless. The same field in the marketplace entry overrides this one.
Once a user's `enabledPlugins` entry is written, it persists across plugin updates, so changing `defaultEnabled` in a later release doesn't change the setting for an existing user.
### `dependencies`
Plugins that must be enabled for this one to work. Each entry is `"name"`, `"name@marketplace"`, or `{ "name": "...", "marketplace": "...", "version": "..." }`. Bare names resolve against this plugin's own marketplace. See [dependency constraints](/docs/en/plugins/dependencies).
### `settings`
Settings Claude Code applies while the plugin is enabled. Only `agent` and `subagentStatusLine` take effect; other keys are dropped at load. A `settings.json` at the plugin root takes precedence over this key. See [Default settings](/docs/en/plugins/components#default-settings).
## Component path forms
Every component key accepts a path relative to the plugin root. `hooks`, `mcpServers`, `lspServers`, and `experimental.monitors` also accept inline configuration, `commands` also accepts an object map, and `mcpServers` also accepts MCP bundle paths and URLs. The examples that follow show each accepted shape once. For what each component does at runtime, see [Plugin components](/docs/en/plugins/components).
### Path-only fields
`agents`, `skills`, `outputStyles`, `workflows`, and `experimental.themes` take one path or an array of paths. `agents` entries must be `.md` files, and `skills` entries must be directories. The other three accept a directory or a file.
```json theme={null}
{
"agents": ["./custom-agents/reviewer.md", "./custom-agents/tester.md"],
"skills": ["./extra-skills/", "."],
"outputStyles": "./styles/"
}
```
### `commands`
`commands` takes a path, an array of paths, or an object map. A path names a flat `.md` command file or a directory. In the object map, each key becomes the command name after the plugin prefix. For example, `"about"` in plugin `deploy-tools` runs as `/deploy-tools:about`.
Each value sets exactly one of `source` or `content`, and an entry that sets both or neither fails validation. The other fields in this table are optional:
| Field | Type | Description |
| :------------- | :--------------- | :--------------------------------------------------------------- |
| `source` | string | Path to the command's Markdown file, relative to the plugin root |
| `content` | string | Inline Markdown for the command body, instead of `source` |
| `description` | string | Description shown for the command |
| `argumentHint` | string | Argument hint shown after the command name, such as `[file]` |
| `model` | string | Default model for the command |
| `allowedTools` | array of strings | Tools the command may use without prompting |
This map declares one command from a file and one from inline content:
```json theme={null}
{
"commands": {
"status": { "source": "./commands/status.md", "argumentHint": "[env]" },
"about": { "content": "Explain what this plugin provides." }
}
}
```
### `hooks`
`hooks` takes a `.json` file path, an inline hooks object in the same shape as [`hooks` in `settings.json`](/docs/en/hooks#configuration), or an array mixing both. For hook events and handler fields, see the [hooks reference](/docs/en/hooks#hook-events).
Claude Code merges whatever you declare with `hooks/hooks.json` when that file exists.
```json theme={null}
{
"hooks": [
"./config/extra-hooks.json",
{
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/scripts/format.sh" }
]
}
]
}
]
}
```
### `mcpServers`
`mcpServers` takes a `.json` file path, an MCP bundle path or URL, an inline map, or an array mixing them. For server config fields, see [plugin-provided MCP servers](/docs/en/mcp#plugin-provided-mcp-servers).
Claude Code loads `.mcp.json` at the plugin root first, then each declared shape in order. A server name declared later replaces an earlier one.
An `mcpServers` value takes one of these shapes:
| Shape | Example value | What Claude Code does |
| :---------------- | :------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- |
| `.json` file path | `"./mcp/servers.json"` | Reads the file as an `mcpServers` map |
| MCP bundle path | `"./bundle.mcpb"` | Extracts the `.mcpb` or `.dxt` bundle into `.mcpb-cache/` under the plugin root and reads its server config |
| MCP bundle URL | `"https://example.com/server.mcpb"` | Downloads the bundle into `.mcpb-cache/`, then reads it |
| Inline map | `{ "deploy-api": { "command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/server.js"] } }` | Uses the map as server configs keyed by name |
A bundle path or URL must end in `.mcpb` or `.dxt`. Any other extension fails validation.
### `lspServers`
`lspServers` takes a `.json` file path, an inline map of server name to config, or an array of either.
Claude Code loads `.lsp.json` at the plugin root first, then each declared config in order. A server name declared later replaces an earlier one.
Each server config is a strict object with these fields. An unknown key fails validation.
| Field | Required | Description |
| :---------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `command` | Yes | Language server binary. No spaces unless the value starts with `/`; put arguments in `args` |
| `extensionToLanguage` | Yes | Map of file extension to LSP language ID, at least one entry. Keys start with a dot, such as `".go"` |
| `args` | No | Arguments passed to the server |
| `transport` | No | Communication transport: `stdio` (default) or `socket`. Claude Code accepts `socket` but runs every server over stdio, so the stdout protocol rules apply to all servers |
| `env` | No | Environment variables for the server process |
| `initializationOptions` | No | Options sent in the initialize request |
| `settings` | No | Settings sent by `workspace/didChangeConfiguration` |
| `workspaceFolder` | No | Workspace folder path for the server |
| `startupTimeout` | No | Milliseconds to wait for startup, a positive integer |
| `shutdownTimeout` | No | Milliseconds to wait for a graceful shutdown, a positive integer. When the timeout elapses, Claude Code terminates the server process. When unset, no timeout applies |
| `restartOnCrash` | No | Whether to restart the server after it crashes. Defaults to `true`. Set to `false` to leave a crashed server stopped instead of restarting it |
| `maxRestarts` | No | Restart attempts before giving up, zero or more |
| `diagnostics` | No | Whether to push diagnostics into context after edits. Defaults to `true` |
This inline config runs `gopls` for `.go` files:
```json theme={null}
{
"lspServers": {
"go": {
"command": "gopls",
"args": ["serve"],
"extensionToLanguage": { ".go": "go" }
}
}
}
Cut at 300 lines. The page has the rest.
plugins/marketplace-reference New page · 475 lines, new page
# Marketplace reference ## Marketplace file ### Reserved names ## Top-level fields ## Plugin entries #### Hooks in an entry #### Display fields ### Strict mode ## Plugin sources ### Relative path plugin source #### Bare names under pluginRoot ### github plugin source ### url plugin source ### git-subdir plugin source ### npm plugin source ### archive plugin source ### command plugin source #### What the command must do #### Output that fails the install or update #### Copy mode and link mode ## Marketplace sources ### Fields by type ### Source values valid only in policy lists ### Source objects in settings ## Validation messages ### Invalid input on a source ### Failures that validation doesn't catch ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Marketplace reference
> Complete reference for marketplace.json fields, plugin entries, and the plugin and marketplace source objects, with where each is valid.
`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`](/docs/en/settings-reference#extraknownmarketplaces), [`strictKnownMarketplaces`](/docs/en/settings-reference#strictknownmarketplaces), and [`blockedMarketplaces`](/docs/en/plugins/org#restrict-what-users-can-install).
<Note>
These cases are covered on other pages:
* **Building or hosting a marketplace**: see [Create a marketplace](/docs/en/plugins/create-marketplace) and [Host and maintain a marketplace](/docs/en/plugins/host-marketplace)
* **Allowlist and blocklist recipes**: see [Manage plugins for your organization](/docs/en/plugins/org)
</Note>
Find the section for what you're writing or reading:
* **The marketplace file**: [Top-level fields](#top-level-fields) and [Plugin entries](#plugin-entries)
* **An entry's `source`**: [Plugin sources](#plugin-sources)
* **A `source` object in settings**: [Marketplace sources](#marketplace-sources)
* **Output from [`claude plugin validate <path>`](/docs/en/plugins/cli-reference)**: [Validation messages](#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`](/docs/en/settings-reference#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`, and `claude-tag-plugins`. Reserved unless the marketplace comes from a `github` or `git` [marketplace source](#marketplace-sources) under `github.com/anthropics/`.
* **Community marketplace names**: `claude-community`, `claude-plugins-community`, and `healthcare`. Reserved under the same rule as the official names.
* **Plugin directory names**: `anthropic-plugin-directory` and `claude-plugin-directory`. Reserved under the same rule as the official names.
* **Names that impersonate an official marketplace**: names such as `official-claude-plugins` or `claude-plugins-v2`, and any name containing a non-ASCII character. The error is `Marketplace name impersonates an official Anthropic/Claude marketplace`. A control or bidirectional-formatting character in a name also reports `Marketplace name cannot contain control or bidirectional-formatting characters`.
* <span id="reserved-name-spellings" />**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.plugins` counts as `claude-code-plugins`. `claude plugin validate` accepts such a name; adding the marketplace fails with [`is another spelling of "<reserved>", a reserved marketplace name`](/docs/en/errors#marketplace-name-is-another-spelling-of-a-reserved-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**: `inline` for plugins loaded with [`--plugin-dir`](/docs/en/cli-reference), `builtin` for built-in plugins, `skills-dir` for plugins auto-loaded from [`.claude/skills/`](/docs/en/skills), and `synced` for plugins synced from your claude.ai account. `claude-plugin-test` is also reserved. `skills-dir` also appears as `{"source": "skills-dir"}` in `strictKnownMarketplaces` and `blockedMarketplaces`, described under [Source values valid only in policy lists](#source-values-valid-only-in-policy-lists).
* **`npm`, `pip`, `uv`, `cargo`, `github`, and `gh`**: 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 add` refuses any other marketplace that uses one with `Cannot 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 from `marketplace.json`. `name`, `owner`, and `plugins` are required.
| Field | Type | Description |
| :----------------------------------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | string | Marketplace identifier. No spaces, control characters, or bidirectional-formatting characters, no `/` or `\`, no `..`, and not `.`. See [Reserved names](#reserved-names). Users type it after `@` when they install a plugin |
| `owner` | object | Maintainer information. `name` is required; `email` and `url` are optional |
| `plugins` | array | [Plugin entries](#plugin-entries). Each entry is validated on its own, so one invalid entry doesn't fail the marketplace |
| `$schema` | string | JSON Schema URL for editor autocomplete. Ignored at load time |
| `description` | string | Marketplace description shown to users. `claude plugin validate` warns when it's missing |
| `version` | string | Marketplace manifest version |
| `metadata.description`, `metadata.version` | string | Alternate location for `description` and `version` |
| `metadata.pluginRoot` | string | Directory that bare plugin source names resolve under. See [Relative path plugin source](#relative-path-plugin-source). Requires Claude Code v2.1.239 or later |
| `forceRemoveDeletedPlugins` | boolean | When `true`, a plugin you remove from `plugins` is uninstalled on users' machines. See [Host and maintain a marketplace](/docs/en/plugins/host-marketplace) |
| `allowCrossMarketplaceDependenciesOn` | array of strings | Marketplace names whose plugins may be installed as dependencies of this marketplace's plugins. When you install a plugin, only the list in that plugin's own marketplace applies, for its whole dependency chain. See [Plugin dependencies](/docs/en/plugins/dependencies) |
| `renames` | object | Map from a former plugin `name` to its current name, or to `null` for a plugin you removed. Requires Claude Code v2.1.193 or later. See [Host and maintain a marketplace](/docs/en/plugins/host-marketplace) |
## Plugin entries
Each object in the top-level `plugins` 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](/docs/en/plugins/manifest-reference), such as `description`, `version`, `author`, `commands`, and `hooks`. For when those fields apply, see [How an entry combines with plugin.json](#entry-and-plugin-json).
The table lists the entry's own fields and the manifest fields whose meaning changes in an entry.
| Field | Type | Description |
| :--------------- | :--------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | string | Plugin identifier, with no spaces, control characters, or bidirectional-formatting characters. Users type it before `@` when they install, even when the plugin's own `plugin.json` sets a different `name` |
| `source` | string or object | Where to fetch the plugin. See [Plugin sources](#plugin-sources) |
| `description` | string | Shown in [`/plugin`](/docs/en/plugins/install) listings and details |
| `version` | string | Version string for the plugin. When `plugin.json` also sets `version`, `plugin.json` takes precedence and `claude plugin validate` warns. See [Plugin loading reference](/docs/en/plugins/loading) |
| `category` | string | Free-form category for organizing the catalog |
| `tags` | array of strings | Free-form tags for search |
| `strict` | boolean | Default `true`. Whether `plugin.json` is the definitive source for the plugin's components. See [Strict mode](#strict-mode) |
| `relevance` | object | Signals that tell Claude Code when to suggest the plugin. See [Recommend plugins for your org](/docs/en/plugins/relevance) |
| `dependencies` | array | Plugins that must be enabled for this one to work. Each item is `"name"`, `"name@marketplace"`, or an object. See [Plugin dependencies](/docs/en/plugins/dependencies) |
| `defaultEnabled` | boolean | Default `true`. Whether the plugin starts enabled when the user hasn't set it in [`enabledPlugins`](/docs/en/settings-reference#enabledplugins). The entry value takes precedence over `plugin.json` |
| `displayName` | string | Human-readable name shown in the UI. When neither the entry nor the plugin's `plugin.json` sets one, users see the plugin's `name` |
| `metadata` | object | Free-form object for your own fields. Claude Code doesn't read it. Requires Claude Code v2.1.222 or later |
| `headers` | object | HTTP headers Claude Code sends when it downloads this entry's [archive](#archive-plugin-source). A header set here replaces a header of the same name from the marketplace source's [`headers`](#fields-by-type). Requires Claude Code v2.1.238 or later |
| `headersHelper` | string | Command that prints this entry's archive-download headers as one JSON object, for a credential that expires. The entry must also set [`"strict": false`](#strict-mode). Requires Claude Code v2.1.238 or later. See [Authenticate archive downloads](/docs/en/plugins/host-marketplace#authenticate-archive-downloads) |
<h3 id="entry-and-plugin-json">
How an entry combines with plugin.json
</h3>
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 of `strict`. Every manifest field in the entry applies, including [`mcpServers`, `lspServers`, `userConfig`, and `channels`](/docs/en/plugins/manifest-reference).
* **`plugin.json` present**: `plugin.json` is the manifest. [Strict mode](#strict-mode) decides whether the entry's six component fields, `commands`, `agents`, `skills`, `hooks`, `outputStyles`, and `themes`, are combined with it or rejected as a conflict. Entry `mcpServers`, `lspServers`, `userConfig`, and `channels` don't apply. Declare them in `plugin.json`.
#### Hooks in an entry
Write entry `hooks` 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`](/docs/en/plugins/components) or `plugin.json`.
#### Display fields
Both the entry and the plugin's own `plugin.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.json` sets a different one.
* For a field the entry leaves unset, users see the `plugin.json` value.
Before install, Claude Code can read `plugin.json` only for entries with a [relative-path source](#relative-path-plugin-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](#entry-and-plugin-json): `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.
| `strict` | `plugin.json` | Entry component fields | Result |
| :------------------ | :------------ | :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| any | absent | any | The entry is the manifest |
| `true`, the default | present | any | `plugin.json` is the authority. Claude Code appends the entry's component fields to it, except `hooks`, whose matchers [replace the manifest's per event](/docs/en/plugins/manifest-reference#how-entry-fields-combine-with-plugin-json) |
| `false` | present | none | `plugin.json` is the manifest, as with `true` |
| `false` | present | one or more | Conflict. The plugin fails to load with `Plugin <name> has conflicting manifests: both plugin.json and marketplace entry specify components` |
## Plugin sources
A plugin entry's `source` 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.
| Type | Fields | Notes |
| :------------ | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Relative path | the string itself | A directory inside the marketplace, resolved from the marketplace root. Must start with `./`, unless you write a [bare name under `metadata.pluginRoot`](#relative-path-plugin-source). `"."` on its own means the root itself |
| `github` | `repo`, `ref`, `sha` | GitHub repository in `owner/repo` form |
| `url` | `url`, `ref`, `sha` | Any git repository by URL |
| `git-subdir` | `url`, `path`, `ref`, `sha` | One subdirectory of a git repository, fetched with a sparse partial clone |
| `npm` | `package`, `version`, `registry` | npm package, fetched with your npm client and unpacked without running install scripts |
| `archive` | `url`, `sha256` | Zip archive over HTTPS. Requires Claude Code v2.1.224 or later |
| `command` | `command`, `timeout`, `mode` | Directory printed by a command Claude Code runs on the user's machine. Requires Claude Code v2.1.229 or later |
The names `url` and `github` are also [marketplace source](#marketplace-sources) 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 both `ref` and `sha`, Claude Code checks out `sha`. On most git hosts, including GitHub, GitLab, and Bitbucket, this means installation succeeds even if the branch or tag named by `ref` has 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 the `ref` must still exist and the pinned commit must be reachable from it.
For how each type is fetched, cached, and versioned, see [Plugin loading reference](/docs/en/plugins/loading).
### 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.
```json theme={null}
{ "name": "formatter", "source": "./plugins/formatter" }
```
A relative path resolves only when Claude Code has the marketplace's files, so check the [marketplace source](#marketplace-sources) type:
* **`github`, `git`, `file`, and `directory`**: Claude Code has the marketplace's files.
* **`url`**: Claude Code fetches only `marketplace.json`, so relative paths can't resolve. Give each plugin an object source instead, such as `github` or `git-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`](#top-level-fields) 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 as `team-a/formatter`, isn't a bare name and still needs the `./` prefix, even when `metadata.pluginRoot` is set.
### github plugin source
`repo` takes `owner/repo`. `ref` and `sha` are optional.
```json theme={null}
{
"name": "formatter",
"source": {
"source": "github",
"repo": "your-org/formatter",
"ref": "v2.0.0",
"sha": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
}
```
### 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.
```json theme={null}
{
"name": "formatter",
"source": {
"source": "url",
"url": "https://gitlab.example.com/your-group/formatter.git",
"ref": "main"
}
}
```
### 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.
```json theme={null}
{
"name": "formatter",
"source": {
"source": "git-subdir",
"url": "https://github.com/your-org/monorepo.git",
"path": "tools/formatter"
}
}
```
### npm plugin source
An `npm` source takes these fields:
* `package`: a package name, or a scoped name such as `@your-org/formatter`
* `version`: a version or range
* `registry`: a registry URL for a package that isn't on the default registry
Claude Code fetches the package with your npm client. The package's install scripts, such as `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](/docs/en/plugins/loading#node-js-package-dependencies) in a separate step, also with scripts disabled.
```json theme={null}
{
"name": "formatter",
"source": {
"source": "npm",
"package": "@your-org/formatter",
"version": "^2.0.0",
"registry": "https://npm.example.com"
}
}
```
### 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.
```json theme={null}
{
"name": "formatter",
"source": {
"source": "archive",
"url": "https://artifacts.example.com/formatter-2.0.0.zip",
"sha256": "6bfa50e3d2e00c052b46abe51fff89346ac803e45771f76dcf6df1ab74cca5e1"
}
}
```
### command plugin source
Use a `command` 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](/docs/en/plugins/loading#when-a-command-source-re-runs), 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, or `link`. See [Copy mode and link mode](#copy-mode-and-link-mode).
```json theme={null}
{
"name": "formatter",
"source": {
"source": "command",
"command": "my-tool claude-plugin-path",
"timeout": 120
}
}
```
For how users accept the command, see [Install from your shell](/docs/en/plugins/install#install-from-your-shell). For what users see after you change it, see [Change the command of a command source](/docs/en/plugins/host-marketplace#change-the-command-of-a-command-source). Administrators turn command sources off with [`disableCommandPluginSources`](/docs/en/settings-reference#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 through `cmd.exe` on Windows, from the user's home directory. Give an absolute path or a command on `PATH`.
* **Output**: print exactly one line on stdout, the absolute path of the plugin directory, and exit 0 within `timeout` seconds.
* **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 than `timeout`, 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 a `skills/`, `commands/`, `agents/`, or `hooks/` directory.
* **The session's own directory**: the printed directory is the one Claude Code was started in, or one of its parents.
Cut at 300 lines. The page has the rest.
plugins/measure New page · 165 lines, new page
# Measure plugin cost and usage ## Measure what a plugin costs ### Lower the always-on figure ### Cost shown to users before install ## Check whether a plugin is used ### Not used recently in `/plugin` ### Find skills that never run ### Unused plugins in `/doctor` ### Usage share in `/usage` ## Measure across a fleet ### Redacted plugin names in your backend ### Query the Analytics API ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Measure plugin cost and usage
> Measure a Claude Code plugin's token cost, find out whether people still use it, and pick the telemetry events for organization-wide plugin questions.
Every session where a plugin is enabled includes the names and descriptions of its skills, agents, and commands in Claude's context, and those tokens count against the user's usage whether or not the plugin gets used. This page shows how to see that number for a plugin, how to reduce it if you maintain the plugin, and where usage shows up so you can tell whether a plugin is still being used.
This page is for plugin authors and maintainers. If you administer Claude Code for an organization, [Measure across a fleet](#measure-across-a-fleet) covers the same questions across every machine.
<Note>
These cases are covered on other pages:
* **Testing how reliably the plugin changes Claude's behavior**: see [Test plugins with evals](/docs/en/plugin-evals)
* **Trimming your own session's context**: see [Manage installed plugins](/docs/en/plugins/install#manage-installed-plugins) and the [context window](/docs/en/context-window) page
</Note>
Start with [Measure what a plugin costs](#measure-what-a-plugin-costs).
## Measure what a plugin costs
To see what a plugin adds to Claude's context, run [`claude plugin details`](/docs/en/plugins/cli-reference#plugin-details) with the plugin's name. You run it in your shell, not at the prompt of a running Claude Code session. The plugin has to be loaded: installed, in a skills directory, or passed with `--plugin-dir` in the same command, as in `claude --plugin-dir ./formatter plugin details formatter`.
This example reads an installed plugin named `formatter` that has two skills, a command, an agent, a hook, and an MCP server:
```bash theme={null}
claude plugin details formatter
```
```text theme={null}
formatter 1.0.0
Description: Formats and lints code on save
Source: formatter@my-marketplace
Component inventory
Skills (3) format-all, format-code, lint-fix
Agents (1) style-reviewer
Hooks (1) PostToolUse (harness-only — no model context cost)
MCP servers (1) formatter-tools (tool schemas resolved at runtime; not counted)
LSP servers (0)
Projected token cost
Always-on: ~146 tok added to every session
Per-component (rounded)
component always-on on-invoke
format-code ~40 ~30
lint-fix ~50 ~30
style-reviewer ~40 ~40
format-all < 20 ~30
On-invoke cost is paid each time a skill or agent fires.
Token counts are estimates and may differ from actual usage.
```
Each part of the output answers a different question:
* **Component inventory**: what Claude Code found in the plugin. Commands are counted with skills, so `format-all` appears under `Skills`. Hooks and MCP servers get no cost estimate and no per-component row; to see what a plugin's MCP tools add, run `/context` in a session with the plugin enabled and read the `MCP tools` category.
* **Always-on**: the tokens that the names and descriptions of the plugin's skills, agents, and commands add to every session where the plugin is enabled, whether or not anything runs. This is the number every user carries, and the one to reduce.
* **Per-component**: each row splits one skill, agent, or command into its always-on share and its on-invoke cost, which is the body that loads only when that component runs. Use the always-on column to find which component contributes most.
### Lower the always-on figure
If you maintain the plugin, these changes reduce what it adds to every session. If you only use it, your options are to disable or uninstall it; see [Manage installed plugins](/docs/en/plugins/install#manage-installed-plugins).
The always-on figure counts each component's name plus its `description` and `when_to_use` frontmatter. To lower it:
* Shorten skill and agent descriptions.
* Split a large plugin so users install only the components they need.
A skill's description is also what Claude matches a request against, so a shorter one can stop the skill triggering. After you trim descriptions, check triggering with a [`tool_used: Skill` grader](/docs/en/plugin-evals#create-your-first-eval-suite) in your eval suite.
For what each component type contributes, see [plugin components](/docs/en/plugins/components).
### Cost shown to users before install
Plugins in the official marketplace show their cost to users before install. In `/plugin`, when a user browses a marketplace's plugin list and selects a plugin, the details pane shows a **Context cost** section with an `Every turn:` line and a `When invoked:` line. When the always-on figure is 2,000 tokens or more, the `Every turn:` line appears highlighted.
A plugin in your own marketplace has no **Context cost** section.
## Check whether a plugin is used
Claude Code doesn't report a plugin's usage back to its author. Usage is recorded on the machine of each person who installed the plugin, so what you can learn depends on your relationship to those people:
* **You administer Claude Code for their organization**: the OpenTelemetry events and the Analytics API count installs and skill activations across every machine. See [Measure across a fleet](#measure-across-a-fleet).
* **They're teammates you can ask**: each user's own Claude Code shows them whether they still use the plugin, in four places: the [`/plugin` panel](#not-used-recently-in-/plugin), [`/skill-doctor`](#find-skills-that-never-run), [`/doctor`](#unused-plugins-in-/doctor), and [`/usage`](#usage-share-in-/usage). All four are commands the user runs at the Claude Code prompt in a session on their own machine.
* **Neither**: you have no usage signal from Claude Code for that plugin.
### Not used recently in `/plugin`
On the **Installed** tab of `/plugin`, a plugin the user installed from a marketplace moves under a **Not used recently** header once it has gone unused for at least 14 days and 10 sessions. The plugin's details also show a `Last used:` line. For what users do with that header and line, see [Find plugins you no longer use](/docs/en/plugins/install#find-plugins-you-no-longer-use).
The **Not used recently** header never appears for:
* Plugins loaded with `--plugin-dir` or from a skills directory
* Plugins enabled through managed settings, or mounted from a [seed directory](/docs/en/plugins/org#seed-containers-and-ci)
* Plugins that include a theme, output style, monitor, or workflow, because those are in use without a tracked invocation
A plugin's [language server](/docs/en/plugins/components#lsp-servers) counts as used when it delivers diagnostics or answers a code navigation request, so an LSP plugin whose server is active in your sessions isn't listed as unused.
When the user's organization sets [`strictKnownMarketplaces`](/docs/en/plugins/org#restrict-what-users-can-install), neither the header nor the `Last used:` line appears.
### Find skills that never run
Run `/skill-doctor` to see what each of your skills costs and how often it gets used. It flags skills that are in Claude's skill listing but have never been invoked, including skills from plugins.
In an interactive session, the report opens in the `/plugin` manager's **Stats** tab. See [Find unused skills](/docs/en/skills#find-unused-skills) for what the report covers and where it's available.
### Unused plugins in `/doctor`
The `/doctor` checkup lists each user-installed skill, MCP server, and plugin, and recommends disabling the ones that were not used. See [`/doctor` in the commands reference](/docs/en/commands#all-commands).
### Usage share in `/usage`
On a Pro, Max, Team, or Enterprise plan, the `/usage` breakdown attributes recent usage to skills, subagents, plugins, and MCP servers as a share of the total. See [Using the `/usage` command](/docs/en/costs#using-the-/usage-command).
## Measure across a fleet
If you administer Claude Code for an organization, you can measure plugin cost and usage across every machine from either of these sources:
* **OpenTelemetry events**: Claude Code exports these to your own backend once you [configure an exporter](/docs/en/monitoring-usage). See [OpenTelemetry events for plugin installs and use](#pick-the-opentelemetry-event-for-each-question).
* **Analytics API**: served from Anthropic's records, with no exporter needed. See [Query the Analytics API](#query-the-analytics-api).
<h3 id="pick-the-opentelemetry-event-for-each-question">
OpenTelemetry events for plugin installs and use
</h3>
These OpenTelemetry events and attributes answer each plugin question from your backend:
| Question | OpenTelemetry event or attribute |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Which plugins get installed, and from where | [`claude_code.plugin_installed`](/docs/en/monitoring-usage#plugin-installed-event), one per install |
| Which plugins are active in how many sessions | [`claude_code.plugin_loaded`](/docs/en/monitoring-usage#plugin-loaded-event), one per enabled plugin at session start |
| Which skills activate, and which plugin owns them | [`claude_code.skill_activated`](/docs/en/monitoring-usage#skill-activated-event), with `plugin.name` and `marketplace.name` for plugin skills |
| What a plugin's hooks report | [`claude_code.hook_plugin_metrics`](/docs/en/monitoring-usage#hook-plugin-metrics-event), emitted only for hooks in official-marketplace plugins |
| What a plugin costs in API spend | `plugin.name` and `marketplace.name` on the [cost counter](/docs/en/monitoring-usage#cost-counter), set when the active skill or subagent belongs to a plugin |
### Redacted plugin names in your backend
Plugins from the official marketplace report their plugin name and marketplace name to your backend verbatim. Every other plugin's name is redacted or omitted by default, including a plugin from your organization's own marketplace. The plugin's [trust tier](/docs/en/plugins/security#find-plugins-in-telemetry) decides which.
To get real names on some events, set the [`OTEL_LOG_TOOL_DETAILS`](/docs/en/monitoring-usage#common-configuration-variables) environment variable to `1` on the machines that export telemetry, for example in the `env` block of the same [managed settings](/docs/en/monitoring-usage#administrator-configuration) that configure the exporter:
| Event | Default | With `OTEL_LOG_TOOL_DETAILS=1` |
| :------------------------------------ | :------------------------------------------------------------------------------------------------- | :-------------------------------------------------- |
| `plugin_loaded` | `plugin.name` and `marketplace.name` are the literal string `third-party` | Real names |
| `plugin_installed`, `skill_activated` | `plugin.name` and `marketplace.name` omitted; on `skill_activated`, `skill.name` is `custom_skill` | Real names |
| Cost counter | `plugin.name` is `third-party`; `marketplace.name` absent | Real `plugin.name`; `marketplace.name` still absent |
On `plugin_loaded`, `plugin_id_hash` still identifies each plugin by default, so you can count distinct third-party plugins.
### Query the Analytics API
On the Enterprise plan, the Analytics API answers "which plugins does my organization install and invoke" from Anthropic's records, with no exporter needed. [`GET /v1/organizations/analytics/plugins`](https://platform.claude.com/docs/en/api/admin/analytics/plugins/list) returns per-plugin, per-day install and invocation counts across Claude Code and Cowork, which you can group by user, RBAC group, or product.
Plugin activity that reaches Anthropic without a plugin name appears in one aggregate `third-party` row. [Find plugins in telemetry](/docs/en/plugins/security#find-plugins-in-telemetry) says which plugins Claude Code reports by name.
Authenticate the request with an API key that has the `read:analytics` scope, which a Primary Owner creates as described under [Access data programmatically](/docs/en/analytics#access-data-programmatically).
See the [endpoint reference](https://platform.claude.com/docs/en/api/admin/analytics/plugins/list) for the parameters and response fields.
## Next steps
* [Test plugins with evals](/docs/en/plugin-evals): measure how reliably the plugin steers Claude, not only what it costs
* [Lower the always-on figure](#lower-the-always-on-figure): what to change in the plugin to reduce its per-turn cost
* [Plugin security and trust](/docs/en/plugins/security#find-plugins-in-telemetry): which telemetry fields carry plugin names and when they're redacted
* [Monitoring usage](/docs/en/monitoring-usage): the full OpenTelemetry event reference
plugins/org New page · 398 lines, new page
# Manage Claude Code plugins for your organization ## Pre-install and require plugins ### Choose a delivery mechanism #### Which managed source applies on a machine ### Require a marketplace and its plugins ### Require plugins per repository ### When each surface applies the plugin keys ### Confirm the rollout ## Seed containers and CI ## Restrict what users can install ### Control matrix #### Aliases for the marketplace keys ### Allowlist with `strictKnownMarketplaces` #### How entries match #### Keep skills-directory plugins loading #### Marketplaces hosted on claude.ai #### Lock every source out ### Blocklist with `blockedMarketplaces` ### Allow the official marketplace and your own ## Set update policy ### Turn auto-update on or off per marketplace ### Turn updates off for the whole fleet ### Assign release channels to user groups ## Recommend plugins ## Audit and review ### OpenTelemetry events ### Analytics API ## Plan for what managed settings can't enforce ## Troubleshoot policy ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Manage Claude Code plugins for your organization
> Control which plugins Claude Code installs and allows across your organization through managed settings.
Managed settings let you decide which plugins Claude Code installs and allows on every machine in your organization. Users can't override them. You deliver them either as [server-managed settings](/docs/en/server-managed-settings) from the claude.ai admin console or as endpoint-managed settings through MDM or a `managed-settings.json` file. Most controls on this page take effect only from managed settings.
This page is for administrators, and the settings here govern Claude Code.
<Note>
These cases are covered on other pages:
* **Installing plugins for yourself**: start at [Install plugins](/docs/en/plugins/install)
* **Controlling which plugins members can use in claude.ai and Cowork**: see [Manage plugins for your organization](https://support.claude.com/en/articles/13837433) in the help center
* **The plugins page in claude.ai's admin settings**: [**Organization settings > Plugins & skills**](https://claude.ai/admin-settings/skills?tab=inventory) turns plugins on for members' claude.ai accounts, and those reach Claude Code as [synced plugins](/docs/en/plugins/loading#synced-plugins). It doesn't set any of the keys on this page
</Note>
The sections follow the order most rollouts take: [require plugins](#pre-install-and-require-plugins) for everyone or per repository, [seed containers and CI](#seed-containers-and-ci), [restrict](#restrict-what-users-can-install) what users can add on their own, [set update policy](#set-update-policy), then [audit](#audit-and-review) what's installed. To review every policy key in one place, see the [control matrix](#control-matrix).
## Pre-install and require plugins
A marketplace is a catalog of plugins that Claude Code fetches from a git repository, a URL, or a local path. Once you register a marketplace on a machine, Claude Code can install plugins from it.
To install plugins for a fleet, set two keys together in [managed settings](/docs/en/managed-settings), the policy file or server-delivered policy that every machine in your organization reads: `extraKnownMarketplaces` registers a marketplace on each machine, and `enabledPlugins` names the plugins to install and enable from it. [Choose a delivery mechanism](#choose-a-delivery-mechanism) covers how managed settings reach each machine.
### Choose a delivery mechanism
Managed settings reach a machine through one of three delivery mechanisms:
* **Server-managed settings**: set the plugin keys as JSON at [**Organization settings > Claude Code > Managed settings**](https://claude.ai/admin-settings/claude-code). Requires an [Owner role](/docs/en/server-managed-settings#access-control) in your Claude organization. A cloud session fetches these settings before it installs plugins.
* **MDM policies**: on macOS, deliver a plist whose top-level keys are the settings keys. On Windows, store the whole JSON document as a string in a registry value. The plist domain and the registry key are in [Where each mechanism stores the policy](/docs/en/managed-settings#where-each-mechanism-stores-the-policy).
* **Managed settings file**: place a `managed-settings.json` at the platform's system path. You can also add files to the `managed-settings.d/` drop-in directory beside it. The file paths per platform are in [Where each mechanism stores the policy](/docs/en/managed-settings#where-each-mechanism-stores-the-policy), and the drop-in merge rules are in [Split a file-based policy across teams](/docs/en/managed-settings#split-a-file-based-policy-across-teams).
Use server-managed settings if you have a Claude for Teams or Enterprise organization on claude.ai and your devices aren't all under MDM. Otherwise use an MDM policy or the managed settings file. For the trade-off, see [Choose between server-managed and endpoint-managed settings](/docs/en/server-managed-settings#choose-between-server-managed-and-endpoint-managed-settings).
#### Which managed source applies on a machine
By default, only one of these three sources applies on a machine. Claude Code uses the first that delivers a policy key, checking server-managed settings first, then MDM policies, then the managed settings file. If server-managed settings deliver even one unrelated policy key, Claude Code ignores the plugin keys in an MDM policy or managed settings file on that machine, apart from the [keys it reads from every source](/docs/en/managed-settings#keys-read-from-every-admin-source).
To apply every source instead, set [`managedSourcesBehavior`](/docs/en/managed-settings#compose-every-managed-source) to `"merge"`.
[How Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources) also lists the keys Claude Code reads from every source in both modes.
### Require a marketplace and its plugins
Add the marketplace under `extraKnownMarketplaces`, keyed by the marketplace's own `name` from its `marketplace.json`. Then add each plugin under `enabledPlugins` as `plugin-name@marketplace-name`. Each marketplace entry carries a `source` object with a `source` field naming the type, such as `github`. This managed settings example registers an organization marketplace and force-enables two plugins from it:
```json theme={null}
{
"extraKnownMarketplaces": {
"your-marketplace": {
"source": { "source": "github", "repo": "your-org/your-marketplace" },
"autoUpdate": true
}
},
"enabledPlugins": {
"code-formatter@your-marketplace": true,
"deploy-helper@your-marketplace": true
}
}
```
After the settings reach a machine, Claude Code registers the marketplace and installs the two plugins at the start of the user's next session. Users see them in `/plugin`, and disabling one at their own scope doesn't stop it from loading, because managed settings take precedence over every other scope.
To block a plugin at every scope and hide it from the marketplace listing, set it to `false` in the managed `enabledPlugins` instead.
Adjust the `autoUpdate` and `source` fields for your marketplace:
* **`autoUpdate`**: `true` keeps the marketplace and its plugins refreshing in the background, and `false` turns that off. See [Set update policy](#set-update-policy).
* **`source`**: `github` is one of several source types. A `git` source takes a `url` for GitLab or an internal host, and a `url` source takes the address of a hosted `marketplace.json`. Every source shape is in the [marketplace reference](/docs/en/plugins/marketplace-reference).
If the marketplace is a private git repository, each user needs read access to it. The clone of a git-based marketplace runs with git on the user's machine, using stored credentials and no prompts. For users without git-host accounts, use a [seed](#seed-containers-and-ci) instead.
A managed entry also overrides a same-name marketplace entry or `--plugin-dir` copy from another source:
* **Marketplaces**: a managed marketplace entry replaces a lower-precedence entry with the same name, and the two entries' fields don't merge.
* **`--plugin-dir` copies**: `--plugin-dir` loads a plugin from a local directory for one session. For what happens when that copy's name matches a plugin your managed `enabledPlugins` names, see [Name conflicts](/docs/en/plugins/loading#name-conflicts).
Anthropic's official marketplace `claude-plugins-official` needs no `extraKnownMarketplaces` entry when `enabledPlugins` sets one of its plugins to `true`. That `name@claude-plugins-official` entry declares the marketplace by itself, wherever these keys apply. If you enable none of its plugins and still want it registered on every machine, give it an explicit entry, as [Allow the official marketplace and your own](#allow-the-official-marketplace-and-your-own) does.
### Require plugins per repository
To cover one repository's contributors instead of your whole fleet, set `extraKnownMarketplaces` and `enabledPlugins` in that repository's `.claude/settings.json`. The `extraKnownMarketplaces` entries apply only in a folder the contributor has trusted, and in an untrusted folder Claude Code ignores them without a message:
* **Interactive sessions**: Claude Code registers the marketplace only after the contributor accepts the [workspace trust dialog](/docs/en/permissions#what-runs-before-you-trust-a-folder) for that folder.
* **[Non-interactive `-p` runs](/docs/en/headless)**: the entries apply only in a folder whose trust the user already accepted interactively, or whose `hasTrustDialogAccepted` flag you set in `~/.claude.json`.
A plugin that the marketplace lists by a relative path loads from the marketplace copy once the repository's `extraKnownMarketplaces` entries apply. A plugin whose marketplace entry points at an external source instead, such as the plugin's own GitHub repository, doesn't install from the repository's settings alone. Each contributor sees `Plugin "<name>" is enabled in project settings but isn't installed` until they run `claude plugin install <name>@<marketplace> --scope project`, as [Install plugins](/docs/en/plugins/install) describes.
If you use a local `directory` or `file` source with a relative path, the path resolves against your repository's main checkout. When you run Claude Code from a git worktree, the path still points at the main checkout, so all worktrees share the same marketplace location.
To roll out a bundle of plugins with dependencies, put the bundle plugin in `enabledPlugins`, as [Plugin dependencies](/docs/en/plugins/dependencies) describes.
### When each surface applies the plugin keys
The table shows when each kind of Claude Code session applies `extraKnownMarketplaces` and `enabledPlugins`, from managed settings and from a repository's `.claude/settings.json`. For the Desktop app and the IDE extensions, see [Install a plugin](/docs/en/plugins/install#install-a-plugin).
| Surface | Managed `extraKnownMarketplaces` and `enabledPlugins` | Repository `.claude/settings.json` |
| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- |
| Terminal, interactive | Applied at session start on every machine that receives the settings | `extraKnownMarketplaces` applied after trust; `enabledPlugins` applied at session start |
| `-p` and CI | Applied at session start, with installs running in the background | `extraKnownMarketplaces` in trusted folders only; `enabledPlugins` applied |
| Cloud sessions | In an Anthropic-hosted environment, only server-managed settings reach the session, which waits for them before it installs plugins. MDM policies and managed settings files stay on the user's machine. For a self-hosted environment, see [Where and when a policy applies](/docs/en/managed-settings#where-and-when-a-policy-applies) | See the **Cloud session** tab under [Install a plugin](/docs/en/plugins/install#install-a-plugin) |
In a `-p` or CI run, marketplaces and plugins install in the background, so a plugin can be missing from the first turn. Set `CLAUDE_CODE_SYNC_PLUGIN_INSTALL=1` to make the run wait for the install before its first query.
### Confirm the rollout
Check that the marketplace and plugins arrived on a machine or in a CI run:
* **On one machine**: start Claude Code and run `/plugin`. The marketplace and the plugins are listed.
* **In CI**: run `claude -p` with `--output-format stream-json --verbose`. The `init` event lists the loaded plugins under `plugins`.
## Seed containers and CI
For container images and CI runners that can't clone at runtime, pre-populate a plugins directory at build time and point `CLAUDE_CODE_PLUGIN_SEED_DIR` at it. Claude Code registers the seed's marketplaces at startup and loads plugin caches from the seed in place, without cloning.
A seed also serves users who have no git-host account.
<Note>
In CI/CD environments, configure a git credential helper before installing plugins from private repositories. On GitHub Actions, export a token with read access to the marketplace repository as `GH_TOKEN`, then run `gh auth setup-git`. The default workflow token can only access the workflow's own repository, so a private marketplace in another repository needs a personal access token or app token.
</Note>
<Steps>
<Step title="Install into the seed at build time">
Set `CLAUDE_CODE_PLUGIN_CACHE_DIR` to the seed path so the marketplace and plugins install there instead of `~/.claude/plugins`:
```bash theme={null}
CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin marketplace add your-org/your-marketplace
CLAUDE_CODE_PLUGIN_CACHE_DIR=/opt/claude-seed claude plugin install code-formatter@your-marketplace
```
The seed has the same layout as `~/.claude/plugins`: `known_marketplaces.json`, `marketplaces/<name>/`, and `cache/<marketplace>/<plugin>/<version>/`. You can mount the seed at a different path than you built it at.
</Step>
<Step title="Point the runtime at the seed">
Set `CLAUDE_CODE_PLUGIN_SEED_DIR=/opt/claude-seed` in the container's environment. To use several seeds, separate their paths with `:` on Unix or `;` on Windows. Claude Code uses the first seed that contains a given marketplace or plugin cache.
</Step>
<Step title="Enable the plugins">
The plugins in a seed aren't enabled on their own. Set `enabledPlugins` for each seed plugin you want loaded, in managed settings or in the repository's `.claude/settings.json`.
</Step>
</Steps>
To verify a seed, run `claude -p` with `--output-format stream-json --verbose` in the image. In the `init` event's `plugins` list, each loaded plugin's `path` is under the seed, such as `/opt/claude-seed/cache/your-marketplace/code-formatter/1.0.0`.
Seed marketplaces follow these rules:
* **Read-only**: Claude Code never writes to the seed and forces `autoUpdate` off for seed marketplaces.
* **Seed entries take precedence**: on each startup, a marketplace declared in the seed overwrites the user's entry of the same name. Users opt out of a seed plugin with `claude plugin disable`, not by removing the marketplace.
* **Update and remove fail**: `claude plugin marketplace update <name>` and `remove` without `--scope` on a seed marketplace fail with a message that names the seed directory.
* **Policy still applies**: the [allowlist and blocklist](#restrict-what-users-can-install) check a seed marketplace's recorded source too. Allow the source you built the seed from.
For fleets with no outbound git access, combine a seed with `directory` or `file` marketplace sources on a shared mount. Set `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` as well, which also turns off [plugin auto-update](/docs/en/plugins/loading#when-auto-update-runs). If a proxy is available, see [Proxy configuration](/docs/en/network-config#proxy-configuration) for the variables to set.
## Restrict what users can install
The managed `strictKnownMarketplaces` allowlist and `blockedMarketplaces` blocklist decide which marketplace sources plugins may come from. A marketplace's source is the git repository, URL, or local path that Claude Code fetches it from. Both lists match the source of the marketplace a plugin comes from, not the plugin's own entry inside that marketplace.
For the common lockdown, which allows the official marketplace and your own, see [Allow the official marketplace and your own](#allow-the-official-marketplace-and-your-own). Pair it with [`disableSideloadFlags`](#control-matrix) so users can't load plugins from a local directory or URL either.
Both lists apply before anything downloads and again at session start:
* **Before a download**: the lists apply when a user adds a marketplace and on every install, update, refresh, and auto-update.
* **At session start**: the lists apply again to plugins that are already installed, so an installed plugin whose marketplace source no longer matches doesn't load. `/plugin` lists it with `Marketplace "<name>" is not in the allowed marketplace list` or `Marketplace "<name>" is blocked by enterprise policy`.
Where the two lists are enforced depends on where you set them:
* **The claude.ai admin console**: Claude Code enforces both lists in the sessions that [read server-managed settings](/docs/en/managed-settings#where-and-when-a-policy-applies). claude.ai also checks them when anyone in your organization adds a new marketplace from a git repository on claude.ai, or from **Customize** in the Claude Desktop app outside its Code tab. That covers a marketplace a member adds for their own account and one added for the whole organization under [**Organization settings > Plugins**](https://claude.ai/admin-settings/plugins). claude.ai refuses a repository that the allowlist doesn't admit or that the blocklist names. It doesn't re-check a marketplace that was added in either place before you set the lists, and it doesn't check uploaded plugins.
* **A managed settings file, OS-level policy, or other managed source**: Claude Code enforces both lists where it reads that source. claude.ai doesn't read it.
While any allowlist is set, or a blocklist names any source other than [`skills-dir`](#blocklist-with-blockedmarketplaces), a plugin whose marketplace Claude Code can't find doesn't load. `/plugin` shows the policy error for it rather than a not-found error. The common case is a stale `enabledPlugins` entry for a marketplace nobody registered.
### Control matrix
The table lists each plugin policy key, what it enforces, and what it can't do.
| Key | What it enforces | What it can't do |
| :----------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `strictKnownMarketplaces` | Allowlist of marketplace sources. `[]` blocks every source, including the official marketplace. Alias: `allowedMarketplaces` | Doesn't register a marketplace, restrict entries inside an allowed marketplace, or block `--plugin-dir` |
| `blockedMarketplaces` | Blocklist of marketplace sources, checked before the allowlist | Doesn't block a marketplace already registered from a source it doesn't match |
| `syncClaudeAiPlugins` | Set `false` to stop Claude Code downloading and loading the plugins [synced from claude.ai](/docs/en/plugins/loading#synced-plugins) for each user's account. Requires Claude Code v2.1.273 or later | Doesn't turn off one synced plugin. For that, set `"<name>@synced": false` in [`enabledPlugins`](/docs/en/settings-reference#enabledplugins) |
| `enabledPlugins` | `true` force-enables, `false` blocks at every scope and hides the plugin | Doesn't install a plugin whose marketplace isn't registered or allowed |
| `disableSideloadFlags` | Rejects `--plugin-dir`, `--plugin-url`, `--agents`, the Agent SDK `plugins` option, and non-SDK `--mcp-config` at startup, and rejects folders named in the [`CLAUDE_CODE_PLUGIN_DIRS`](/docs/en/env-vars#variables) variable the same way | Doesn't restrict `.mcp.json`, `claude mcp add`, or SDK-provided servers. Pair it with [`allowedMcpServers`](/docs/en/managed-mcp) |
| `disableCommandPluginSources` | Blocks plugins with a `command` source from installing, updating, or loading. A `command` source is one whose plugin directory is produced by running a command on the machine. When unset, it takes the value of `allowManagedHooksOnly` | Doesn't affect other source types |
| `allowManagedHooksOnly` | Restricts which hooks run. See [`allowManagedHooksOnly`](/docs/en/settings-reference#allowmanagedhooksonly) | Doesn't trust hooks from plugins users enable themselves |
| `strictPluginOnlyCustomization` | Blocks skills, agents, hooks, and MCP servers that don't come from a plugin, managed settings, or Claude Code's built-ins. Set `true` to cover all four types, or an array of `skills`, `agents`, `hooks`, and `mcp` values such as `["skills", "hooks"]` to cover some | Doesn't restrict which plugins users install. Pair it with `strictKnownMarketplaces` |
| `pluginSuggestionMarketplaces` | Marketplaces whose plugins may appear as install suggestions. See [Recommend plugins](#recommend-plugins) | Doesn't affect the built-in tips |
| `pluginTrustMessage` | Appends your text to the trust warning that `/plugin` shows before a plugin installs | Doesn't change the warning's own text |
| `allowedChannelPlugins` | Replaces the default list of plugins allowed to push channel messages. Requires `channelsEnabled: true` | See [Restrict which channel plugins can run](/docs/en/channels#restrict-which-channel-plugins-can-run) |
| [`CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL=1`](/docs/en/env-vars) | Stops interactive terminal sessions from auto-registering the official marketplace | Doesn't remove a marketplace already registered. The allowlist and blocklist gate the same auto-registration without it. A machine that started once with it set doesn't resume auto-registration after you unset it |
Every key in the table is a managed setting, apart from `enabledPlugins`, `syncClaudeAiPlugins`, and `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL`:
* **`enabledPlugins`**: you can set it in any scope, and managed settings lock it.
* **`syncClaudeAiPlugins`**: each user can also set it in their own user or local settings. See its [scope in the settings reference](/docs/en/settings-reference#syncclaudeaiplugins).
* **`CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL`**: this is an environment variable that you deliver through the managed `env` block shown under [Turn updates off for the whole fleet](#turn-updates-off-for-the-whole-fleet).
Each settings key here has an entry in the [settings reference](/docs/en/settings-reference).
#### Aliases for the marketplace keys
`strictKnownMarketplaces` can also be spelled `allowedMarketplaces`, and `extraKnownMarketplaces` can also be spelled `additionalMarketplaces`.
* **Version**: the aliases require Claude Code v2.1.232 or later, and older clients ignore them. In a file that a mixed fleet reads, keep the canonical names.
* **Both spellings set**: when a file sets both spellings, the canonical key's value applies.
### Allowlist with `strictKnownMarketplaces`
Set the allowlist to a list of these source objects. Most entries match exactly, `hostPattern` and `pathPattern` entries match as regular expressions, and `github` owner wildcards match by owner:
* **`github`**: `{ "source": "github", "repo": "your-org/approved-plugins" }`, with optional `ref` and `path`.
* **`github` owner wildcard**: `{ "source": "github", "repo": "your-org/*" }` matches every repository under that owner. The `*` must stand for the whole repository name. Claude Code ignores entries such as `*/plugins` and `your-org/tools-*` as invalid, so they match nothing. Requires Claude Code v2.1.223 or later.
* **`git`**: `{ "source": "git", "url": "https://gitlab.example.com/tools/plugins.git" }`, with optional `ref` and `path`.
* **`url`**: `{ "source": "url", "url": "https://plugins.example.com/marketplace.json" }`, with optional `headers`.
* **`file` and `directory`**: `{ "source": "file", "path": "/opt/marketplace/marketplace.json" }` or `{ "source": "directory", "path": "/opt/marketplace/plugins" }`, with absolute paths.
* **`hostPattern`**: `{ "source": "hostPattern", "hostPattern": "^github\\.example\\.com$" }`, matched against the host of `github`, `git`, and `url` sources. The pattern matches anywhere in the hostname, so anchor it with `^` and `$` as shown to match the whole host. A `github` source always counts as `github.com`. Use a `hostPattern` entry for a GitHub Enterprise Server or GitLab host where developers create their own marketplaces. The [GHES page](/docs/en/github-enterprise-server#allowlist-ghes-marketplaces-in-managed-settings) has the worked example.
* **`pathPattern`**: `{ "source": "pathPattern", "pathPattern": "^/opt/approved/" }`, matched against the `path` of `file` and `directory` sources. The pattern matches anywhere in the path, so start it with `^` to pin a directory prefix. `".*"` allows every local path.
* **`skills-dir`**: `{ "source": "skills-dir" }` keeps [skills-directory plugins](#keep-skills-directory-plugins-loading) loading while an allowlist is set, and matches no marketplace.
#### How entries match
A `url` entry matches on its `url` value; `headers` aren't compared. For `github` and `git` entries, the `repo` or `url`, the `ref`, and the `path` must all match, or be absent on both sides:
* An entry without `ref` doesn't cover a source with `ref: "main"`.
* An entry for `your-org/your-marketplace` doesn't cover a `git` URL that clones the same repository.
* A trailing slash, a `.git` suffix, or `ssh://` in place of `https://` is a different value. When a marketplace can be cloned by more than one URL, prefer a `hostPattern` entry.
Owner-wildcard entries follow the exact rules for `ref` and match any `path` inside the repository unless the entry pins one. Wildcard matching is case-sensitive on the allowlist.
#### Keep skills-directory plugins loading
Skills-directory plugins are the plugins users keep under `~/.claude/skills/` or a project's `.claude/skills/` in folders that carry a `.claude-plugin/plugin.json`. If you set any allowlist without a `{ "source": "skills-dir" }` entry, they stop loading. Plain [skills](/docs/en/skills), meaning a `SKILL.md` without that manifest, keep loading.
#### Marketplaces hosted on claude.ai
The allowlist and blocklist match a [marketplace hosted on claude.ai](/docs/en/plugins/install#add-from-claude-ai) by its host. To allow or block one, add a `hostPattern` entry that matches `claude.ai` to `strictKnownMarketplaces` or `blockedMarketplaces`. On the allowlist, such an entry admits your organization's claude.ai marketplaces and the claude.ai default marketplaces, but not a marketplace made of a member's own claude.ai uploads or one whose scope claude.ai didn't state. Requires Claude Code v2.1.273 or later.
#### Lock every source out
An empty allowlist, `[]`, locks every marketplace source out, including the official marketplace.
This lockdown doesn't cover the plugins [synced from claude.ai](/docs/en/plugins/loading#synced-plugins), which Claude Code downloads from each user's account rather than from a marketplace. To stop those as well, set [`syncClaudeAiPlugins`](/docs/en/settings-reference#syncclaudeaiplugins) to `false` in managed settings, or turn off Skills for your organization on claude.ai.
### Blocklist with `blockedMarketplaces`
`blockedMarketplaces` takes the same source objects as [`strictKnownMarketplaces`](#allowlist-with-strictknownmarketplaces) and is checked first, so a source on both lists is blocked. Blocklist matching is wider than allowlist matching:
* Git URLs are canonicalized, so the `git@` and `https://` forms, `.git` suffixes, and trailing slashes of one `github.com` repository all match the same entry.
* A `github` entry also blocks the equivalent `git` URL, and the other way around.
* For an `owner/*` entry, the owner comparison is case-insensitive.
* An entry without `ref` or `path` blocks every ref and path of the repositories it matches.
This entry blocks every repository under one GitHub owner:
```json theme={null}
{
"blockedMarketplaces": [
{ "source": "github", "repo": "untrusted-org/*" }
]
}
```
The `url` entries in `blockedMarketplaces` also apply when a user adds an `https://` repository URL that Claude Code [clones rather than fetches](/docs/en/plugins/cli-reference#plugin-marketplace-add), such as a bare `github.com` or `gitlab.com` repository URL. The user can't add that URL if an entry names it. The match ignores the `.git` suffix and any ref the user appends after `#`. Requires Claude Code v2.1.232 or later.
A `{ "source": "skills-dir" }` entry here stops [skills-directory plugins](#keep-skills-directory-plugins-loading) from loading, from both `~/.claude/skills/` and a project's `.claude/skills/`.
A blocklist that names only that entry doesn't count as an active restriction, so it doesn't [stop plugins whose marketplace Claude Code can't find](#restrict-what-users-can-install) from loading.
### Allow the official marketplace and your own
Most organizations allow the official marketplace and their own, and register both so every machine has them. This managed settings policy allows both marketplaces, registers both, force-enables two plugins, and rejects `--plugin-dir`:
```json theme={null}
{
"strictKnownMarketplaces": [
{ "source": "github", "repo": "anthropics/claude-plugins-official" },
{ "source": "github", "repo": "your-org/*" },
{ "source": "skills-dir" }
],
"extraKnownMarketplaces": {
"claude-plugins-official": {
"source": { "source": "github", "repo": "anthropics/claude-plugins-official" }
},
"your-marketplace": {
"source": { "source": "github", "repo": "your-org/your-marketplace" }
}
},
"enabledPlugins": {
"code-formatter@your-marketplace": true,
"deploy-helper@your-marketplace": true
},
"disableSideloadFlags": true
}
```
On a machine with this policy, adding any source outside the list, for example `/plugin marketplace add https://example.com/other-marketplace.git`, fails with a message containing `is blocked by enterprise policy` followed by the allowed sources. `claude --plugin-dir ./x` exits with a message naming `disableSideloadFlags`.
The `{ "source": "skills-dir" }` entry keeps [skills-directory plugins](#keep-skills-directory-plugins-loading) loading under this allowlist. Remove that entry and they stop loading.
Register both marketplaces with explicit `extraKnownMarketplaces` entries, as this policy does, rather than relying on the allowlist or on the official marketplace registering itself:
Cut at 300 lines. The page has the rest.
plugins/overview New page · 122 lines, new page
# Plugins overview ## Understand what a plugin is ### Decide whether you need a plugin ### What an enabled plugin adds to your sessions ## Get plugins from a marketplace ### Make an installed plugin available in your session ## Tell Anthropic's marketplaces from third-party ones ## Understand install scopes ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Plugins overview > Understand what a Claude Code plugin is, when you need one instead of a standalone skill or MCP server, and which page to read to install or create one. A Claude Code plugin is a directory of skills, agents, hooks, MCP servers, or other components that Claude Code installs and loads as one unit. Most plugins come from a marketplace, which is a catalog that lists plugins and where to fetch each one. You can also load a plugin from a folder someone gives you, or [build your own](/docs/en/plugins/create). <Note> If you use claude.ai chat or Cowork and not Claude Code, see [Plugins on claude.ai and in Cowork](https://claude.com/docs/plugins/overview). </Note> To try a plugin now, run `/plugin` in a Claude Code terminal session and install one from the **Discover** tab, which lists the plugins from Anthropic's official marketplace and any marketplace you've added. From there: * [Install and manage plugins](/docs/en/plugins/install): the full install steps, scopes, and other surfaces * [Create a plugin](/docs/en/plugins/create): build your own * [Decide whether you need a plugin](#decide-whether-you-need-a-plugin): whether a plugin is the right tool for what you want ## Understand what a plugin is A plugin is a directory of components, usually with a manifest. The manifest, a JSON file at `.claude-plugin/plugin.json`, gives the plugin its name and can add a version, a description, and other [metadata](/docs/en/plugins/manifest-reference). The components are what the plugin adds to Claude Code, such as: * [**Skills**](/docs/en/plugins/components#skills): `SKILL.md` instructions Claude loads when relevant, and that you can also run as a command * [**Agents**](/docs/en/plugins/components#agents): subagent definitions Claude can delegate to * [**Hooks**](/docs/en/plugins/components#hooks): commands Claude Code runs at points in its lifecycle, such as after every edit * [**MCP servers**](/docs/en/plugins/components#mcp-servers): tool servers Claude Code connects to while the plugin is enabled This diagram shows a plugin named `my-plugin` that holds one of each of those components, and what you get from each file once the plugin loads. <img src="https://mintcdn.com/claude-code/2Q_GtOEovg5qaBem/images/plugin-directory.svg?fit=max&auto=format&n=2Q_GtOEovg5qaBem&q=85&s=f623b64e82713b830e48174f0a922888" className="dark:hidden" alt="Diagram in two columns joined by five straight arrows. Left, the directory of a plugin named my-plugin, holding a manifest at .claude-plugin/plugin.json, skills/review/SKILL.md, agents/reviewer.md, hooks/hooks.json, .mcp.json, and other components. Right, what each file gives you in your session: the manifest sets the plugin name, my-plugin; the skill runs as /my-plugin:review; the agent file is a subagent Claude can delegate to; the hooks file holds hooks that run on lifecycle events; and .mcp.json adds an MCP server that gives Claude tools." width="760" height="336" data-path="images/plugin-directory.svg" /> <img src="https://mintcdn.com/claude-code/2Q_GtOEovg5qaBem/images/plugin-directory-dark.svg?fit=max&auto=format&n=2Q_GtOEovg5qaBem&q=85&s=17ee2bd45b63154fcc148ae1d1f736d8" className="hidden dark:block" alt="Diagram in two columns joined by five straight arrows. Left, the directory of a plugin named my-plugin, holding a manifest at .claude-plugin/plugin.json, skills/review/SKILL.md, agents/reviewer.md, hooks/hooks.json, .mcp.json, and other components. Right, what each file gives you in your session: the manifest sets the plugin name, my-plugin; the skill runs as /my-plugin:review; the agent file is a subagent Claude can delegate to; the hooks file holds hooks that run on lifecycle events; and .mcp.json adds an MCP server that gives Claude tools." width="760" height="336" data-path="images/plugin-directory-dark.svg" /> For every component type a plugin can hold, with an example of each, see [Plugin components](/docs/en/plugins/components). To see where each piece is located in a plugin's directory, use the [plugin explorer](/docs/en/plugins/components#explore-the-plugin-directory) on that page. ### Decide whether you need a plugin Skills, subagents, hooks, and MCP servers all work on their own, without a plugin. A skill you save in `~/.claude/skills/`, for example, is available in every project on your machine. To set one up on its own, see [Skills](/docs/en/skills), [Subagents](/docs/en/sub-agents), [Hooks](/docs/en/hooks-guide), or [MCP](/docs/en/mcp). Use a plugin when you want several skills, subagents, hooks, or MCP servers packaged as one unit. Install one to get a setup someone else built, with one command and updates from its marketplace. Make one to give your own setup to teammates, install it in many projects, or publish versioned releases. ### What an enabled plugin adds to your sessions An enabled plugin is part of every session, not only the sessions where you use it. That has a few consequences worth knowing before you install one: * **Context and usage**: for each skill, agent, and command that [Claude can invoke on its own](/docs/en/skills#control-who-invokes-a-skill), the name and description are in Claude's context on every turn so that Claude knows it exists. Those tokens count toward your usage and leave less room in the [context window](/docs/en/context-window) even in sessions where nothing from the plugin runs. The full text of a skill or agent loads only when it's used. What the plugin's MCP servers add per turn follows [MCP tool search](/docs/en/mcp#scale-with-mcp-tool-search). * **Processes**: MCP servers the plugin defines run alongside each session where it's enabled, and its hooks fire at their events. * **Permissions**: what the plugin runs, it runs as you. See [Plugin security and trust](/docs/en/plugins/security) for what to review first. You can check a plugin's footprint at each stage: * **Before you install**: open the plugin from the **Marketplaces** tab in `/plugin`. Plugins in Anthropic's official marketplace show a **Context cost** estimate there. * **After you install**: [Measure what a plugin costs](/docs/en/plugins/measure#measure-what-a-plugin-costs) shows how to read a plugin's footprint, and the **Installed** tab's **Not used recently** group lists plugins you could turn off. * **To stop it without uninstalling**: disable the plugin with `/plugin` or, in your shell, `claude plugin disable`. See [Manage installed plugins](/docs/en/plugins/install#manage-installed-plugins). ## Get plugins from a marketplace A marketplace is a repository or directory with a `.claude-plugin/marketplace.json` file that lists plugins and where to fetch each one. It's a catalog, not a hosted store. You add a marketplace once, then install plugins from it by name, such as `commit-commands@claude-plugins-official`. <Note> A plugin marketplace isn't [Claude Marketplace](https://claude.com/marketplace). Claude Marketplace is the website at claude.com/marketplace where you browse plugins, connectors, partner products, and service partners. It isn't a marketplace you add with `/plugin marketplace add`. </Note> Claude Code adds Anthropic's official marketplace the first time you start an interactive terminal session, unless a [managed policy](/docs/en/plugins/org#allow-the-official-marketplace-and-your-own) blocks it. Claude Code adds no other marketplace on its own, including Anthropic's community and demo marketplaces. To distinguish the three Anthropic marketplaces, read [Anthropic's marketplaces](/docs/en/plugins/anthropic-marketplaces). To see what the official one lists, open the **Discover** tab of `/plugin` in a session or browse [Claude Marketplace](https://claude.com/marketplace/plugins). This diagram shows the path from a marketplace to your session. A marketplace lists a plugin, you install that plugin, and Claude Code loads its components. <img src="https://mintcdn.com/claude-code/2Q_GtOEovg5qaBem/images/plugins-model.svg?fit=max&auto=format&n=2Q_GtOEovg5qaBem&q=85&s=4196344954b7c2e27fc0bd6a9a1113a1" className="dark:hidden" alt="Diagram of the marketplace path in three boxes, left to right. A marketplace, a catalog of plugins, lists a plugin. The plugin is one directory installed as a unit, holding skills, agents, hooks, MCP servers, and other components. You install the plugin into Claude Code, which loads its components." width="760" height="252" data-path="images/plugins-model.svg" /> <img src="https://mintcdn.com/claude-code/2Q_GtOEovg5qaBem/images/plugins-model-dark.svg?fit=max&auto=format&n=2Q_GtOEovg5qaBem&q=85&s=f6cdefe1fc05daf3b253d26e9f3f70f6" className="hidden dark:block" alt="Diagram of the marketplace path in three boxes, left to right. A marketplace, a catalog of plugins, lists a plugin. The plugin is one directory installed as a unit, holding skills, agents, hooks, MCP servers, and other components. You install the plugin into Claude Code, which loads its components." width="760" height="252" data-path="images/plugins-model-dark.svg" /> [Install and manage plugins](/docs/en/plugins/install#install-a-plugin) has the install steps for each place you run Claude Code. While you're developing a plugin, you don't need a marketplace: load it straight from its folder with `--plugin-dir`, as [Develop without a marketplace](/docs/en/plugins/create#develop-without-a-marketplace) shows. ### Make an installed plugin available in your session Before a plugin you installed gives you a skill you can run, it has to be present at each of these layers: * **Settings**: your settings list the marketplaces you've added and the plugins that are enabled. * **Disk**: `~/.claude/plugins/` holds what Claude Code has fetched and installed. * **Session**: plugins load at startup, or when you [reload plugins](/docs/en/plugins/loading#check-which-stage-a-plugin-reached). Read [Plugin loading reference](/docs/en/plugins/loading) for the rules at each layer, including which settings file takes precedence and where the files are on disk. ## Tell Anthropic's marketplaces from third-party ones A marketplace's name places it in one of three tiers. Claude Code accepts the official and community names only for marketplaces sourced from `github.com/anthropics/` repositories: * **Official**: marketplaces with one of Anthropic's [official marketplace names](/docs/en/plugins/security#official-marketplace-names), including `claude-plugins-official` and the demo marketplace `claude-code-plugins`. * **Community**: marketplaces with one of Anthropic's community names, such as `claude-community`. [Identify Anthropic's marketplaces by name](/docs/en/plugins/security#marketplace-tiers) lists them. * **Third-party**: every other marketplace. A marketplace your coworker or your organization publishes is third-party. Whatever the tier, a plugin you install can run code with your user privileges. Read [Plugin security and trust](/docs/en/plugins/security) for how to review a plugin before you install it. Through [managed settings](/docs/en/settings#settings-files), an organization can allowlist or block marketplaces, force-install plugins, and turn off session-only loading. Read [Manage plugins for your organization](/docs/en/plugins/org) for those controls. ## Understand install scopes When you install a plugin, you pick a scope, and the scope decides who the plugin is enabled for: * **User scope**: enabled for you in every project on this computer * **Project scope**: enabled for everyone who works in this repository, through the committed `.claude/settings.json`. Each collaborator still [installs it on their own machine](/docs/en/plugins/loading#enabled-in-project-settings-but-not-installed) * **Local scope**: enabled for you in this repository only A plugin you install at user scope in the terminal, the desktop app's local sessions, or the VS Code extension is available in the other two on that computer, because all three read the same settings files. See [Choose an install scope](/docs/en/plugins/install#choose-an-install-scope) for how to pick one. A cloud session, including one in the browser at claude.ai/code, doesn't load the plugins in your local settings. For install steps in the terminal, VS Code, and the desktop app, and for what a cloud session loads, see [Install a plugin](/docs/en/plugins/install#install-a-plugin). <Note> The same plugin format also installs on claude.ai and in Cowork, where a different set of components loads. For those surfaces, see [Plugins on claude.ai and in Cowork](https://claude.com/docs/plugins/overview) on claude.com. </Note> ## Next steps Most people start by installing a plugin from Anthropic's official marketplace, which Claude Code adds the first time you start an interactive terminal session. Run `/plugin` in a terminal session to browse it, or follow [Install and manage plugins](/docs/en/plugins/install), which also covers the desktop app and VS Code. To see what's in that marketplace before you open Claude Code, browse [Claude Marketplace](https://claude.com/marketplace/plugins) on the web. To build your own, [Create a plugin](/docs/en/plugins/create) starts with an empty directory and ends with a working plugin. Once you've installed or built a plugin, these pages cover what comes next: * **Share what you built**: [Publish and distribute a plugin](/docs/en/plugins/publish) * **Check whether it works and is used**: [Test plugins with evals](/docs/en/plugin-evals) and [Measure plugin cost and usage](/docs/en/plugins/measure) * **Run a marketplace for your team**: [Create a marketplace](/docs/en/plugins/create-marketplace), then [Host and maintain a marketplace](/docs/en/plugins/host-marketplace) * **Set plugin policy for an organization**: [Manage plugins for your organization](/docs/en/plugins/org) * **Fix a problem**: [Troubleshoot plugins](/docs/en/plugins/troubleshooting)
plugins/publish New page · 174 lines, new page
# Publish and distribute a plugin ## Choose how to distribute ## Prepare your plugin for release ## Share a plugin without a marketplace ### Ship a plugin with your own tool ## Publish through your own marketplace ### Add the marketplace file to your repository ### Control who can install ### Tell users how to install ### Ship updates to users ## Submit to the community marketplace ## Ship updates, renames, and removals ### Release a new version ### Tag a release ### Rename or remove a plugin ## Declare dependencies ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Publish and distribute a plugin
> Publish a Claude Code plugin through your own marketplace or Anthropic's community marketplace, with a pre-release checklist and how users get updates.
Publishing a Claude Code plugin means listing it in a marketplace, a JSON catalog that lists plugins and where to fetch each one, so that other people can install it by name and receive your updates. You can run your own marketplace or submit your plugin to Anthropic's community marketplace. To share a plugin without publishing it, send people the plugin's directory or a `.zip` of it to load themselves.
This page is for the author of a working plugin who is ready to share it.
<Note>
These cases are covered on other pages:
* **Your plugin isn't finished yet**: start with [Create a plugin](/docs/en/plugins/create)
* **You maintain a CLI or SDK with a plugin in an official marketplace**: see [Recommend your plugin from your CLI](/docs/en/plugins/cli-hints)
</Note>
Start with [Choose how to distribute](#choose-how-to-distribute) to compare the distribution options. If you already know your route, go to [Prepare your plugin for release](#prepare-your-plugin-for-release), then follow your route's section for what to tell your users and how they receive your updates.
## Choose how to distribute
Choose a distribution option based on who needs to install the plugin:
| Route | Who can install | What you need | Do users get your updates automatically? |
| :------------------------------------------------------------------------ | :---------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- | :--------------------------------------- |
| [No marketplace](#share-a-plugin-without-a-marketplace) | The people you send the plugin folder or a `.zip` of it | The plugin's folder | None. They load the copy you sent |
| [Your own marketplace](#publish-through-your-own-marketplace) | Anyone who can reach the repository, which can be a private one your team can clone | A git repository or other host with a `.claude-plugin/marketplace.json` that lists your plugin | Off |
| [Anthropic's community marketplace](#submit-to-the-community-marketplace) | Anyone who adds `anthropics/claude-plugins-community` | A submission through the plugin directory submission form | Off |
Auto-update is a per-marketplace setting on the user's side that fetches new versions in the background.
## Prepare your plugin for release
The name, the version, validation, and an install from a marketplace decide whether a release works for the people who install it. Check them before the first release and again before each later one.
<Steps>
<Step title="Choose a permanent name">
Users install, enable, and configure your plugin by `name@marketplace`, so a renamed plugin is a different plugin to every existing install. Choose a kebab-case name such as `deploy-helper`, because `claude plugin validate` warns on other forms, and treat it as permanent. Set `displayName` in `plugin.json` for the label users see.
</Step>
<Step title="Decide how you'll version">
If you set `version` in `plugin.json` and later push commits without changing it, `claude plugin update` prints `<name> is already at the latest version (1.0.0).` and users keep the old copy. Either increment `version` on every release, or omit it in a git-hosted marketplace so Claude Code uses the commit SHA instead. See [Versions and updates](/docs/en/plugins/loading#versions-and-updates).
</Step>
<Step title="Validate">
In your shell, run `claude plugin validate --strict ./your-plugin`. A clean run prints `✔ Validation passed`.
* **In CI**: keep `--strict`, which also fails the run with exit code 1 on warnings such as an unknown manifest field or a missing `version`. Drop `--strict` if you chose to omit `version` in the previous step.
* **Paths**: validation reports component paths that don't start with `./`. Inside hook commands and MCP server configs, refer to files as `${CLAUDE_PLUGIN_ROOT}/...`. See [path rules](/docs/en/plugins/manifest-reference#path-rules).
</Step>
<Step title="Install it from a local marketplace">
In your shell, add a local marketplace that lists the plugin with `claude plugin marketplace add ./path-to-marketplace`, install the plugin from it, and start a session to confirm it loads.
* For the smallest marketplace that works, see [Create a marketplace](/docs/en/plugins/create-marketplace).
* To know whether an install loads your source directory or a cached copy, see [In-place and copied plugins](/docs/en/plugins/loading#in-place-and-copied-plugins).
</Step>
<Step title="Fill in the metadata users see">
Set `description`, `author`, `homepage`, and `repository` in `plugin.json`, and add a `README.md` at the plugin root. `homepage` must parse as a URL. The [manifest reference](/docs/en/plugins/manifest-reference#fields) lists every field.
</Step>
<Step title="Run your eval suite">
If you have an eval suite, run `claude plugin eval` in your shell. It runs the plugin's test cases and scores the results, which catches regressions when you change the plugin. See [Test plugins with evals](/docs/en/plugin-evals).
</Step>
</Steps>
## Share a plugin without a marketplace
If the plugin is in a git repository, people can clone it and load the checkout, or start Claude Code from their shell with `--plugin-url` pointed at a `.zip` you attach to a release. To get your next version they pull or download again. If it isn't in a repository, send them the directory or a `.zip` of it. They load it in one of two ways:
* **For one session**: they start Claude Code from their shell with `claude --plugin-dir ./deploy-helper`, where the path is the clone, the unzipped folder, or the `.zip` itself. See [Flags that load a plugin for one session](/docs/en/plugins/cli-reference#flags-that-load-a-plugin-for-one-session).
* **For every session**: they move the plugin directory, with its `.claude-plugin/plugin.json`, under `~/.claude/skills/` so Claude Code [loads it in every session](/docs/en/plugins/loading#find-where-a-plugin-came-from).
Adding a `.claude-plugin/marketplace.json` to that same repository is what lets people install by name and update with a command; see [Publish through your own marketplace](#publish-through-your-own-marketplace).
### Ship a plugin with your own tool
If you maintain a CLI or SDK, publish the plugin in a marketplace and have your installer or post-install message run or print the two commands a user needs: `claude plugin marketplace add <source>`, then `claude plugin install <name>@<marketplace>`. For in-session discovery when someone uses your tool, see [Recommend your plugin from your CLI](/docs/en/plugins/cli-hints).
## Publish through your own marketplace
Your own marketplace is a `.claude-plugin/marketplace.json` file that lists your plugin, added to a git repository. Once the file is in the repository, the plugin is published, with no submission form. You can keep the file in the plugin's own repository or in a separate one.
### Add the marketplace file to your repository
To publish from the plugin's own repository, save the marketplace file beside `plugin.json` in `.claude-plugin/`, with one entry whose `source` is `"./"`, the repository root. Give the entry the same `name` as `plugin.json`, per [Keep the entry name and the manifest name the same](/docs/en/plugins/create-marketplace#keep-the-entry-name-and-the-manifest-name-the-same):
```json .claude-plugin/marketplace.json theme={null}
{
"name": "your-marketplace",
"owner": { "name": "Your Name" },
"plugins": [
{ "name": "deploy-helper", "source": "./" }
]
}
```
In your shell, run `claude plugin validate .` in the repository to check the file before you push.
[Create a marketplace](/docs/en/plugins/create-marketplace) covers the layout with several plugins in one repository.
### Control who can install
Anyone who can clone the repository can install from it, so if the repository is private, the marketplace is private too. For hosts other than a git repository, see [Host a marketplace](/docs/en/plugins/host-marketplace). To reach everyone at a company, including people who don't use git, see [Roll out to a whole company](/docs/en/plugins/host-marketplace#roll-out-to-a-whole-company).
### Tell users how to install
Tell your users to add the marketplace and then install the plugin from their shell, replacing the source and names with yours:
* Add the marketplace once: `claude plugin marketplace add your-org/your-marketplace`, where the argument is a GitHub `owner/repo` shorthand, a URL, or a path
* Install the plugin: `claude plugin install deploy-helper@your-marketplace`
* Or do both from inside a session: `/plugin install deploy-helper --marketplace your-org/your-marketplace`. Requires Claude Code v2.1.275 or later. See [Add a marketplace and install in one command](/docs/en/plugins/install#add-a-marketplace-and-install-in-one-command)
### Ship updates to users
Users receive a release when they ask for it or when auto-update is on for your marketplace:
* **On request**: `claude plugin update deploy-helper@your-marketplace` in the user's shell refreshes the marketplace and installs the new copy when your plugin's version has changed
* **Auto-update**: off by default for your marketplace. See [Turn on auto-update](/docs/en/plugins/host-marketplace#turn-on-auto-update). Once on, it does the same as `claude plugin update` on a delay after the session starts
[Install plugins](/docs/en/plugins/install) covers the user-side commands, and [when auto-update runs](/docs/en/plugins/loading#when-auto-update-runs) covers the timing.
## Submit to the community marketplace
Anthropic's community marketplace, `claude-community`, is the public marketplace that lists plugins submitted through the plugin directory submission form.
Users add the community marketplace in a Claude Code session with `/plugin marketplace add anthropics/claude-plugins-community` and install from it as `@claude-community`.
For how the community marketplace differs from the official marketplace, see [Anthropic's marketplaces](/docs/en/plugins/anthropic-marketplaces).
To submit your plugin to the community marketplace, use one of the in-app forms:
* **claude.ai**: [claude.ai/admin-settings/directory/submissions/plugins/new](https://claude.ai/admin-settings/directory/submissions/plugins/new)
* **Console**: [platform.claude.com/plugins/submit](https://platform.claude.com/plugins/submit)
The claude.ai form requires a Team or Enterprise organization and the Directory permission, which Owners hold by default. Individual authors who aren't part of a Team or Enterprise organization can use the Console form instead.
In your shell, run `claude plugin validate ./your-plugin` locally before you submit, replacing `./your-plugin` with the path to your plugin directory. When validation passes, Claude Code prints `✔ Validation passed`, or `✔ Validation passed with warnings` if there are warnings. Warnings don't fail validation; add `--strict` to treat them as errors.
Listed plugins appear in the [`anthropics/claude-plugins-community`](https://github.com/anthropics/claude-plugins-community) catalog, in nearly every case pinned to a specific commit SHA.
There can be a delay between submitting and your plugin appearing in `marketplace.json`. To check whether your plugin is installable yet, search for its name in the [community catalog](https://github.com/anthropics/claude-plugins-community/blob/main/.claude-plugin/marketplace.json).
The official marketplace, `claude-plugins-official`, doesn't take submissions through these forms. If you work with an Anthropic partner contact, ask them about an official-marketplace listing.
## Ship updates, renames, and removals
### Release a new version
If you publish through your own marketplace and your `plugin.json` sets `version`, increment it and push. Users who run `claude plugin update` or have auto-update on then receive the new version, as described under [Ship updates to users](#ship-updates-to-users).
### Tag a release
Tag the release in git when other plugins declare a version range on yours, because those ranges resolve against tags. Otherwise you don't need a tag.
To tag, run `claude plugin tag` in your shell from the plugin directory. It creates a `{name}--v{version}` tag. Add `--push` to send the tag to `origin`. The [`plugin tag` reference](/docs/en/plugins/cli-reference#plugin-tag) lists its flags.
### Rename or remove a plugin
Never change a published plugin's `name`. After a rename, users who already installed it lose the plugin, because their install is recorded under the old name. A `renames` entry in your marketplace file migrates them instead. Change `displayName` when you want a different label.
If a rename is unavoidable, use the marketplace file's `renames` map so that existing installs migrate instead of failing with [`Plugin "<name>" not found in marketplace`](/docs/en/plugins/troubleshooting#plugin-not-found-in-marketplace). To remove a plugin from the marketplace, or for the full `renames` details, see [Rename or remove a plugin](/docs/en/plugins/host-marketplace#rename-or-remove-a-plugin) on the hosting page. The [marketplace reference](/docs/en/plugins/marketplace-reference#top-level-fields) has the field.
## Declare dependencies
If your plugin needs another plugin from the same marketplace to be enabled, list it in the `dependencies` array of `plugin.json`. Each entry is a bare name or an object with a semver `version` range. When a user installs your plugin, Claude Code installs and enables the dependency too.
[Plugin dependencies](/docs/en/plugins/dependencies) covers the range syntax, cross-marketplace dependencies, and how users prune dependencies they no longer need.
## Next steps
* [Host and maintain a marketplace](/docs/en/plugins/host-marketplace): release new versions and keep users up to date
* [Plugin dependencies](/docs/en/plugins/dependencies): declare and version the plugins yours relies on
* [Recommend your plugin from your CLI](/docs/en/plugins/cli-hints): prompt Claude Code users of your CLI to install the plugin
* [Measure plugin cost and usage](/docs/en/plugins/measure): see what your plugin costs in context and whether people use it
plugins/relevance New page · 219 lines, new page
# Recommend plugins for your org ## Understand how plugin relevance works ## Add relevance to a plugin entry ## Field reference ### `relevance` ### `relevance.signals` #### Working directory matching #### Command name matching #### Manifest dependency matching ## Validate your marketplace ## Enable suggestions in managed settings ## Preview what the user sees ## See also
A whole new page. There's nothing to diff it against, so here is what it says.
# Recommend plugins for your org
> Add a relevance block to marketplace plugin entries so Claude Code suggests them when a user's work matches, and allowlist the marketplace in managed settings.
Claude Code can suggest installing a plugin from your organization's marketplace when a user's session matches signals you define for that plugin. Signals include the working directory, files Claude has read, and commands Claude has run. You define them by adding a `relevance` block to the plugin's entry in `marketplace.json`.
A marketplace operator writes the `relevance` entries. An administrator then allowlists the marketplace in managed settings. Users see no suggestions from a marketplace until it's allowlisted.
<Note>
These cases are covered on other pages:
* **You want to install plugins**: see [Install and manage plugins](/docs/en/plugins/install)
* **You want to turn suggestions off**: see [Understand how plugin relevance works](#understand-how-plugin-relevance-works)
</Note>
Start with the sections for your role:
* **Marketplace operators**: read [how suggestions work](#understand-how-plugin-relevance-works), then [add relevance to a plugin entry](#add-relevance-to-a-plugin-entry) and [validate your marketplace](#validate-your-marketplace)
* **Administrators**: [enable suggestions in managed settings](#enable-suggestions-in-managed-settings)
## Understand how plugin relevance works
Each plugin entry in `marketplace.json` can include a `relevance` object. The object names a topic and one or more signals. A signal is a pattern that Claude Code tests against the current session, such as the working directory or files Claude has read.
Signal matching happens locally on the user's machine and adds no network traffic. Claude Code doesn't report which signals matched or their values to Anthropic or to the marketplace operator.
When a signal matches and the plugin isn't already installed, Claude Code suggests the plugin in these places:
* **Spinner tip**: a message with the `/plugin install` command appears below the spinner while Claude is responding.
* **Session-start notification**: if a `cwd` signal matches the working directory, a one-line notification appears before the user sends a first message.
* **`/plugin` Discover tab**: the plugin is pinned to the top of the Discover list.
[Preview what the user sees](#preview-what-the-user-sees) shows the exact text of each and how often they repeat.
Claude Code never installs the plugin automatically. The user always confirms.
The spinner tip and the session-start notification both stop appearing when the user or project sets [`spinnerTipsEnabled`](/docs/en/settings-reference#spinnertipsenabled) to `false`, or when a [`spinnerTipsOverride`](/docs/en/settings-reference#spinnertipsoverride) with `excludeDefault` replaces the built-in tips. The Discover-tab pin isn't affected by either setting.
## Add relevance to a plugin entry
Add a `relevance` object to the plugin's entry in your `marketplace.json`. The following example declares that the `terraform-helpers` plugin is relevant when Claude reads a `.tf` file or runs `terraform`:
```json theme={null}
{
"name": "your-marketplace",
"owner": { "name": "Your Org" },
"plugins": [
{
"name": "terraform-helpers",
"source": "./plugins/terraform-helpers",
"description": "Your organization's Terraform conventions and helpers",
"relevance": {
"topic": "Terraform",
"signals": {
"cli": ["terraform"],
"filesRead": ["**/*.tf"]
}
}
}
]
}
```
While none of its signals match, the plugin keeps its normal position in the Discover list and doesn't appear as a spinner tip.
To check the block before publishing, [validate your marketplace](#validate-your-marketplace).
## Field reference
The `relevance` object and its nested `signals` object accept the fields in the following tables.
Older clients still load a marketplace that uses `relevance` fields they don't recognize, because unknown fields under `relevance` and `relevance.signals` are ignored at load time. A recognized field whose value exceeds its limit in the [field reference](#field-reference) invalidates the whole plugin entry, and users can't install that plugin from the marketplace until you fix it; `claude plugin validate` reports the same limits.
### `relevance`
| Field | Type | Description |
| :-------- | :----- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `topic` | string | Optional. The phrase that fills "Working with *topic*?" in the spinner tip. Defaults to the plugin name with each hyphen segment capitalized. Maximum 64 characters. |
| `signals` | object | Matchers that determine when the plugin is relevant. Claude Code suggests the plugin only if at least one signal is set. See [`relevance.signals`](#relevance-signals). |
The `topic` is often the product name, for example `Terraform`. Use a domain such as `design` when the plugin name doesn't sound natural as a topic.
### `relevance.signals`
The `signals` object accepts the following fields.
| Field | Type | Description | Limit |
| :------------- | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------- |
| `cwd` | array of strings | Glob patterns matched against the session's working directory. See [working directory matching](#working-directory-matching). | 10 patterns of 256 characters each |
| `cli` | array of strings | Command names from shell commands Claude has run this session, for example `["terraform"]`. Exact match. See [command name matching](#command-name-matching). | 10 entries of 64 characters each |
| `hosts` | array of strings | Hostnames seen in `http://` or `https://` URLs in Bash commands this session, for example `["registry.terraform.io"]`. Bare lowercase hostname only: no scheme, port, or path. Exact case-insensitive match. | 20 entries of 128 characters each |
| `filesRead` | array of strings | Glob patterns matched against the paths of files Claude has read this session, for example `["**/*.tf"]`. Forward-slash normalized and case-insensitive. | 10 patterns of 256 characters each |
| `manifestDeps` | array of objects | Dependencies declared in package manifests Claude has read this session. Each entry is `{ "file": "...", "pattern": "..." }`, where both values are regular expressions. See [manifest dependency matching](#manifest-dependency-matching). | 10 entries, each value at most 256 characters. Manifest files larger than 512 KB are skipped |
The `filesRead` and `manifestDeps` signals also match against files Claude has written or edited this session and against the project's auto-loaded `CLAUDE.md` memory files.
#### Working directory matching
`cwd` is the only signal that can match at session start, before the user sends a first message.
Claude Code matches each `cwd` pattern as follows:
* The pattern is matched against the working directory as an absolute path. When the session is inside a git repository, it's also matched against the working directory's path relative to the repository root.
* Matching is forward-slash normalized and case-insensitive.
* Every pattern matches the directory itself and everything under it, so `infra`, `infra/`, and `infra/**` behave identically.
#### Command name matching
Claude Code records one command name for each shell command Claude runs: the first token after any leading environment variable assignments and `sudo`. Compound commands contribute only their leading command, so `cd infra && terraform plan` records `cd`, not `terraform`.
#### Manifest dependency matching
Each `manifestDeps` entry pairs two JavaScript `RegExp` source strings:
* `file`: matched case-insensitively against the manifest file's path. The path is typically absolute, so anchor the pattern at the end rather than the start. Paths aren't separator-normalized for this signal, so Windows paths use backslashes.
* `pattern`: matched case-sensitively against that file's contents.
The following example uses `manifestDeps` to suggest your plugin once Claude has read a `package.json` that depends on your SDK's npm package, named `your-sdk` here.
```json theme={null}
{
"name": "your-plugin",
"source": "./plugins/your-plugin",
"relevance": {
"signals": {
"manifestDeps": [
{
"file": "[/\\\\]package\\.json$",
"pattern": "\"your-sdk\"\\s*:"
}
]
}
}
}
```
In this example, the `file` pattern uses `[/\\\\]` so it matches both forward-slash and backslash path separators, and `\\.` so the dot is literal. In JSON, each backslash in the regular expression is written twice.
## Validate your marketplace
In your shell, run `claude plugin validate` against your marketplace directory to check the `relevance` block before publishing:
```bash theme={null}
claude plugin validate ./my-marketplace
```
The validator reports errors and warnings on the `relevance` block, including these:
* Reports unknown keys under `relevance` and `relevance.signals` as warnings
* Flags a `relevance` value that isn't an object
* Rejects a `signals.hosts` entry that includes a scheme, port, or path
Each finding prints with the path of the field it concerns, and the output ends with `Validation passed`, `Validation passed with warnings`, or `Validation failed`.
## Enable suggestions in managed settings
Users see no suggestions from a marketplace until an administrator allowlists it in [managed settings](/docs/en/plugins/org), even when its `marketplace.json` declares `relevance`.
To allowlist a marketplace, edit your managed settings as follows:
* Add the marketplace name to `pluginSuggestionMarketplaces`.
* For any marketplace other than the official Anthropic marketplace, also declare the marketplace source, either as that name's entry in [`extraKnownMarketplaces`](/docs/en/plugins/org#require-a-marketplace-and-its-plugins) or as an entry in [`strictKnownMarketplaces`](/docs/en/plugins/org#allowlist-with-strictknownmarketplaces).
On a machine where the marketplace isn't registered, or is registered under the allowlisted name from a different source, no suggestions from it appear. The source check stops an unrelated source from registering under an allowlisted name to get its plugins suggested across your org.
The following `managed-settings.json` registers an org marketplace from a GitHub repository and enables its suggestions:
```json theme={null}
{
"extraKnownMarketplaces": {
"your-marketplace": {
"source": {
"source": "github",
"repo": "your-org/your-marketplace"
}
}
},
"pluginSuggestionMarketplaces": ["your-marketplace"]
}
```
The official marketplace's name can only register from the official Anthropic source, so it needs no source declaration. For the official marketplace, allowlist the name alone:
```json theme={null}
{
"pluginSuggestionMarketplaces": ["claude-plugins-official"]
}
```
## Preview what the user sees
When a plugin's `relevance` signal matches during a session, the tip below the spinner reads:
```text theme={null}
Working with Terraform? Install the terraform-helpers plugin:
/plugin install terraform-helpers@your-marketplace
```
When a `cwd` signal matches at session start, the one-line notification reads:
```text theme={null}
plugin suggestion: terraform-helpers@your-marketplace · /plugin
```
In the `/plugin` Discover tab, the plugin is pinned above the other results with an annotation that names the matching signal, such as `suggested for this directory` or `suggested for terraform commands`.
Claude Code limits how often it suggests a given plugin:
* The suggestion appears at most once every three sessions across the spinner tip and the session-start notification combined.
* The session-start notification stops appearing once the spinner tip and the notification have shown the plugin a combined total of two times.
* Neither the spinner tip nor the session-start notification repeats once the plugin is installed.
* The Discover tab pins the plugin the first time the user opens the tab while the plugin's signals match. Claude Code records that in `~/.claude.json`, so every later time the user opens `/plugin` on that machine, the plugin appears in normal order.
## See also
* [Host a marketplace](/docs/en/plugins/host-marketplace): run the marketplace that hosts your plugins
* [Marketplace reference](/docs/en/plugins/marketplace-reference#plugin-entries): every field a plugin entry accepts
* [Recommend your plugin from your CLI](/docs/en/plugins/cli-hints): prompt users from your own CLI instead of from Claude Code's session signals
* [Manage plugins for your organization](/docs/en/plugins/org): `extraKnownMarketplaces`, `strictKnownMarketplaces`, and the rest of the plugin policy keys
plugins/security New page · 162 lines, new page
# Plugin security and trust ## Understand what a plugin can do ### Official marketplace names ## Review a plugin before you install ### Remove a plugin you no longer trust ## Recognize when Claude Code refuses or warns ### Trust warning before you install ### Untrusted marketplace sources and failed integrity checks ## Enforce plugin controls for your organization ## Find plugins in telemetry ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Plugin security and trust
> Decide whether to trust a plugin before you install it, from what a plugin can do on your machine to how to review one and remove it.
A Claude Code plugin you install can execute arbitrary code on your machine with your user privileges.
You install a plugin from a marketplace, which is the catalog Claude Code fetches it from. Some marketplace names are [reserved for Anthropic's own marketplaces](#marketplace-tiers), and every other marketplace is third-party. A marketplace's name tells you who publishes the catalog, not what each plugin in it does, so [review a plugin before you install it](#review-a-plugin-before-you-install) whichever marketplace it comes from.
Read this page if you're deciding whether to install a plugin, or if you review tools before your team can use them.
<Note>
These cases are covered on other pages:
* **Claude Code's own security model**: see [Security](/docs/en/security)
* **Restricting or requiring plugins for an organization**: see [Manage plugins for your organization](/docs/en/plugins/org)
* **The `security-guidance` or `claude-security` plugins**: this page isn't about them. See [`security-guidance`](/docs/en/security-guidance) and [`claude-security`](/docs/en/claude-security)
</Note>
Start with [what a plugin can do](#understand-what-a-plugin-can-do) and [which marketplaces are Anthropic's](#marketplace-tiers), then [review the plugin before you install it](#review-a-plugin-before-you-install).
## Understand what a plugin can do
A plugin can carry content that runs code on your machine with your user privileges and content that enters Claude's context as instructions, so [review a plugin before you install it](#review-a-plugin-before-you-install). Here's what an installed plugin can do:
* **Hooks**: a plugin's [hooks](/docs/en/hooks) run as shell commands at points in Claude Code's lifecycle, such as before or after a tool call.
* **MCP and LSP servers**: Claude Code connects to the [MCP servers](/docs/en/mcp) an enabled plugin declares and gives Claude their tools. A stdio MCP server runs as a process that Claude Code starts on your machine. Claude Code also starts the language servers the plugin declares.
* **`bin/` directory**: Claude Code adds each enabled plugin's `bin/` directory to the `PATH` of the Bash tool's shell, so Claude's Bash commands can run any executable there.
* **Skills, commands, and agents**: these enter Claude's context as instructions, so they influence what Claude does with the tools it already has.
* **Updates**: when auto-update is on for the marketplace you installed a plugin from, Claude Code updates that plugin in the background, so the files you reviewed can change on disk. [When auto-update runs](/docs/en/plugins/loading#when-auto-update-runs) has the timing. To turn auto-update on or off per marketplace, see [Keep plugins updated](/docs/en/plugins/install#keep-plugins-updated).
Claude Code's [permission rules](/docs/en/permissions) and [sandbox](/docs/en/sandboxing) cover the tool calls Claude makes, not the code a plugin runs by itself:
* **Hooks and server processes**: command hooks execute shell commands with your full user permissions. Claude Code runs hooks and MCP servers outside the sandbox.
* **Claude's tool calls**: a call to one of the plugin's MCP tools, and a Bash command that runs an executable from the plugin's `bin/`, are tool calls, so your permission rules apply to them.
Installing a plugin also enables it, unless its manifest or marketplace entry sets [`defaultEnabled: false`](/docs/en/plugins/install#choose-an-install-scope) and you haven't enabled it yourself.
To remove a plugin you no longer trust, see [Remove a plugin you no longer trust](#remove-a-plugin-you-no-longer-trust).
<h2 id="marketplace-tiers">
Identify Anthropic's marketplaces by name
</h2>
A marketplace's name places it in one of three tiers: official, community, or third-party. Claude Code accepts the official and community names only for marketplaces sourced from `github.com/anthropics/` repositories, so a third-party marketplace can't present itself as an Anthropic one. A marketplace that a coworker or your organization publishes is third-party.
The table lists which names fall in each tier:
| Tier | Which marketplaces |
| :---------- | :----------------------------------------------------------------------------------------------- |
| Official | The [official marketplace names](#official-marketplace-names), such as `claude-plugins-official` |
| Community | `claude-community`, `claude-plugins-community`, and `healthcare` |
| Third-party | Every other marketplace |
Where the `claude-community` catalog pins a plugin to a commit SHA, which it does for nearly every entry, Claude Code refuses to install a different commit.
### Official marketplace names
These marketplace names make up the official tier:
* `claude-plugins-official`
* `claude-code-marketplace`
* `claude-code-plugins`
* `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`
* `claude-tag-plugins`
For how the official, community, and demo marketplaces differ and where to browse what each one lists, see [Anthropic's marketplaces](/docs/en/plugins/anthropic-marketplaces).
## Review a plugin before you install
Before you install a plugin, look at what it adds and where it comes from.
<Steps>
<Step title="Check the marketplace's source">
In your shell, run `claude plugin marketplace list` to print the source each marketplace was added from, such as a GitHub repository or a directory.
</Step>
<Step title="Read the details pane">
In a Claude Code session, run `/plugin` and select the plugin. The details pane shows a **Will install** section listing the plugin's commands, agents, skills, hooks, and MCP and LSP servers. For a plugin Anthropic has no published component data for, the section shows what the marketplace entry declares, or a note: `Components will be discovered at installation` for a plugin stored inside the marketplace, or `Component summary not available for remote plugin` for one fetched from elsewhere.
</Step>
<Step title="Read the plugin's source">
In the details pane, select **Open homepage** or **View on GitHub** below the install options. If the pane offers neither, open the marketplace repository you found in the first step. Find the plugin's directory there. The **Will install** section shows that a hook exists but not what it runs, so read these files in the plugin's directory:
* **`hooks/hooks.json`**: the command each hook runs
* **`.mcp.json`**: each server's command or URL
* **`bin/`**: every file in the directory
</Step>
<Step title="List what the plugin contains">
Clone the repository that holds the plugin's directory, then run `claude --plugin-dir <plugin directory> plugin details <plugin name>` in your shell to see what Claude Code finds in it. The command reads the plugin's files without starting a session and prints a `Component inventory` listing the plugin's skills and commands, agents, hooks with each hook's event, and MCP and LSP servers.
</Step>
</Steps>
After you install a plugin, run `claude plugin details <plugin name>` in your shell to print the same `Component inventory` for the installed copy under `~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/`.
### Remove a plugin you no longer trust
In your shell, run [`claude plugin uninstall <plugin>`](/docs/en/plugins/cli-reference#plugin-uninstall) with the `--scope` you installed it at. Then check what the uninstall removed and what it left:
* **Persistent data**: when that was the last scope the plugin was installed at, uninstalling also deletes the plugin's persistent data directory, unless you pass `--keep-data`.
* **Cached files**: the plugin's files stay on disk under `~/.claude/plugins/cache/` for 14 days before a [background sweep removes them](/docs/en/plugins/loading#cleanup-of-previous-versions). After you uninstall your last plugin, orphaned directories stay until you install another. To delete the files now, remove the plugin's directory under `~/.claude/plugins/cache/<marketplace>/<plugin>/` yourself.
* **The marketplace**: if you don't trust the marketplace's owner either, [remove the marketplace](/docs/en/plugins/install#manage-marketplaces) too, which uninstalls every plugin you installed from it.
## Recognize when Claude Code refuses or warns
The details pane you open from the **Discover** or **Marketplaces** tab in `/plugin` shows the same trust warning for each plugin. Claude Code refuses instead of warning in cases such as those under [Untrusted marketplace sources and failed integrity checks](#untrusted-marketplace-sources-and-failed-integrity-checks).
### Trust warning before you install
The warning reads the same whatever marketplace the plugin comes from:
```text theme={null}
Make sure you trust a plugin before installing, updating, or using it. Anthropic does not control what MCP servers, files, or other software are included in plugins and cannot verify that they will work as intended or that they won't change. See each plugin's homepage for more information.
```
If your organization sets `pluginTrustMessage` in [managed settings](/docs/en/plugins/org), Claude Code appends that text to the warning.
### Untrusted marketplace sources and failed integrity checks
Claude Code refuses to load a marketplace or to install a plugin in these cases, each with its own error message:
* **Untrusted marketplace source**: when a marketplace uses an official or community name but its source is outside `github.com/anthropics/`, Claude Code stops loading the marketplace and the plugins you installed from it. The error is [Marketplace is registered from an untrusted source](/docs/en/errors#marketplace-is-registered-from-an-untrusted-source).
* **Archive integrity**: when a marketplace entry pins an [`archive` source](/docs/en/plugins/marketplace-reference#archive-plugin-source) to a `sha256` digest and the downloaded file's digest doesn't match it, Claude Code refuses the install. The error is [Plugin archive integrity check failed](/docs/en/errors#plugin-archive-integrity-check-failed).
The `sha256` pin is separate from the community catalog's commit SHA pin, which selects the git commit to check out.
## Enforce plugin controls for your organization
With [managed settings](/docs/en/plugins/org), an administrator can enforce these plugin controls:
* Allowlist or blocklist marketplace sources
* Force-enable plugins
* Turn off the `--plugin-dir` and `--plugin-url` flags and the `CLAUDE_CODE_PLUGIN_DIRS` variable
* Limit hooks to those from managed settings and force-enabled plugins
* Stop plugins from members' claude.ai accounts from loading in Claude Code, with [`syncClaudeAiPlugins`](/docs/en/plugins/org#control-matrix)
The [control matrix](/docs/en/plugins/org#control-matrix) says what each key does and doesn't cover.
## Find plugins in telemetry
If your organization exports Claude Code's [OpenTelemetry events](/docs/en/monitoring-usage) to its own backend, the [marketplace tiers](#marketplace-tiers) decide which plugin names appear there:
* **[Plugin loaded event](/docs/en/monitoring-usage#plugin-loaded-event)**: the event reports official-tier plugin and marketplace names as they are. For the community and third-party tiers, `plugin.name` and `marketplace.name` are the literal string `third-party` unless you set `OTEL_LOG_TOOL_DETAILS=1`.
* **Plugin scope**: the loaded event's `plugin.scope` still reports where the plugin came from, such as `org` for a plugin your managed settings enable or `user-local` for any other third-party plugin. The [plugin loaded event](/docs/en/monitoring-usage#plugin-loaded-event) lists every value.
* **[Plugin installed event](/docs/en/monitoring-usage#plugin-installed-event)**: unless you set `OTEL_LOG_TOOL_DETAILS=1`, the event omits the name fields for non-official plugins instead of reporting `third-party`.
* **[Claude Code Analytics API](https://platform.claude.com/docs/en/api/admin/analytics/plugins/list)**: Claude Code reports plugins from the official and community tiers by name and reports every other plugin as `third-party`.
## Next steps
* [Manage plugins for your organization](/docs/en/plugins/org): restrict which marketplaces users can install from and require the ones you trust
* [Install and manage plugins](/docs/en/plugins/install): review a plugin's details pane before you choose a scope
* [Anthropic's marketplaces](/docs/en/plugins/anthropic-marketplaces): which marketplace names are Anthropic's
* [Security](/docs/en/security): Claude Code's own security model
plugins/troubleshooting New page · 1026 lines, new page
# Troubleshoot plugins ## Find where `/plugin` runs ## Add a marketplace ## Install a plugin ## Plugin installed but not working #### Hooks fail to load #### `hook error` notices in the transcript #### Hook loads but never fires #### `Invalid MCP server config for "<server>": <error>` #### Server is configured but never connects #### Server works with `--plugin-dir` but fails after install #### Language server doesn't start #### Language server uses too much memory #### False positive diagnostics in a monorepo ## Build a plugin ## Host a marketplace ## Blocked by your organization ## Next steps
A whole new page. There's nothing to diff it against, so here is what it says.
# Troubleshoot plugins
> Fix plugin errors in Claude Code. Find the exact message you saw, grouped by stage from where /plugin runs through install and org policy.
This page lists error messages and symptoms for Claude Code plugins and for marketplaces, the catalogs Claude Code installs plugins from. Each entry gives the cause, one fix, and what you see once the fix works.
Where a message names a plugin or marketplace, the entry shows a placeholder such as `<name>` instead.
Use this page whether you install plugins, build them, host a marketplace, or administer plugins for an organization.
<Note>
These cases are covered on other pages:
* **Why scopes, the cache, and precedence behave the way they do**: read [Plugin loading reference](/docs/en/plugins/loading)
* **Looking up a flag, field, or command**: use the [plugin commands reference](/docs/en/plugins/cli-reference), the [manifest reference](/docs/en/plugins/manifest-reference), or the [marketplace reference](/docs/en/plugins/marketplace-reference)
</Note>
Search for the exact message you saw. Each message is listed under the stage that produces it, which isn't always the command you ran. For example, an install can fail because a marketplace is missing, so that message is under [Add a marketplace](#add-a-marketplace).
## Find where `/plugin` runs
`/plugin` is a command you type inside a running Claude Code terminal session, and it opens an interactive panel. The entries in this section cover the places where you can type it but it can't run, and the command spellings that don't exist.
<h3 id="plugin-isnt-available-in-this-environment">
`/plugin isn't available in this environment`
</h3>
You typed `/plugin` somewhere other than a Claude Code terminal session, and Claude replied with this line instead of opening anything.
You get this reply in a session that has no terminal to draw the `/plugin` panel in: [non-interactive mode](/docs/en/headless) with `claude -p`, the Agent SDK, the Claude desktop app's Code tab, the VS Code extension panel, and the browser at claude.ai/code.
In the VS Code extension panel, only a `/plugin` line with something after it, such as `/plugin install <plugin>@<marketplace>`, gets this reply. `/plugin` or `/plugins` typed alone opens the **Manage plugins** dialog.
Install the plugin from the surface you're on instead:
* **Claude desktop app, local or SSH session**: click the **+** button next to the prompt, then **Plugins**, then **Add plugin** to open the [plugin browser](/docs/en/desktop#install-plugins)
* **VS Code extension**: use the **VS Code** tab under [Install a plugin](/docs/en/plugins/install#install-a-plugin)
* **Claude Code on the web, or a desktop cloud session**: a cloud session has no plugin browser. See the **Cloud session** tab under [Install a plugin](/docs/en/plugins/install#install-a-plugin) for what a cloud session loads
* **A terminal you have access to**: run `claude` and type `/plugin` there, or run `claude plugin install <plugin>@<marketplace>` in your shell without starting a session
When a terminal install works, `/plugin` prints an install summary that starts with `✓ Installed <plugin>.` and `claude plugin install` prints `Successfully installed plugin: <plugin>@<marketplace>`.
<h3 id="zsh-no-such-file-or-directory-plugin">
`zsh: no such file or directory: /plugin`
</h3>
You typed `/plugin ...` at a shell prompt, and the shell reported that no file named `/plugin` exists. Bash reports `bash: /plugin: No such file or directory`.
`/plugin` is a command you type inside a Claude Code session, not at the shell prompt. Start a session and type the same command there:
```shell theme={null}
claude
```
Then, at the Claude Code prompt:
```text theme={null}
/plugin install <plugin>@<marketplace>
```
A successful install prints a summary that starts with `✓ Installed <plugin>.` If the install itself then fails, its message is under [Add a marketplace](#add-a-marketplace) or [Install a plugin](#install-a-plugin).
To install from the shell without starting a session, run `claude plugin install <plugin>@<marketplace>` instead.
<h3 id="the-term-plugin-is-not-recognized-as-the-name-of-a-cmdlet">
`The term '/plugin' is not recognized as the name of a cmdlet`
</h3>
You typed `/plugin ...` at a PowerShell prompt, and `/plugin` is a Claude Code command, not a program. Bash and Zsh report [their own form of this error](#zsh-no-such-file-or-directory-plugin).
Use either of these instead:
* Run `claude`, then type `/plugin` at the Claude Code prompt
* Run `claude plugin install <plugin>@<marketplace>` in PowerShell without starting a session
<h3 id="claude-command-not-found-after-claude-plugin">
`claude: command not found` after `claude plugin ...`
</h3>
You ran `claude plugin install ...` in your shell, and the shell couldn't find `claude` at all. On Windows the message is `'claude' is not recognized as the name of a cmdlet` or `'claude' is not recognized as an internal or external command`.
The cause isn't the plugin command. Either Claude Code isn't installed, or its install directory isn't on your `PATH` in this shell. Follow [`command not found: claude` after installation](/docs/en/troubleshoot-install#command-not-found-claude-after-installation), then retry the plugin command.
<h3 id="unknown-command-and-command-spellings-that-dont-exist">
`Unknown command` and command spellings that don't exist
</h3>
You typed a plugin command you saw somewhere and got `Unknown command: /<name>` in a session, or `error: unknown command '<name>'` or `error: unknown option '<flag>'` from the `claude` binary in your shell.
Several command spellings are in use that Claude Code doesn't have. The table below maps each one to the real command. The [plugin commands reference](/docs/en/plugins/cli-reference) lists every subcommand and flag.
| You typed | What Claude Code says | Use instead |
| :----------------------------------------- | :--------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- |
| `claude plugin add <source>` | `error: unknown command 'add'` | `claude plugin marketplace add <source>` to add a marketplace, or `claude plugin install <plugin>@<marketplace>` to install a plugin |
| `claude plugin install <plugin> --project` | `error: unknown option '--project'` | `claude plugin install <plugin>@<marketplace> --scope project` |
| `/install <plugin>` | `Unknown command: /install` | `/plugin install <plugin>@<marketplace>` |
| `/plugin add <source>` | The `/plugin` panel opens on the **Discover** tab | `/plugin marketplace add <source>` |
| `marketplace.anthropic.com` as a source | `Invalid marketplace source format. Try: owner/repo, https://..., or ./path` | `anthropics/claude-plugins-official` for the official marketplace |
These spellings look wrong but work:
* `claude plugins` is an alias of `claude plugin`
* `claude plugin remove` is an alias of `claude plugin uninstall`
* `/plugins` and `/marketplace` in a session open the same panel as `/plugin`
## Add a marketplace
A marketplace is a catalog you add to Claude Code from a git repository, a URL, or a local path. These entries cover the messages you get when adding one fails or a later refresh fails.
<h3 id="marketplace-claude-plugins-official-not-found">
`Marketplace "claude-plugins-official" not found`
</h3>
You ran `/plugin install <plugin>@claude-plugins-official` in a session, and Claude Code reported that it has no marketplace by that name.
The official marketplace isn't registered on this machine yet. Claude Code normally registers it on its own the first time you start an interactive terminal session. It hasn't run yet if you've only used Claude Code through the VS Code extension, and it skips or defers that step:
* When a policy blocks the source
* When `CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL` is set
* After a failed attempt that's waiting to retry
The `claude plugin` shell commands never register it for you.
Add it, then retry the install:
```text theme={null}
/plugin marketplace add anthropics/claude-plugins-official
```
Claude Code prints `Successfully added marketplace: claude-plugins-official`, and `/plugin marketplace list` shows the marketplace with its source.
For any other marketplace name in this message, see [`Marketplace "<name>" not found`](#marketplace-not-found).
The same string also appears in the `/plugin` **Errors** tab, the panel's list of load failures, when a plugin listed in your settings names a marketplace you haven't added.
<h3 id="marketplace-not-found">
`Marketplace "<name>" not found`
</h3>
You ran `/plugin install <plugin>@<name>` in a session, often from an install line someone sent you, and Claude Code reported that it has no marketplace by that name.
If the name starts with `claudeai-`, the marketplace is hosted on claude.ai, and you add it by name from your shell with `claude plugin marketplace add --claudeai <name>`. See [Add a marketplace from claude.ai](/docs/en/plugins/install#add-from-claude-ai).
For any other name, an install line names a marketplace but doesn't say where the marketplace is hosted, and Claude Code has no index to look a marketplace name up in. Ask whoever sent the line for the marketplace's source, which is a GitHub `owner/repo`, a git URL, or a path. Then [add the marketplace](/docs/en/plugins/install#add-a-marketplace) and run the install line again.
A marketplace someone sends you is third-party, so [review the plugin before you install it](/docs/en/plugins/security#review-a-plugin-before-you-install).
If you already added the marketplace, check the spelling against `/plugin marketplace list`.
<h3 id="invalid-marketplace-source-format">
`Invalid marketplace source format`
</h3>
You ran `/plugin marketplace add <source>` or `claude plugin marketplace add <source>`, and Claude Code replied `Invalid marketplace source format. Try: owner/repo, https://..., or ./path`.
Claude Code accepts a source in one of these forms:
* A GitHub `owner/repo` shorthand
* An `https://` or `http://` URL
* A `user@host:path` SSH URL
* A local path starting with `./`, `../`, `/`, or `~`
A bare name such as `claude-plugins-official` matches none of them. Neither does a bare hostname such as `marketplace.anthropic.com`.
Retype the source in one of the accepted forms:
```text theme={null}
/plugin marketplace add anthropics/claude-plugins-official
```
Claude Code prints `Successfully added marketplace: <name>` when the add works.
<h3 id="is-not-a-valid-github-owner-repo-shorthand">
`'<source>' is not a valid GitHub owner/repo shorthand`
</h3>
You passed a source with a slash that isn't `owner/repo`, such as `github.com/owner/repo` or a `gitlab.example.com/group/project` path. Claude Code refused it with this message and a list of accepted forms.
The `owner/repo` shorthand is GitHub-only and has to follow GitHub's naming rules, so a hostname or an extra path segment fails. Pass the source in the form that matches where the marketplace is hosted:
* **A repository on any host**: the full clone URL
* **A hosted `marketplace.json`**: its `https://` URL
* **A local checkout**: `./path` or an absolute path
For example, to add the official marketplace by its clone URL, in a session:
```text theme={null}
/plugin marketplace add https://github.com/anthropics/claude-plugins-official.git
```
A successful add prints `Successfully added marketplace: <name>`.
<h3 id="path-does-not-exist">
`Path does not exist: <path>`
</h3>
You passed a local path to `marketplace add`, and nothing exists at that path. A relative path resolves against your current directory.
Check the resolved path in the message. Then run the command from the directory the relative path starts from, or pass an absolute path to the marketplace directory. A successful add prints `Successfully added marketplace: <name>`.
Claude Code accepts a directory that contains `.claude-plugin/marketplace.json`, or a path to a `.json` file. A path to any other file fails with `File path must point to a .json file (marketplace.json)`.
<h3 id="marketplace-file-not-found-at-claude-plugin-marketplace-json">
`Marketplace file not found at <path>/.claude-plugin/marketplace.json`
</h3>
Claude Code cloned or downloaded the marketplace but found no `marketplace.json` at the expected path inside it. The add command reports it as `Failed to add marketplace: Marketplace file not found at ...`.
The default location is `.claude-plugin/marketplace.json` at the repository root, and the [marketplace reference](/docs/en/plugins/marketplace-reference) lists the accepted locations.
The fix differs for the owner and for everyone else:
* **You own the marketplace**: put the file at that location and re-add the marketplace
* **Someone else hosts it**: ask the owner for the exact source they publish
<h3 id="ssh-authentication-failed-or-https-authentication-failed">
`SSH authentication failed` or `HTTPS authentication failed`
</h3>
You added or updated a marketplace from a git repository, and the clone failed with `Failed to clone marketplace repository:` followed by one of these lines.
First check the repository itself: a misspelled `owner/repo`, a repository that doesn't exist, or a private repository you can't see also ends in this message. Open the repository URL in your browser, or run `git ls-remote <url>` in your terminal, to confirm it exists and you have access.
If the repository is right, the cause is credentials. Claude Code runs git with interactive prompts disabled, so it can't ask you for a password, a key passphrase, or a credential the way your terminal would. If git needs to prompt, you see `fatal: Cannot prompt because user interactivity has been disabled` or `terminal prompts disabled` in the original error. Only credentials that already work non-interactively succeed:
* **SSH**: `ssh -T git@<host>` must succeed without prompting for a passphrase, and the host must already be in `known_hosts`
* **HTTPS**: your credential helper must hold a token for the host. For GitHub, run `gh auth login` and `gh auth setup-git`. For another host, store a personal access token in your git credential helper. Test with `git ls-remote <url>`
Once `git ls-remote` succeeds in your terminal without a prompt, run the add or update again. A successful add prints `Successfully added marketplace: <name>`. A successful update prints `Successfully updated marketplace: <name>` from your shell, or `✔ Updated 1 marketplace` in a session.
To make Claude Code skip SSH for GitHub `owner/repo` sources, set `CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1`. Without it, Claude Code clones those sources over SSH when an SSH key for `github.com` looks configured, and falls back to HTTPS when the SSH clone fails.
For what background auto-updates can and can't do with your credentials, see [What background auto-update does with credentials](/docs/en/plugins/host-marketplace#what-background-auto-update-does-with-credentials).
<h3 id="ssh-host-key-is-not-in-your-known-hosts-file">
`SSH host key is not in your known_hosts file`
</h3>
You added a marketplace over SSH from a host you've never connected to, and the clone failed with this line and a `ssh -T git@<host>` hint. For a host whose key changed, the message is `SSH host key has changed` with a `ssh-keygen -R <host>` hint instead.
Claude Code clones with `StrictHostKeyChecking=yes`, so it refuses a host whose key you haven't accepted yet rather than accepting the key automatically. Connect once from your terminal to accept the fingerprint, then retry:
```shell theme={null}
ssh -T [email protected]
```
For a public repository, add the marketplace by its `https://` URL instead to avoid SSH entirely.
<h3 id="command-git-not-found-or-is-in-an-unsafe-location">
`Command 'git' not found or is in an unsafe location`
</h3>
On Windows, you added a marketplace and Claude Code reported `Failed to clone marketplace repository: Command 'git' not found or is in an unsafe location (current directory)`.
Claude Code looks for `git` on your `PATH` and refuses to run one found only in the current directory. To fix it, install Git and retry:
<Steps>
<Step title="Install Git for Windows">
Install Git for Windows so that `git` is on your `PATH`.
</Step>
<Step title="Open a new terminal">
Open a new terminal so the updated `PATH` applies.
</Step>
<Step title="Confirm git runs">
Confirm `git --version` prints a version.
</Step>
<Step title="Retry the add">
Run the `marketplace add` command again.
</Step>
</Steps>
<h3 id="git-clone-timed-out-after-120s">
`Git clone timed out after 120s`
</h3>
You added or updated a marketplace, and it failed with `Git clone timed out after 120s`, followed by a hint to set `CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS`.
Cloning a marketplace, and re-cloning one to update it, gets 120 seconds by default. For a large repository or a slow connection, raise the limit. The value is in milliseconds:
<Tabs>
<Tab title="Bash or Zsh">
```bash theme={null}
export CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS=300000
```
</Tab>
<Tab title="PowerShell">
```powershell theme={null}
$env:CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS = "300000"
```
</Tab>
</Tabs>
Then retry in the same shell.
If the repository is a monorepo, limit the checkout to the directories you name with `claude plugin marketplace add <source> --sparse <paths>`.
Cut at 300 lines. The page has the rest.