> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 04-7 Using Plugins Properly: Know-How Beyond the Quick Start

> Most people install a plugin, follow the Quick Start, and consider it done -- without being able to say what it installed, what capabilities it provides, or how to configure it fully. This unit covers plugin directory structure, a post-install audit SOP, advanced configuration, version management, and a security evaluation SOP.

export const LearnerPrimer = ({items = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    title: "Before this unit, be honest with yourself",
    sub: "If you can't answer these, that gap is exactly what this unit closes."
  } : {
    title: "讀這個單元前，先誠實面對",
    sub: "這幾題答不出來，正是這個單元要替你補的洞。"
  };
  const css = `
  .lp-root{--lp-bg:#FAF7F1;--lp-surface:rgba(191,117,81,0.05);--lp-border:rgba(0,0,0,0.09);--lp-edge:rgba(191,117,81,0.42);--lp-text:#2b2722;--lp-dim:#6f6a62;--lp-accent:#bf7551;border:1px solid var(--lp-border);border-left:3px solid var(--lp-edge);border-radius:13px;background:var(--lp-bg);color:var(--lp-text);overflow:hidden;margin:1.25rem 0;}
  .dark .lp-root{--lp-bg:#1b1a18;--lp-surface:rgba(207,138,104,0.07);--lp-border:rgba(255,255,255,0.08);--lp-edge:rgba(207,138,104,0.5);--lp-text:#e7e3da;--lp-dim:#a8a299;--lp-accent:#cf8a68;}
  .lp-head{display:flex;align-items:center;gap:9px;padding:13px 18px 11px;border-bottom:1px solid var(--lp-border);background:var(--lp-surface);}
  .lp-ic{color:var(--lp-accent);flex-shrink:0;}
  .lp-htx{display:flex;flex-direction:column;gap:1px;min-width:0;}
  .lp-title{font-size:14px;font-weight:650;line-height:1.3;letter-spacing:.01em;}
  .lp-sub{font-size:12px;color:var(--lp-dim);line-height:1.4;}
  .lp-list{list-style:none;margin:0;padding:10px 18px 14px;display:flex;flex-direction:column;gap:0;}
  .lp-item{display:flex;align-items:baseline;gap:11px;padding:7px 0;font-size:14px;line-height:1.6;border-top:1px solid var(--lp-border);}
  .lp-item:first-child{border-top:none;}
  .lp-mark{flex-shrink:0;color:var(--lp-accent);font-size:13px;font-weight:700;line-height:1.55;font-variant-numeric:tabular-nums;opacity:.85;}
  .lp-q{flex:1 1 0;min-width:0;color:var(--lp-text);}
  @media (max-width:620px){.lp-head{padding:12px 14px 10px;}.lp-list{padding:8px 14px 12px;}}
  `;
  return <div className="lp-root">
      <style>{css}</style>
      <div className="lp-head">
        <svg className="lp-ic" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="6" /><circle cx="12" cy="12" r="2" /></svg>
        <span className="lp-htx">
          <span className="lp-title">{t.title}</span>
          <span className="lp-sub">{t.sub}</span>
        </span>
      </div>
      <ul className="lp-list">
        {items.map((q, i) => <li className="lp-item" key={i}>
            <span className="lp-mark">{String(i + 1).padStart(2, "0")}</span>
            <span className="lp-q">{q}</span>
          </li>)}
      </ul>
    </div>;
};

<LearnerPrimer
  lang="en"
  items={[
"Installing a plugin is not the same as knowing how to use it.",
"Enabling a plugin without auditing its hooks means unknown code runs constantly.",
"Did you install this plugin because the Quick Start looked cool, or because of a real pain point?",
"When a name collision occurs, blaming the model for strange behavior is the wrong diagnosis.",
"Omit the version field in production and one bad commit on main takes you down with it.",
"Edit a Subagent frontmatter inside a plugin and the next update will overwrite your change.",
"Multiple plugins each managing the same lint hook type stack up and waste resources.",
]}
/>

<Info>
  **What this unit solves**

  Most people follow the Quick Start, install a plugin, and consider it done -- without being able to say what it installed, what capabilities it provides, or how to configure it fully. That is knowing the surface without knowing the substance. Since Claude Code v2.1, a plugin is "a unit that packages and distributes skills, agents, hooks, MCP/LSP configuration, and background monitors," distributed through two public marketplaces (`claude-plugins-official` and `claude-community`). This unit covers plugin directory structure, a post-install audit SOP, advanced configuration beyond the Quick Start, version management, and the security evaluation SOP you should run before picking up any plugin.
