Create custom plugins to extend Claude Code with slash commands, agents, hooks, Skills, and MCP servers.
Plugins let you extend Claude Code with custom functionality that can be shared across projects and teams. This guide covers creating your own plugins with slash commands, agents, Skills, hooks, and MCP servers.
Looking to install existing plugins? See Discover and install plugins. For complete technical specifications, see Plugins reference.
Claude Code supports two ways to add custom slash commands, agents, and hooks:
| Approach | Slash command names | Best for |
|---|---|---|
Standalone (.claude/ directory) |
/hello |
Personal workflows, project-specific customizations, quick experiments |
Plugins (directories with .claude-plugin/plugin.json) |
/plugin-name:hello |
Sharing with teammates, distributing to community, versioned releases, reusable across projects |
Use standalone configuration when:
/hello or /reviewUse plugins when:
/my-plugin:hello (namespacing prevents conflicts between plugins)
Start with standalone configuration in .claude/ for quick iteration, then convert to a plugin when you're ready to share.
This quickstart walks you through creating a plugin with a custom slash command. You'll create a manifest (the configuration file that defines your plugin), add a slash command, and test it locally using the --plugin-dir flag.
claude --version to check)
If you don't see the /plugin command, update Claude Code to the latest version. See Troubleshooting for upgrade instructions.
Every plugin lives in its own directory containing a manifest and your custom commands, agents, or hooks. Create one now:
```bash theme={null}
mkdir my-first-plugin
```
The manifest file at `.claude-plugin/plugin.json` defines your plugin's identity: its name, description, and version. Claude Code uses this metadata to display your plugin in the plugin manager.
Create the `.claude-plugin` directory inside your plugin folder:
```bash theme={null}
mkdir my-first-plugin/.claude-plugin
```
Then create `my-first-plugin/.claude-plugin/plugin.json` with this content:
```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"
}
}
```
| Field | Purpose |
| :------------ | :--------------------------------------------------------------------------------------------------------------------- |
| `name` | Unique identifier and slash command namespace. Slash commands are prefixed with this (e.g., `/my-first-plugin:hello`). |
| `description` | Shown in the plugin manager when browsing or installing plugins. |
| `version` | Track releases using [semantic versioning](/en/plugins-reference#version-management). |
| `author` | Optional. Helpful for attribution. |
For additional fields like `homepage`, `repository`, and `license`, see the [full manifest schema](/en/plugins-reference#plugin-manifest-schema).
Slash commands are Markdown files in the `commands/` directory. The filename becomes the slash command name, prefixed with the plugin's namespace (`hello.md` in a plugin named `my-first-plugin` creates `/my-first-plugin:hello`). The Markdown content tells Claude how to respond when someone runs the slash command.
Create a `commands` directory in your plugin folder:
```bash theme={null}
mkdir my-first-plugin/commands
```
Then create `my-first-plugin/commands/hello.md` with this content:
```markdown my-first-plugin/commands/hello.md theme={null}
---
description: Greet the user with a friendly message
---
# Hello Command
Greet the user warmly and ask how you can help them today.
```
Run Claude Code with the `--plugin-dir` flag to load your plugin:
```bash theme={null}
claude --plugin-dir ./my-first-plugin
```
Once Claude Code starts, try your new command:
```shell theme={null}
/my-first-plugin:hello
```
You'll see Claude respond with a greeting. Run `/help` to see your command listed under the plugin namespace.
<Note>
**Why namespacing?** Plugin slash commands are always namespaced (like `/greet:hello`) to prevent conflicts when multiple plugins have commands with the same name.
To change the namespace prefix, update the `name` field in `plugin.json`.
</Note>
Make your slash command dynamic by accepting user input. The `$ARGUMENTS` placeholder captures any text the user provides after the slash command.
Update your `hello.md` file:
```markdown my-first-plugin/commands/hello.md theme={null}
---
description: Greet the user with a personalized message
---
# Hello Command
Greet the user named "$ARGUMENTS" warmly and ask how you can help them today. Make the greeting personal and encouraging.
```
Restart Claude Code to pick up the changes, then try the command with your name:
```shell theme={null}
/my-first-plugin:hello Alex
```
Claude will greet you by name. For more argument options like `$1`, `$2` for individual parameters, see [Slash commands](/en/slash-commands).
You've successfully created and tested a plugin with these key components:
.claude-plugin/plugin.json): describes your plugin's metadatacommands/): contains your custom slash commands$ARGUMENTS): captures user input for dynamic behavior
The --plugin-dir flag is useful for development and testing. When you're ready to share your plugin with others, see Create and distribute a plugin marketplace.
You've created a plugin with a slash command, but plugins can include much more: custom agents, Skills, hooks, MCP servers, and LSP servers.
Common mistake: Don't put commands/, agents/, skills/, or hooks/ inside the .claude-plugin/ directory. Only plugin.json goes inside .claude-plugin/. All other directories must be at the plugin root level.
| Directory | Location | Purpose |
|---|---|---|
.claude-plugin/ |
Plugin root | Contains only plugin.json manifest (required) |
commands/ |
Plugin root | Slash commands as Markdown files |
agents/ |
Plugin root | Custom agent definitions |
skills/ |
Plugin root | Agent Skills with SKILL.md files |
hooks/ |
Plugin root | Event handlers in hooks.json |
.mcp.json |
Plugin root | MCP server configurations |
.lsp.json |
Plugin root | LSP server configurations for code intelligence |
Next steps: Ready to add more features? Jump to Develop more complex plugins to add agents, hooks, MCP servers, and LSP servers. For complete technical specifications of all plugin components, see Plugins reference.
Once you're comfortable with basic plugins, you can create more sophisticated extensions.
Plugins can include Agent Skills to extend Claude's capabilities. Skills are model-invoked: Claude automatically uses them based on the task context.
Add a skills/ directory at your plugin root with Skill folders containing SKILL.md files:
my-plugin/
├── .claude-plugin/
│ └── plugin.json
└── skills/
└── code-review/
└── SKILL.md
Each SKILL.md needs frontmatter with name and description fields, followed by instructions:
name: code-review
When reviewing code, check for:
After installing the plugin, restart Claude Code to load the Skills. For complete Skill authoring guidance including progressive disclosure and tool restrictions, see Agent Skills.
For common languages like TypeScript, Python, and Rust, install the pre-built LSP plugins from the official marketplace. Create custom LSP plugins only when you need support for languages not already covered.
LSP (Language Server Protocol) plugins give Claude real-time code intelligence. If you need to support a language that doesn't have an official LSP plugin, you can create your own by adding an .lsp.json file to your plugin:
```json .lsp.json theme={null} { "go": {
"command": "gopls",
"args": ["serve"],
"extensionToLanguage": {
".go": "go"
}
} }
Users installing your plugin must have the language server binary installed on their machine.
For complete LSP configuration options, see [LSP servers](/en/plugins-reference#lsp-servers).
### Organize complex plugins
For plugins with many components, organize your directory structure by functionality. For complete directory layouts and organization patterns, see [Plugin directory structure](/en/plugins-reference#plugin-directory-structure).
### Test your plugins locally
Use the `--plugin-dir` flag to test plugins during development. This loads your plugin directly without requiring installation.
```bash theme={null}
claude --plugin-dir ./my-plugin
As you make changes to your plugin, restart Claude Code to pick up the updates. Test your plugin components:
/command-name/agentsYou can load multiple plugins at once by specifying the flag multiple times:
bash theme={null}
claude --plugin-dir ./plugin-one --plugin-dir ./plugin-two
If your plugin isn't working as expected:
.claude-plugin/When your plugin is ready to share:
README.md with installation and usage instructionsplugin.jsonOnce your plugin is in a marketplace, others can install it using the instructions in Discover and install plugins.
For complete technical specifications, debugging techniques, and distribution strategies, see Plugins reference.
If you already have custom commands, Skills, or hooks in your .claude/ directory, you can convert them into a plugin for easier sharing and distribution.
Create a new plugin directory:
```bash theme={null}
mkdir -p my-plugin/.claude-plugin
```
Create the manifest file at `my-plugin/.claude-plugin/plugin.json`:
```json my-plugin/.claude-plugin/plugin.json theme={null}
{
"name": "my-plugin",
"description": "Migrated from standalone configuration",
"version": "1.0.0"
}
```
Copy your existing configurations to the plugin directory:
```bash theme={null}
# Copy commands
cp -r .claude/commands my-plugin/
# Copy agents (if any)
cp -r .claude/agents my-plugin/
# Copy skills (if any)
cp -r .claude/skills my-plugin/
```
If you have hooks in your settings, create a hooks directory:
```bash theme={null}
mkdir my-plugin/hooks
```
Create `my-plugin/hooks/hooks.json` with your hooks configuration. Copy the `hooks` object from your `.claude/settings.json` or `settings.local.json`—the format is the same:
```json my-plugin/hooks/hooks.json theme={null}
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{ "type": "command", "command": "npm run lint:fix $FILE" }]
}
]
}
}
```
Load your plugin to verify everything works:
```bash theme={null}
claude --plugin-dir ./my-plugin
```
Test each component: run your commands, check agents appear in `/agents`, and verify hooks trigger correctly.
Standalone (.claude/) |
Plugin |
|---|---|
| Only available in one project | Can be shared via marketplaces |
Files in .claude/commands/ |
Files in plugin-name/commands/ |
Hooks in settings.json |
Hooks in hooks/hooks.json |
| Must manually copy to share | Install with /plugin install |
After migrating, you can remove the original files from .claude/ to avoid duplicates. The plugin version will take precedence when loaded.
Now that you understand Claude Code's plugin system, here are suggested paths for different goals:
To find navigation and other pages in this documentation, fetch the llms.txt file at: https://code.claude.com/docs/llms.txt