How to create a Claude Code plugin, step by step

Build a minimal Claude Code plugin: plugin.json, one skill, claude plugin validate, --plugin-dir, reload and debug, checked against the official docs.

To create a Claude Code plugin you need a directory, a .claude-plugin/plugin.json manifest and at least one component such as a skill. This guide builds the smallest useful one and tests it locally, following the official Create a Claude Code plugin page, which showed a last-modified date of 2026-10-10 when we checked it. Commands and version requirements change between releases, so confirm against the current docs.

What a Claude Code plugin is and when you need one

A plugin bundles skills, agents, hooks and MCP servers under one directory with a manifest. Per the docs, skills, agents, hooks and MCP servers all work standalone in a project or home directory, and you should keep that 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.

The visible change is naming: 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. If you have not written a skill yet, start with Claude Code skills.

Plugin layout: what goes where

Each component type has a fixed place under the plugin root, which is the directory you pass to --plugin-dir. From the plugin layout section:

Location Contents
.claude-plugin/plugin.json The manifest
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 under a top-level "hooks" key
.mcp.json MCP server definitions

The common mistake is putting components in the wrong place. The docs warn that only plugin.json goes inside .claude-plugin/, and components saved there do not load.

Step 1: create the directory and plugin.json

mkdir -p my-first-plugin/.claude-plugin

Save this as my-first-plugin/.claude-plugin/plugin.json, the example from the walkthrough:

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

name is required and becomes the prefix on every skill and agent; do not put spaces in it. description is what users see in /plugin. version is optional, and setting it keeps users on that version until you change it. author needs a name if present. The manifest reference lists every other field.

Step 2: add a skill

mkdir -p my-first-plugin/skills/hello

Create my-first-plugin/skills/hello/SKILL.md:

---
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.

disable-model-invocation: true stops Claude from running the skill on its own; remove it for a skill Claude should trigger itself. The command is the plugin name plus the skill name: /my-first-plugin:hello.

Step 3: validate with claude plugin validate

claude plugin validate ./my-first-plugin

Per the docs, this 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. A failure names the field to fix; the troubleshooting page explains each message.

Step 4: load it with –plugin-dir and run it

claude --plugin-dir ./my-first-plugin

Then, inside the session:

/my-first-plugin:hello

Claude replies with a greeting. The plugin loads only in sessions started with the flag. Per Develop without a marketplace, --plugin-dir accepts a directory or a .zip, can be repeated, and --plugin-url fetches a .zip from a URL. Loading a folder that holds several plugins requires Claude Code v2.1.265 or later. The CLAUDE_CODE_PLUGIN_DIRS environment variable is the option when you cannot add a flag.

To have the plugin load in every session without the flag, the docs describe claude plugin init my-tool, which scaffolds a plugin under ~/.claude/skills/.

Add hooks, agents or an MCP server

Add only the directories you use. Agents go in agents/ as one Markdown file each. Hooks go in hooks/hooks.json with a top-level "hooks" key whose value has the same shape as hooks in a settings file, so the examples in Claude Code hooks examples carry over. MCP servers go in .mcp.json at the plugin root. The plugin components page covers each one, including LSP servers and user configuration.

Test and debug: /reload-plugins, /plugin Errors tab, claude plugin list

The docs give this order of checks when a change does not show up:

  1. claude plugin validate <path> in your shell.
  2. /reload-plugins in the session to apply edits made on disk, then run the skill’s command or look in the /plugin Installed tab.
  3. /plugin, Errors tab, which lists what failed to load and why.
  4. claude plugin list in your shell, which shows Status: ✔ loaded or the load error. Pass --plugin-dir with the plugin path before plugin list to include the plugin you are developing.

For MCP servers use /mcp. For hooks, trigger the event and read the debug log. Three documented failures:

  • <component> path not found in the Errors tab: a path in your manifest points at nothing.
  • Skills missing: skills/ is inside .claude-plugin/, or a skills manifest entry points at a file instead of a directory containing SKILL.md.
  • Nothing loads and no error: --plugin-dir points at a marketplace root instead of one plugin folder.

The userConfig dialog does not appear with --plugin-dir; run /plugin configure <plugin-name>. To check the plugin actually changes Claude’s behavior, the docs point to claude plugin eval and Test plugins with evals.

Share it

The docs list three routes: send the directory or a .zip to a few people, list it in your own marketplace so teammates install it by name, or submit it to Anthropic’s directory. Details are on the publish page. Anthropic also provides the plugin-dev plugin from the claude-plugins-official marketplace, whose /plugin-dev:create-plugin command walks you through designing and validating a larger plugin.

What to change in your setup

The first three items follow the docs; the last two are our own judgment.

  1. Run the walkthrough once to learn the layout, then validate and load your own plugin with claude plugin validate and --plugin-dir.
  2. To convert a project’s .claude/ files, follow Convert an existing .claude/ setup: create my-plugin/.claude-plugin/plugin.json, then cp -r the commands, agents and skills folders you have into the plugin root.
  3. Move hooks by copying the hooks object from .claude/settings.json into my-plugin/hooks/hooks.json; the format is the same. While the originals remain, a hook present in both places runs twice, and skills appear both as /deploy and /my-plugin:deploy. After testing, delete the originals and remove the hooks object from settings.
  4. Our inference: if the setup serves only you or one repository, keeping standalone files is simpler, as the docs themselves suggest.
  5. Our inference: update any saved commands or notes to the prefixed form, such as /my-plugin:deploy, once you switch.

FAQ

Is plugin.json required to create a Claude Code plugin?
No. The manifest is optional. If you load a plugin with --plugin-dir and it has no manifest, Claude Code names the plugin after its directory. When you do write one, name is the only required field.
Where does the skills folder go in a Claude Code plugin?
At the plugin root, next to .claude-plugin/. Only plugin.json goes inside .claude-plugin/; components saved there do not load.
How do I pick up edits without restarting Claude Code?
Run /reload-plugins in the session. It applies the changes you made on disk and prints one Reloaded line with counts.
Does the userConfig dialog show when I load a plugin with --plugin-dir?
No. Run /plugin configure followed by the plugin name in the session to open it.