</Info>

## Learning objectives

* [ ] Name the components a plugin packages (skills, agents, commands, hooks, `.mcp.json`, `.lsp.json`, monitors, `bin/`, `settings.json`) and explain the role each plays in the system.
* [ ] After installing a plugin, proactively inventory every skill, agent, command, hook, and MCP server it actually provides, rather than relying on what the Quick Start happens to mention.
* [ ] Perform complete configuration beyond the Quick Start: environment variables, conflict resolution with existing settings, model selection, and preloaded skills.
* [ ] Distinguish when to use each of the three install paths: `claude --plugin-dir` (local development), `--plugin-url` (CI artifact), `/plugin install` (marketplace).
* [ ] Apply the 03-1 evaluation framework and 03-3 security principles to decide whether to install a plugin, whether to keep it, and whether to restrict its hook or MCP permissions.

***

## 1. What a plugin is: a bundled capability set

A plugin is a **directory** containing a manifest and a set of components: skills, agents, commands, hooks, MCP server configuration, LSP server configuration, background monitors, and executables. It upgrades the "project-local scattered `.claude/` configuration" into a **distributable, versioned, cross-project-shareable unit** (as of 2026-06, per the official plugins chapter \[1]).

What actually happens when you install a plugin:

* Its component directories and files are registered in Claude Code's load list.
* The `name` field in `plugin.json` adds a namespace prefix to all skills and commands (`/plugin-name:skill-name`).
* The included MCP server and LSP server configurations are activated.
* Default values in `settings.json` are applied (currently limited to the `agent` and `subagentStatusLine` keys) \[1].

<Tip>
  **Why you would want a plugin instead of just writing in `.claude/`**

  Cross-project sharing: the same API conventions, code review agent, or post-tool formatter useful across multiple repos cannot be rewritten in each one. Versioning: plugins have a `version` field that can be pinned, avoiding the "auto-tracking main and now today's commit broke everything" scenario. Distribution: a marketplace lets team members or the community install with one command rather than manually cloning and configuring paths. Namespace isolation: plugin skills are always namespaced (`/plugin-name:hello`), so identically named skills from different plugins never overwrite each other.
</Tip>

## 2. Plugins versus standalone `.claude/` configuration

Claude Code supports two ways to add custom skills, agents, and hooks (\[1]):

| Dimension          | Standalone config (`.claude/`)                                          | Plugin                                                                      |
| ------------------ | ----------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| Skill naming       | `/hello` (short, no prefix)                                             | `/my-plugin:hello` (namespaced)                                             |
| Best for           | Personal workflows, single-project customization, rapid experimentation | Cross-project sharing, team distribution, community marketplace, versioning |
| Distribution       | Through version control (travels with the repo)                         | Through marketplace or git URL                                              |
| Version management | Follows the repo                                                        | Explicit `version` field or git commit SHA                                  |
| Hook configuration | Inside `settings.json`                                                  | `hooks/hooks.json` (separated from settings)                                |
| Install command    | Edit files                                                              | `/plugin install` or `claude --plugin-dir`                                  |

<Tip>
  **Starting strategy**

  Iterate quickly with standalone `.claude/` configuration, validate that the workflow is worth packaging, and **then** convert to a plugin for distribution (\[1]). This order avoids "spending three hours packaging a feature nobody uses."
</Tip>

## 3. Directory structure

Complete plugin directory structure (as of 2026-06) \[1]:

<Tree>
  <Tree.Folder name="my-plugin/" defaultOpen>
    <Tree.Folder name=".claude-plugin/" defaultOpen>
      <Tree.File name="plugin.json · required: manifest" />
    </Tree.Folder>

    <Tree.Folder name="skills/ · optional: Agent Skills">
      <Tree.Folder name="code-review/">
        <Tree.File name="SKILL.md" />

        <Tree.Folder name="references/" />
      </Tree.Folder>
    </Tree.Folder>

    <Tree.Folder name="commands/ · optional: user-triggered commands">
      <Tree.File name="deploy.md" />
    </Tree.Folder>

    <Tree.Folder name="agents/ · optional: custom Subagents">
      <Tree.File name="security-reviewer.md" />
    </Tree.Folder>

    <Tree.Folder name="hooks/ · optional: event handlers">
      <Tree.File name="hooks.json" />
    </Tree.Folder>

    <Tree.File name=".mcp.json · optional: MCP server configuration" />

    <Tree.File name=".lsp.json · optional: LSP server configuration" />

    <Tree.Folder name="monitors/ · optional: background monitors">
      <Tree.File name="monitors.json" />
    </Tree.Folder>

    <Tree.Folder name="bin/ · optional: executables added to PATH when the plugin is active" />

    <Tree.File name="settings.json · optional: defaults applied when the plugin is activated" />

    <Tree.File name="README.md · recommended: human-readable description" />
  </Tree.Folder>
