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.
These cases are covered on other pages:
- Installing someone else’s plugin: see Install plugins
- Not sure you need a plugin: see 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
- Nothing yet: follow Create your first plugin, then Develop without a marketplace and Test and debug.
- Files under
.claude/already: do the first-plugin walkthrough once to learn the layout, then follow 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 ahelloskill without colliding.
.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, 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.
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.
1
Create the plugin directory
Create the plugin directory, with a
.claude-plugin/ folder inside it to hold the manifest:2
Write the manifest
The manifest is a JSON file named The four fields do this:
plugin.json that tells Claude Code the plugin’s name and describes it. Save this one as my-first-plugin/.claude-plugin/plugin.json:my-first-plugin/.claude-plugin/plugin.json
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 says when to set or omit it.author: who to credit.nameis required inside it;emailandurlare optional.
plugin.json goes inside .claude-plugin/. The skill you add next goes directly under my-first-plugin/, next to that folder.3
Add a skill
This plugin’s one component is a skill. Each skill is a directory under Then create The
skills/ that contains a SKILL.md file. Create the skill’s directory:my-first-plugin/skills/hello/SKILL.md with this content:my-first-plugin/skills/hello/SKILL.md
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.4
Validate the plugin
Check the manifest and the skill’s frontmatter before you run anything: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.5
Run Claude Code with the plugin
Start a session with the plugin loaded:Once Claude Code starts, run the skill:Claude replies with a greeting.
--plugin-dir. To keep working on it without the flag, or to test a .zip build, see Develop without a marketplace.
Share your plugin
A plugin you built with 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
.zipof it, and nothing needs to be published. See 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.
- 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.
Plugin layout
Each kind of component, 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.
The table lists the directories most plugins start with, and the full layout lists the rest.
Develop without a marketplace
You don’t need a marketplace to run a plugin you’re writing. Load it directly from disk or a URL instead:--plugin-dir: loads a directory or.ziparchive for one session.--plugin-url: fetches a.ziparchive from a URL for one session.claude plugin init: scaffolds a plugin under~/.claude/skills/that loads every session.
Load a plugin for one session
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:
From a folder of plugins
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.
/reload-plugins to apply it.
From a URL
When you startclaude from your shell, pass --plugin-url with the address of a .zip archive, such as a build artifact your CI publishes:
/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 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. 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. To test a plugin together with a plugin it depends on, see Test a plugin and its dependency locally.
Make a plugin load in every session
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:
~/.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.
Name the plugin’s skills
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 runclaude 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.
Share the plugin through a repository
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 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:- In your shell, run
claude plugin validate <path>. It checks the manifest and the frontmatter of every skill, agent, and command file, and exits0onValidation passed. Add--strictto fail on warnings too. Exit codes and directory handling are on the plugin commands reference. - In the running session, run
/reload-pluginsto apply edits you made on disk. It prints oneReloaded:line with counts. Then confirm a skill loaded by typing its/plugin-name:skillcommand, or by finding the plugin in the/pluginInstalled tab. - 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. - Back in your shell, run
claude plugin list. It prints session-only and skills-directory plugins in their own sections withStatus: ✔ loadedor the load error. To include the plugin you’re developing, pass--plugin-dirwith its path beforeplugin list.
/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.
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, 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 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.
--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.
The plugin loads but its skills are missing
Theskills/ 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.
The userConfig dialog never appears
The dialog for your plugin’s userConfig 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.
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, starting with Create your first eval suite.
Convert an existing .claude/ setup
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.
1
Create the plugin structure
Create the plugin directory and its Create
.claude-plugin/ folder alongside .claude/. You can move the plugin anywhere afterwards.my-plugin/.claude-plugin/plugin.json:my-plugin/.claude-plugin/plugin.json
2
Copy your existing files
Copy each configuration directory you have to the plugin root, and skip the command for any directory you don’t have.Run
ls -a my-plugin to confirm that each directory you copied appears next to .claude-plugin.3
Move your hooks
If you have hooks in Create
.claude/settings.json or .claude/settings.local.json, create a hooks directory:my-plugin/hooks/hooks.json and copy the hooks object from your settings file into it. The format is the same.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.my-plugin/hooks/hooks.json
4
Test the migrated plugin
Load the plugin for a session:Check each component under its new name:
- Skills: run
/my-plugin:deployfor a skill that was/deploy. - Subagents: ask Claude to use the
my-plugin:revieweragent for an agent that wasreviewer. - Hooks: trigger the event each hook matches.
.claude/, they stay loaded alongside the plugin’s copies:
- Skills and agents: the two sets don’t collide, because the plugin’s skills and agents carry the
my-plugin:prefix./deployand/my-plugin:deployboth work, and Claude seesreviewerandmy-plugin:revieweras two subagents. - Hooks: hooks have no prefix, so a hook that is in both your settings file and
hooks/hooks.jsonruns twice each time its event fires.
.claude/ and remove the hooks object from your settings file.
Next steps
- Plugin components: add agents, hooks, MCP servers, LSP servers, and user configuration to your plugin
- Test plugins with evals: write eval cases and run them with
claude plugin evalto check how reliably the plugin guides Claude’s behavior - Publish a plugin: version it, put it in a marketplace, and submit it to the community marketplace
- Plugins on claude.ai and in Cowork: the same plugin folder installs on claude.ai and in Cowork. Some components are Claude Code-only
- Plugin manifest reference: every
plugin.jsonfield, path rule, and directory - Skills: write the skills your plugin provides
- Anthropic’s plugins in the claude-code repository: complete worked examples of the layout on this page, such as
feature-devandcode-review