from line 6
66
77This page is for people writing their own plugins.
88
9<Note>
10 These cases are covered on other pages:
9> [!NOTE]
10>
11> These cases are covered on other pages:
12>
13> * **Installing someone else's plugin**: see [Install plugins](/docs/en/plugins/install)
14> * **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
15> * **Your plugin's users are on claude.ai or in Cowork**: the same folder installs there with a different subset of components. See [Plugin structure and testing](https://claude.com/docs/plugins/build) and the [component support table](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)
1116
12 * **Installing someone else's plugin**: see [Install plugins](/docs/en/plugins/install)
13 * **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
14 * **Your plugin's users are on claude.ai or in Cowork**: the same folder installs there with a different subset of components. See [Plugin structure and testing](https://claude.com/docs/plugins/build) and the [component support table](https://claude.com/docs/plugins/platform-support#compare-component-support-by-app)
15</Note>
16
1717Start from the section that matches what you already have:
1818
1919* **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).
from line 38
3838
3939Open 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.
4040
41<Steps>
42 <Step title="Create the plugin directory">
43 Create the plugin directory, with a `.claude-plugin/` folder inside it to hold the manifest:
41**1. Create the plugin directory**
4442
45 ```bash theme={null}
46 mkdir -p my-first-plugin/.claude-plugin
47 ```
48 </Step>
43Create the plugin directory, with a `.claude-plugin/` folder inside it to hold the manifest:
4944
50 <Step title="Write the manifest">
51 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`:
45```bash theme={null}
46mkdir -p my-first-plugin/.claude-plugin
47```
5248
53 ```json my-first-plugin/.claude-plugin/plugin.json theme={null}
54 {
55 "name": "my-first-plugin",
56 "description": "A greeting plugin to learn the basics",
57 "version": "1.0.0",
58 "author": {
59 "name": "Your Name"
60 }
61 }
62 ```
49**2. Write the manifest**
6350
64 The four fields do this:
51The [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`:
6552
66 * **`name`**: required. It identifies the plugin and becomes the prefix on every skill and agent the plugin provides. Don't put spaces in it.
67 * **`description`**: the text users see for the plugin in `/plugin`.
68 * **`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.
69 * **`author`**: who to credit. `name` is required inside it; `email` and `url` are optional.
53```json my-first-plugin/.claude-plugin/plugin.json theme={null}
54{
55 "name": "my-first-plugin",
56 "description": "A greeting plugin to learn the basics",
57 "version": "1.0.0",
58 "author": {
59 "name": "Your Name"
60 }
61}
62```
7063
71 Every other field is on the [manifest reference](/docs/en/plugins/manifest-reference#fields).
64The four fields do this:
7265
73 Only `plugin.json` goes inside `.claude-plugin/`. The skill you add next goes directly under `my-first-plugin/`, next to that folder.
74 </Step>
66* **`name`**: required. It identifies the plugin and becomes the prefix on every skill and agent the plugin provides. Don't put spaces in it.
67* **`description`**: the text users see for the plugin in `/plugin`.
68* **`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.
69* **`author`**: who to credit. `name` is required inside it; `email` and `url` are optional.
7570
76 <Step title="Add a skill">
77 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:
71Every other field is on the [manifest reference](/docs/en/plugins/manifest-reference#fields).
7872
79 ```bash theme={null}
80 mkdir -p my-first-plugin/skills/hello
81 ```
73Only `plugin.json` goes inside `.claude-plugin/`. The skill you add next goes directly under `my-first-plugin/`, next to that folder.
8274
83 Then create `my-first-plugin/skills/hello/SKILL.md` with this content:
75**3. Add a skill**
8476
85 ```markdown my-first-plugin/skills/hello/SKILL.md theme={null}
86 ---
87 name: hello
88 description: Greet the user with a friendly message
89 disable-model-invocation: true
90 ---
77This 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:
9178
92 Greet the user warmly and ask how you can help them today.
93 ```
79```bash theme={null}
80mkdir -p my-first-plugin/skills/hello
81```
9482
95 The `disable-model-invocation: true` line means Claude doesn't run the skill on its own. 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).
96 </Step>
83Then create `my-first-plugin/skills/hello/SKILL.md` with this content:
9784
98 <Step title="Validate the plugin">
99 Check the manifest and the skill's frontmatter before you run anything:
85```markdown my-first-plugin/skills/hello/SKILL.md theme={null}
86---
87name: hello
88description: Greet the user with a friendly message
89disable-model-invocation: true
90---
10091
101 ```bash theme={null}
102 claude plugin validate ./my-first-plugin
103 ```
92Greet the user warmly and ask how you can help them today.
93```
10494
105 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).
106 </Step>
95The `disable-model-invocation: true` line means Claude doesn't run the skill on its own. 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).
10796
108 <Step title="Run Claude Code with the plugin">
109 Start a session with the plugin loaded:
97**4. Validate the plugin**
11098
111 ```bash theme={null}
112 claude --plugin-dir ./my-first-plugin
113 ```
99Check the manifest and the skill's frontmatter before you run anything:
114100
115 Once Claude Code starts, run the skill:
101```bash theme={null}
102claude plugin validate ./my-first-plugin
103```
116104
117 ```text theme={null}
118 /my-first-plugin:hello
119 ```
105The 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).
120106
121 Claude replies with a greeting.
122 </Step>
123</Steps>
107**5. Run Claude Code with the plugin**
124108
109Start a session with the plugin loaded:
110
111```bash theme={null}
112claude --plugin-dir ./my-first-plugin
113```
114
115Once Claude Code starts, run the skill:
116
117```text theme={null}
118/my-first-plugin:hello
119```
120
121Claude replies with a greeting.
122
125123The 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).
126124
127125To have Claude scaffold and check a larger plugin with you, [install](/docs/en/plugins/install#install-a-plugin) Anthropic's `plugin-dev` plugin from the `claude-plugins-official` marketplace, which adds skills and agents for writing components such as skills, hooks, and MCP servers and for validating the finished plugin. Once it's installed, run `/plugin-dev:create-plugin` followed by a description of the plugin you want, and Claude walks you through designing, creating, and validating it.
128126
129<h3 id="share-the-plugin">
130 Share your plugin
131</h3>
127### Share your plugin
132128
133129A 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:
134130
from line 147
151147| `hooks/hooks.json` | Hook configuration: a top-level `"hooks"` key whose value has the same shape as `hooks` in a settings file |
152148| `.mcp.json` | MCP server definitions |
153149
154<Warning>
155 Only `plugin.json` goes inside `.claude-plugin/`. Components saved there don't load.
150> [!WARNING]
151>
152> Only `plugin.json` goes inside `.claude-plugin/`. Components saved there don't load.
153>
154> The plugin root is the plugin's own directory, not `~/.claude/` itself. A `.mcp.json` saved at `~/.claude/.mcp.json` doesn't load.
156155
157 The plugin root is the plugin's own directory, not `~/.claude/` itself. A `.mcp.json` saved at `~/.claude/.mcp.json` doesn't load.
158</Warning>
159
160156## Develop without a marketplace
161157
162158You 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:
from line 163
167163
168164If two plugins loaded in different ways share a name, see [Name conflicts](/docs/en/plugins/loading#name-conflicts) for which one Claude Code keeps.
169165
170<h3 id="load-a-directory-or-archive-for-one-session">
171 Load a plugin for one session
172</h3>
166### Load a plugin for one session
173167
174168You 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.
175169
176<span id="from-a-directory-or-zip" />
177
178170#### Load a plugin from a directory or `.zip`
179171
180172When 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:
from line 190
198190
199191A 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.
200192
201<span id="fetch-an-archive-from-a-url-for-one-session" />
202
203193#### Load a plugin from a URL
204194
205195When you start `claude` from your shell, pass `--plugin-url` with the address of a `.zip` archive, such as a build artifact your CI publishes:
from line 204
214204
215205If 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.
216206
217<span id="from-an-environment-variable" />
218
219207#### Load plugins from an environment variable
220208
221209To 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.
from line 210
222210
223211Managed 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).
224212
225<h3 id="scaffold-a-plugin-that-loads-every-session">
226 Make a plugin load in every session
227</h3>
213### Make a plugin load in every session
228214
229215Your 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.
230216
from line 226
240226
241227Pass `--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).
242228
243<h4 id="skill-names-in-a-scaffolded-plugin">
244 Name the plugin's skills
245</h4>
229#### Name the plugin's skills
246230
247231The 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`.
248232
from line 234
250234
251235To 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.
252236
253<h4 id="load-a-plugin-for-everyone-in-one-repository">
254 Share the plugin through a repository
255</h4>
237#### Share the plugin through a repository
256238
257239`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.
258240
from line 273
291273
292274A 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).
293275
294<h2 id="convert-an-existing-claude-setup">
295 Convert an existing `.claude/` setup
296</h2>
276## Convert an existing `.claude/` setup
297277
298278If you already have skills, agents, or hooks under a project's `.claude/` directory, you can move them into a plugin without rewriting them.
299279
300280Run the commands in these steps from the project root, which is the directory that contains `.claude/`, because the `cp` paths are relative to it.
301281
302<Steps>
303 <Step title="Create the plugin structure">
304 Create the plugin directory and its `.claude-plugin/` folder alongside `.claude/`. You can move the plugin anywhere afterwards.
282**1. Create the plugin structure**
305283
306 ```bash theme={null}
307 mkdir -p my-plugin/.claude-plugin
308 ```
284Create the plugin directory and its `.claude-plugin/` folder alongside `.claude/`. You can move the plugin anywhere afterwards.
309285
310 Create `my-plugin/.claude-plugin/plugin.json`:
286```bash theme={null}
287mkdir -p my-plugin/.claude-plugin
288```
311289
312 ```json my-plugin/.claude-plugin/plugin.json theme={null}
313 {
314 "name": "my-plugin",
315 "description": "Migrated from standalone configuration",
316 "version": "1.0.0"
317 }
318 ```
319 </Step>
290Create `my-plugin/.claude-plugin/plugin.json`:
320291
321 <Step title="Copy your existing files">
322 Copy each configuration directory you have to the plugin root, and skip the command for any directory you don't have.
292```json my-plugin/.claude-plugin/plugin.json theme={null}
293{
294 "name": "my-plugin",
295 "description": "Migrated from standalone configuration",
296 "version": "1.0.0"
297}
298```
323299
324 ```bash theme={null}
325 cp -r .claude/commands my-plugin/
326 ```
300**2. Copy your existing files**
327301
328 ```bash theme={null}
329 cp -r .claude/agents my-plugin/
330 ```
302Copy each configuration directory you have to the plugin root, and skip the command for any directory you don't have.
331303
332 ```bash theme={null}
333 cp -r .claude/skills my-plugin/
334 ```
304```bash theme={null}
305cp -r .claude/commands my-plugin/
306```
335307
336 Run `ls -a my-plugin` to confirm that each directory you copied appears next to `.claude-plugin`.
337 </Step>
308```bash theme={null}
309cp -r .claude/agents my-plugin/
310```
338311
339 <Step title="Move your hooks">
340 If you have hooks in `.claude/settings.json` or `.claude/settings.local.json`, create a hooks directory:
312```bash theme={null}
313cp -r .claude/skills my-plugin/
314```
341315
342 ```bash theme={null}
343 mkdir -p my-plugin/hooks
344 ```
316Run `ls -a my-plugin` to confirm that each directory you copied appears next to `.claude-plugin`.
345317
346 Create `my-plugin/hooks/hooks.json` and copy the `hooks` object from your settings file into it. The format is the same.
318**3. Move your hooks**
347319
348 This example shows the shape with one hook that runs a linter on each file Claude writes or edits. Replace the example with your own `hooks` object.
320If you have hooks in `.claude/settings.json` or `.claude/settings.local.json`, create a hooks directory:
349321
350 ```json my-plugin/hooks/hooks.json theme={null}
351 {
352 "hooks": {
353 "PostToolUse": [
354 {
355 "matcher": "Write|Edit",
356 "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix" }]
357 }
358 ]
322```bash theme={null}
323mkdir -p my-plugin/hooks
324```
325
326Create `my-plugin/hooks/hooks.json` and copy the `hooks` object from your settings file into it. The format is the same.
327
328This example shows the shape with one hook that runs a linter on each file Claude writes or edits. Replace the example with your own `hooks` object.
329
330```json my-plugin/hooks/hooks.json theme={null}
331{
332 "hooks": {
333 "PostToolUse": [
334 {
335 "matcher": "Write|Edit",
336 "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix" }]
359337 }
360 }
361 ```
362 </Step>
338 ]
339 }
340}
341```
363342
364 <Step title="Test the migrated plugin">
365 Load the plugin for a session:
343**4. Test the migrated plugin**
366344
367 ```bash theme={null}
368 claude --plugin-dir ./my-plugin
369 ```
345Load the plugin for a session:
370346
371 Check each component under its new name:
347```bash theme={null}
348claude --plugin-dir ./my-plugin
349```
372350
373 * **Skills**: run `/my-plugin:deploy` for a skill that was `/deploy`.
374 * **Subagents**: ask Claude to use the `my-plugin:reviewer` agent for an agent that was `reviewer`.
375 * **Hooks**: trigger the event each hook matches.
351Check each component under its new name:
376352
377 If something is missing, work through [Test and debug](#test-and-debug).
378 </Step>
379</Steps>
353* **Skills**: run `/my-plugin:deploy` for a skill that was `/deploy`.
354* **Subagents**: ask Claude to use the `my-plugin:reviewer` agent for an agent that was `reviewer`.
355* **Hooks**: trigger the event each hook matches.
356
357If something is missing, work through [Test and debug](#test-and-debug).
380358
381359While the originals are still under `.claude/`, they stay loaded alongside the plugin's copies:
382360
No line in this hunk matches that.