</Tree>

<Warning>
  **Do not put `commands/`, `agents/`, `skills/`, or `hooks/` inside `.claude-plugin/`**

  The official documentation repeatedly emphasizes this (\[1]): **only `plugin.json` belongs inside `.claude-plugin/`**. All other directories must be at the plugin root level. This is a common mistake that causes Claude Code to fail to find components when loading the plugin.
</Warning>

## 4. Manifest: `.claude-plugin/plugin.json`

Minimal manifest \[1]:

```json theme={null}
{
  "name": "my-first-plugin",
  "description": "A greeting plugin to learn the basics",
  "version": "1.0.0",
  "author": {
    "name": "Your Name"
  }
}
```

| Field         | Purpose                                                                                                                                                      |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `name`        | Unique identifier; also the skill namespace prefix. The `my-first-plugin` in `/my-first-plugin:hello` comes from this value                                  |
| `description` | Displayed in the plugin manager so users can judge what the plugin does                                                                                      |
| `version`     | Optional. **If set, users receive updates only when this field changes.** If omitted, each commit is treated as a new version when distributing via git \[1] |
| `author`      | Optional; author info (name, email)                                                                                                                          |
| `homepage`    | Optional; plugin homepage                                                                                                                                    |
| `repository`  | Optional; source repo                                                                                                                                        |
| `license`     | Optional; license terms                                                                                                                                      |

Full schema in the official plugins reference \[2].

## 5. How to place each component

### 5.1 Skills

Skills go as **directories** at `skills/<name>/SKILL.md`, identical to standalone configuration (\[1]; see also [04-4 Skills](/en/code-agent/customization/skills)):

<Tree>
  <Tree.Folder name="my-plugin/" defaultOpen>
    <Tree.Folder name="skills/" defaultOpen>
      <Tree.Folder name="code-review/" defaultOpen>
        <Tree.File name="SKILL.md" />

        <Tree.Folder name="references/">
          <Tree.File name="style-guide.md" />
        </Tree.Folder>
      </Tree.Folder>
    </Tree.Folder>
  </Tree.Folder>
</Tree>

Each SKILL.md uses a YAML frontmatter block with a `description`:

```yaml theme={null}
---
description: Reviews code for best practices and potential issues. Use when reviewing code, checking PRs, or analyzing code quality.
---

When reviewing code, check for:
1. Code organization and structure
2. Error handling
3. Security concerns
4. Test coverage
```

Run `/reload-plugins` after installing the plugin for it to load. Complete skill authoring guidelines are in [04-4 Skills](/en/code-agent/customization/skills).

### 5.2 Commands

Commands go as single files at `commands/<name>.md` (\[1]; see also [04-3 Commands](/en/code-agent/customization/commands)):

<Tree>
  <Tree.Folder name="my-plugin/" defaultOpen>
    <Tree.Folder name="commands/" defaultOpen>
      <Tree.File name="deploy.md" />
    </Tree.Folder>
  </Tree.Folder>
</Tree>

<Note>
  **`commands/` is the legacy form for plugins**

  The official v2.1 documentation explicitly states "Use `skills/` for new plugins" (\[1]). New plugins should put imperative logic in `skills/<name>/SKILL.md` to gain directory-based structure, `references/`, `scripts/`, and progressive disclosure.
</Note>

### 5.3 Agents

Subagents go at `agents/<name>.md`, with the same frontmatter as standalone configuration (see [04-5 Subagents](/en/code-agent/customization/subagents)). **Plugin Subagents have three restrictions** (\[1]): the `hooks`, `mcpServers`, and `permissionMode` frontmatter fields are ignored.

<Warning>
  **Plugin Subagent restrictions**

  For security reasons, Plugin Subagents do not support the `hooks`, `mcpServers`, or `permissionMode` fields \[1]. When you need those three, copy the agent file to `.claude/agents/` or `~/.claude/agents/`. Another path is to add rules to `permissions.allow` in `settings.json`, but that rule applies to the entire session and cannot be scoped to the plugin agent alone.
</Warning>

### 5.4 Hooks

Hook configuration goes in `hooks/hooks.json`, using **the same format as the `hooks` block in `settings.json`** (\[1]):

```json theme={null}
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix" }
        ]
      }
    ]
  }
}
```

Hook commands receive the hook input JSON via stdin; use `jq` to extract fields (examples in [04-6 Hooks](/en/code-agent/customization/hooks)).

### 5.5 MCP servers

`.mcp.json` uses the same schema as standalone configuration (\[1]):

```json theme={null}
{
  "github": {
    "type": "stdio",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": {
      "GITHUB_TOKEN": "${GITHUB_TOKEN}"
    }
  }
}
```

These MCP servers connect automatically to the main session when the plugin is activated.

### 5.6 LSP servers

LSP (Language Server Protocol) servers give Claude real-time code intelligence (\[1]). Example `.lsp.json`:

```json theme={null}
{
  "go": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": {
      ".go": "go"
    }
  }
}
```

<Tip>
  **Prefer pre-built LSP plugins from the official marketplace**

  For mainstream languages such as TypeScript, Python, and Rust, **install a pre-built LSP plugin directly from `claude-plugins-official`**. Only build your own LSP plugin for languages the official marketplace does not cover \[1].
</Tip>

### 5.7 Monitors

Monitors let a plugin watch logs, files, and external state in the background and notify Claude when events occur (\[1]). `monitors/monitors.json`:

```json theme={null}
[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]
```

Each line of stdout from `command` is treated as a notification sent to Claude. The full schema including `when` triggers and variable substitution is in \[2].

### 5.8 bin/

Executables in `bin/` are added to the `Bash` tool's `PATH` when the plugin is activated \[1]. **Place things here carefully**: every executable becomes a command callable at any time in your shell and can be triggered by any hook or agent.

### 5.9 Default settings

The `settings.json` at the plugin root applies defaults when the plugin is activated. **Only two keys are currently supported** (\[1]): `agent` and `subagentStatusLine`.

```json theme={null}
{
  "agent": "security-reviewer"
}
```

This sets the plugin's `agents/security-reviewer.md` as the main session agent. Unknown keys are silently ignored.

## 6. Installation: four paths

Choose the install method that matches your use case:

| Path              | Command                                                 | Use                                                          |
| ----------------- | ------------------------------------------------------- | ------------------------------------------------------------ |
| Local development | `claude --plugin-dir ./my-plugin`                       | Development, testing, debugging                              |
| Local ZIP         | `claude --plugin-dir ./my-plugin.zip`                   | Same as above with a packaged version (v2.1.128+) \[1]       |
| URL CI artifact   | `claude --plugin-url https://example.com/my-plugin.zip` | Load-testing a CI-produced plugin                            |
| Marketplace       | `/plugin install <name>`                                | Install from `claude-plugins-official` or `claude-community` |

### 6.1 Local development mode

`--plugin-dir` loads a directory directly without an install step (\[1]):

```bash theme={null}
claude --plugin-dir ./my-plugin
```

Load multiple plugins at once (repeat the flag):

```bash theme={null}
claude --plugin-dir ./plugin-one --plugin-dir ./plugin-two
```

After editing a plugin during development, run `/reload-plugins` to reload without restarting.

### 6.2 Installing from the marketplace

The marketplace is managed with the `/plugin` command. Install flow (\[1]):

```
/plugin                                  # open the plugin manager
# browse the marketplace, select a plugin, follow the prompts
```

Or using the command form:

```
/plugin install <plugin-name>            # install from an added marketplace
/plugin marketplace add anthropics/claude-plugins-community
```

### 6.3 The two public marketplaces

Anthropic maintains two public marketplaces (\[1]):

* **`claude-plugins-official`**: Anthropic-curated, hand-picked plugins. **Available automatically with every Claude Code installation.**
* **`claude-community`**: community-submitted, review-approved plugins. Users add it with `/plugin marketplace add anthropics/claude-plugins-community` and install from `@claude-community`.

<Note>
  **The difference between them**

  `claude-plugins-official` curation is entirely Anthropic's decision; there is no application process, and the submission form does not place plugins there. `claude-community` goes through an automated pipeline: `claude plugin validate` automatic checks plus automated security screening. Once approved, the plugin is pinned to a specific commit SHA in the `anthropics/claude-plugins-community` repository; CI automatically bumps the pin when you push a new commit. The catalog syncs nightly, so there can be a 24-hour gap between approval and installability.

  Submission entry points: claude.ai/settings/plugins/submit or platform.claude.com/plugins/submit.
</Note>

### 6.4 Private marketplaces (internal team distribution)

Teams can host a marketplace in a private repository accessible only to organization members. Detailed mechanics are in \[2].

## 7. Post-install audit SOP: do not stop at the Quick Start

<Note>
  **30-minute audit workflow**

  Run through these steps after installing any plugin. **This is the gap between "installed and actually using it" and "installed and running only 20% of it."**
</Note>

<Steps>
  <Step title="Read the manifest">
    Open `~/.claude/plugins/<plugin-name>/.claude-plugin/plugin.json` and note the `name`, `version`, `author`, `description`, and `homepage` (if present).
  </Step>

  <Step title="List all components">
    ```bash theme={null}
    PLUGIN=~/.claude/plugins/<plugin-name>
    echo "=== skills ==="
    find "$PLUGIN/skills" -name "SKILL.md" 2>/dev/null
    echo "=== commands ==="
    ls "$PLUGIN/commands" 2>/dev/null
    echo "=== agents ==="
    ls "$PLUGIN/agents" 2>/dev/null
    echo "=== hooks ==="
    cat "$PLUGIN/hooks/hooks.json" 2>/dev/null
    echo "=== mcp servers ==="
    cat "$PLUGIN/.mcp.json" 2>/dev/null
    echo "=== lsp servers ==="
    cat "$PLUGIN/.lsp.json" 2>/dev/null
    echo "=== monitors ==="
    cat "$PLUGIN/monitors/monitors.json" 2>/dev/null
    echo "=== bin ==="
    ls "$PLUGIN/bin" 2>/dev/null
    echo "=== settings ==="
    cat "$PLUGIN/settings.json" 2>/dev/null
    ```
  </Step>

  <Step title="Confirm inside Claude Code">
    Run `/help` and look for the plugin's skills and commands (they will carry the namespace prefix). Run `/agents` and check whether the plugin's agents appear in the Library. Ask Claude in conversation: "list the plugins enabled in the current session and the skills and MCP servers each provides."
  </Step>

  <Step title="Read every SKILL.md, agent.md, and hooks.json">
    **Do not skip this.** Spend 30 seconds scanning each file to understand what it does, when it triggers, whether it takes arguments, and whether it dynamically injects shell commands. For every `command` in hooks.json, run the supply-chain scan in the next section.
  </Step>

  <Step title="Record configuration override points">
    What does the plugin's `settings.json` write (currently only `agent` and `subagentStatusLine`)? Which environment variables do the plugin's MCP servers need at startup (check the `env` field in `.mcp.json`)? Does your own `settings.json` have any settings the plugin would override (see \[2] for plugin settings.json precedence rules)?
  </Step>
</Steps>

A common blind spot this SOP uncovers: you install a plugin that "looks like it does code review," and only after the audit do you discover it also contains a `lint-on-save` hook that fires on `PostToolUse: Write|Edit` -- which the Quick Start never mentioned.

## 8. Complete configuration: beyond the Quick Start

The Quick Start typically demonstrates only one or two happy paths. Advanced settings are often buried in the details.

### 8.1 Environment variables and secrets

A plugin's `.mcp.json` and `monitors/monitors.json` frequently reference environment variables (`${GITHUB_TOKEN}`, etc.). The Quick Start sets the minimum required set; you need to:

* Confirm those variables exist in your local or CI environment.
* Inject them through an environment variable management tool (1Password CLI, `.env` with direnv, a cloud secret manager) -- **do not hardcode them in plugin configuration files**; plugins go into version control.

### 8.2 Name collisions between skills and commands

Plugin skills are always namespaced (`/plugin-name:hello`), but **standalone configuration (`.claude/commands/`) same-named commands can still collide with a plugin's `commands/<name>.md`**. Precedence rules (as of 2026-06; full details in \[2]):

* Standalone configuration takes priority (loaded first, matched first).
* Plugin commands are loaded after.
* When names collide, standalone configuration wins.

But if the standalone configuration is removed, the plugin command takes effect. **Check this layer explicitly during the audit**: does your `.claude/commands/deploy.md` share a name with a plugin's `commands/deploy.md`?

### 8.3 Hook execution order

When multiple hooks are triggered by the same event, **execution order follows configuration position** (\[1]): hooks in `settings.json` run first, then the plugin's `hooks/hooks.json`. If multiple plugins have PostToolUse hooks with the same matcher, all of them run in sequence. **There is no debouncing or manual priority ordering**. If your formatting hook and a plugin's formatting hook both process the same file, you need to consolidate manually.

### 8.4 MCP server port collisions

If two plugins both try to start a server on the same port, the second one to start will fail. Check each plugin's `.mcp.json`:

* Commands starting with `node`, `python`, or `npx` typically let the server choose a port dynamically, so collisions are less common.
* If a port is hardcoded (e.g., `localhost:8080`), change one of them to a different port manually.

### 8.5 Model selection

Some plugin Subagents inherit the main conversation model by default. For high-repetition workers (code formatters, test runners), changing the frontmatter to `model: haiku` can produce significant cost savings (see [04-5 Subagents](/en/code-agent/customization/subagents)).

<Warning>
  **Editing a plugin Subagent's frontmatter is a "fork"**

  If you edit a Subagent frontmatter inside a plugin, **your change will be overwritten the next time that plugin updates**. The long-term approaches are: fork and maintain the entire plugin yourself, or replace that functionality with a standalone Subagent.
</Warning>

### 8.6 Scaffolding with `claude plugin init`

`claude plugin init my-tool` scaffolds a plugin skeleton into `~/.claude/skills/my-tool/`, including a `.claude-plugin/plugin.json` manifest and a starter `SKILL.md`. It is loaded automatically as `my-tool@skills-dir` in the next session without any marketplace step (\[1]).

## 9. Version management

Two version modes for plugins (\[1]):

| Mode               | Trigger                                | Behavior                                    |
| ------------------ | -------------------------------------- | ------------------------------------------- |
| Explicit `version` | The field changes                      | Users receive updates only on a new version |
| Implicit (git SHA) | `version` omitted; distributed via git | **Every commit is a new version**           |

<Warning>
  **The cost of omitting `version`**

  Convenient for developers, but the plugin you installed will "auto-update on every commit." One breaking commit into main breaks your workflow. **Use an explicit `version` in production.** Omitting it is fine during development.
</Warning>

Update strategies:

* **Production lock**: freeze the `version` field; bump only after reviewing the PR.
* **Dev tracking**: omit `version`; use `claude --plugin-dir` pointing to a local directory.
* **Internal team distribution**: private marketplace + git tag; CI bumps the version.

## 10. Migrating from standalone configuration to a plugin

If you already have `.claude/commands/`, `agents/`, and `skills/`, you can migrate them into a plugin (\[1]):

```bash theme={null}
# 1. Build the plugin structure
mkdir -p my-plugin/.claude-plugin
echo '{"name": "my-plugin", "description": "...", "version": "1.0.0"}' \
  > my-plugin/.claude-plugin/plugin.json

# 2. Copy components
cp -r .claude/commands my-plugin/
cp -r .claude/agents my-plugin/
cp -r .claude/skills my-plugin/

# 3. Migrate hooks
mkdir my-plugin/hooks
# copy the hooks block from .claude/settings.json into my-plugin/hooks/hooks.json
# (the format is identical)

# 4. Test
claude --plugin-dir ./my-plugin

# 5. Verify every component: run skills, check that agents appear, verify hooks fire
```

<Tip>
  **Remove the originals after migrating**

  Once migration is complete and the plugin loads correctly, delete the corresponding files from `.claude/` to avoid double-loading \[1].
</Tip>

## 11. Security and evaluation

A plugin is code you do not fully control entering your working environment. The risk surface:

### 11.1 Supply chain evaluation

| Dimension             | What to assess                                                                                                       |
| --------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Maintainer            | Who is it? An individual or an organization? Community reputation? Commit activity history?                          |
| Update frequency      | When was the last commit? If the plugin has not been updated in a year, test thoroughly before applying              |
| Source                | From `claude-plugins-official`, the reviewed `claude-community`, or a private git URL? Trust level varies enormously |
| Code review           | Have you read the manifest and every SKILL.md, hooks.json, and .mcp.json?                                            |
| Known vulnerabilities | Snyk ToxicSkills (2026-02) found that 36% of public skills contain prompt injection                                  |

### 11.2 Pre-install scan

Following the SOP from [04-6 Hooks](/en/code-agent/customization/hooks), run this against `hooks/hooks.json` and every SKILL.md:

```bash theme={null}
PLUGIN=~/.claude/plugins/<plugin-name>

# 1. Suspicious outbound connections
rg -n 'curl|wget|nc|ssh|ANTHROPIC_BASE_URL|enableAllProjectMcpServers' "$PLUGIN/"

# 2. Hidden Unicode
rg -nP '[\x{200B}-\x{200D}\x{202A}-\x{202E}]' "$PLUGIN/"

# 3. HTML comments, script tags, base64
rg -n '<!--|<script|data:text/html|base64,' "$PLUGIN/"

# 4. Suspicious permissions or outbound (second pass)
rg -n 'curl|wget|nc|scp|ssh|enableAllProjectMcpServers|ANTHROPIC_BASE_URL' "$PLUGIN/"
```

Any hit requires a manual review of the surrounding context before you decide whether to install.

### 11.3 Restricting plugin permissions

If you are not comfortable with a plugin's hooks or MCP permissions after installing:

* **Disable all hooks**: set `"disableAllHooks": true` in `settings.json` (this also stops plugin hooks; managed-tier hooks are unaffected) \[1].
* **Deny a specific MCP server**: add a rule to `permissions.deny` in `settings.json`.
* **Fork the plugin**: copy the entire plugin to a local directory, remove the parts you are concerned about, rename `name` to `<name>-local`, and load it with `claude --plugin-dir`.

### 11.4 Connecting to the 03-1 evaluation framework

Before installing a plugin, run the [03-1 evaluation framework](/en/code-agent/judgment/fit-evaluation):

* Does this plugin address a real, high-frequency pain point in my workflow, or does it just look good in the Quick Start?
* Try it for a week: how many times per day do you actually invoke it? Does the time saved justify the supply-chain risk introduced?
* Is there a smaller, more trustworthy alternative (for example, extracting just one skill from the plugin and using it as standalone configuration)?

Do not evaluate based on the Quick Start alone -- that is a "shortest path demo," not a "reason worth installing."

## 12. Tool comparison

Plugin and extension mechanisms differ significantly in naming and architecture across vendors (as of 2026-06):

| Concept                       | Anthropic Claude (primary)                                                            | OpenAI Codex                                           | Google Antigravity                                          | GitHub Copilot CLI                                          | Cursor (brief)                            |
| ----------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------- |
| Extension unit                | Plugin (manifest + skills/agents/hooks/mcp/lsp/monitors/bin/settings)                 | Codex extension (`config.toml` + `extensions/<name>/`) | Antigravity extension (`~/.gemini/antigravity/extensions/`) | Copilot Extensions (third-party apps on GitHub Marketplace) | Cursor extensions (`.cursor/extensions/`) |
| Namespace                     | Required (`/plugin-name:hello`)                                                       | Configuration-based                                    | Configuration-based                                         | No namespace                                                | Configuration-based                       |
| Install method                | `claude --plugin-dir`, `/plugin install`, marketplace                                 | `codex extension install`                              | Configuration-based                                         | Marketplace UI                                              | Configuration-based                       |
| List installed                | `/plugin` command, filesystem scan                                                    | `codex extension list`                                 | Configuration-based                                         | Configuration-based                                         | Configuration-based                       |
| Configuration override points | `settings.json` (applied on activation), `hooks/hooks.json`, `monitors/monitors.json` | Configuration-based                                    | Configuration-based                                         | Configuration-based                                         | Configuration-based                       |
| Security scanning             | No built-in; manual `rg` scan                                                         | Configuration-based                                    | Configuration-based                                         | Configuration-based                                         | Configuration-based                       |
| Public marketplace            | `claude-plugins-official` (enabled by default) + `claude-community` (user-added)      | No unified public marketplace                          | Configuration-based                                         | GitHub Marketplace                                          | Configuration-based                       |
| Version management            | Explicit `version` or git commit SHA                                                  | Configuration-based                                    | Configuration-based                                         | Configuration-based                                         | Configuration-based                       |

<Note>
  **Naming clarification**

  Claude Code plugins and "Copilot Extensions" are different things: the former is a directory-based extension to the local CLI; the latter is a third-party app on GitHub Marketplace that typically integrates cloud services (issue trackers, CI platforms, cloud providers). This table compares like-for-like mechanisms only. The plugin and extension mechanisms of OpenAI Codex, Antigravity, and Cursor each differ in naming and architecture; check each vendor's current official documentation for details. Cursor is a third-party IDE (Anysphere) and is mentioned here briefly for one column only.
</Note>

## 13. Hands-on exercises

<Note>
  **30-minute exercises**

  1. **Audit an existing plugin**: run the `find` / `cat` SOP from this unit on your most-used plugin; list five components it actually provides (including ones the Quick Start omitted) and the trigger conditions for each.
  2. **Security scan**: run the four `rg` commands against the same plugin; note every hit and manually review the surrounding context.
  3. **Local development test**: create an empty plugin at `~/playground/my-test-plugin/` using `claude plugin init my-test-plugin`, add one SKILL and one PostToolUse hook, load it with `claude --plugin-dir`, and observe the namespace prefix and hook triggering behavior.
  4. **Fork a live plugin**: copy a plugin you have installed from `~/.claude/plugins/` to a local directory, remove the hooks block, rename `name` to `<original-name>-no-hooks`, load it with `claude --plugin-dir`, and verify the hooks do not run.
  5. **Pre-submission validation**: if you have written a plugin and want to submit it to `claude-community`, first run `claude plugin validate` to pass the automated checks.
</Note>

## 14. Common pitfalls

<Warning>
  **Anti-pattern list**

  * **Treating the Quick Start as complete documentation**: the Quick Start is the shortest-path demo only; the plugin's actual capability set is usually much larger. Assuming "installed means fully deployed" without an audit is how you miss 80% of what it can do.
  * **Enabling a plugin without auditing its hooks**: hooks execute automatically on every matching tool call. Allowing an unreviewed hook means unknown code runs constantly in your working environment.
  * **Attributing plugin conflicts to "model misbehavior"**: name-collision overrides and hook execution order conflicts are deterministic, debuggable problems, not random model behavior.
  * **Omitting `version` in production**: every commit is treated as a new version; one bad commit on main takes your workflow down with it.
  * **Treating SKILL.md and agent.md inside a plugin as "in version control and therefore stable"**: the next plugin update will overwrite your local fork. Long-term changes require maintaining your own fork.
  * **Multiple plugins each managing the same class of lint/format hook**: every Write/Edit triggers all of them in sequence, wasting resources. Consolidate into one custom plugin or disable the duplicates.
  * **Installing from a private URL without reading the source first**: `claude --plugin-url` is convenient for loading CI artifacts, but for any private URL, always read the source and run `rg` scans first.
</Warning>

## Self-check

<Check>
  **The bar for passing this unit**

  1. Can you name the nine component types a plugin packages (skills, commands, agents, hooks, `.mcp.json`, `.lsp.json`, monitors, `bin/`, `settings.json`) and explain what each does?
  2. Without looking at the Quick Start, can you list all components a plugin has installed, the purpose of each, and what it wrote into `settings.json` -- just from the plugin directory structure?
  3. Can you distinguish when to use each of the three install paths: `claude --plugin-dir`, `--plugin-url`, and `/plugin install`?
  4. Before installing a new plugin, can you name at least three supply-chain evaluation questions and the corresponding scan commands?
  5. If a plugin conflicts with your existing `.claude/` configuration, can you name at least two paths to investigate?
</Check>

## Sources and further reading

Factual claims are grounded in official documentation; fast-changing items are annotated as of 2026-05.

<div className="references">
  * \[1] Anthropic, "Create plugins," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/plugins](https://code.claude.com/docs/en/plugins) (as of 2026-06; covers directory structure, manifest schema, four install paths, `claude-plugins-official` and `claude-community` marketplaces, `--plugin-dir` vs. `--plugin-url` difference)

  * \[2] Anthropic, "Plugins reference," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/plugins-reference](https://code.claude.com/docs/en/plugins-reference) (as of 2026-06; full schema, version management, private marketplace, three restricted Subagent frontmatter fields)

  * \[3] Anthropic, "Discover and install plugins," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/discover-plugins](https://code.claude.com/docs/en/discover-plugins) (as of 2026-06; marketplace browsing and install flow)

  * \[4] Anthropic, "Create and distribute a plugin marketplace," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/plugin-marketplaces](https://code.claude.com/docs/en/plugin-marketplaces) (as of 2026-06; private marketplace and CI/CD integration)

  * \[5] Anthropic, "Hooks," code.claude.com, 2026. \[Online]. Available: [https://code.claude.com/docs/en/hooks](https://code.claude.com/docs/en/hooks) (as of 2026-06; plugin `hooks/hooks.json` uses the same schema as settings.json)
</div>

* Configuration layer model: [02-1 Configuration Layer Model](/en/code-agent/configuration/config-layer-model).
* Skill authoring and progressive disclosure: [04-4 Skills](/en/code-agent/customization/skills).
* Subagent frontmatter: [04-5 Subagents](/en/code-agent/customization/subagents).
* Hook trigger events and command handlers: [04-6 Hooks](/en/code-agent/customization/hooks).
* MCP server configuration: [04-9 MCP Integration](/en/code-agent/customization/mcp-integration).
* Evaluation framework: [03-1 Evaluating Fit](/en/code-agent/judgment/fit-evaluation).
* Supply chain risk: [03-3 Security, Privacy, and Supply Chain Risk](/en/code-agent/judgment/security-privacy-supply-chain).
