Plugins package skills, hooks, MCP servers, and agents into reusable, shareable units that you can distribute across teams or publish to community marketplaces. A plugin is a directory with a .claude-plugin/plugin.json manifest — everything else is optional. The namespace system prevents conflicts so multiple plugins can coexist without stepping on each other.
Plugin Structure
Every plugin starts with a single required file: .claude-plugin/plugin.json. The rest of the directory layout mirrors the standard .claude/ project structure, but lives at the plugin root — not inside .claude-plugin/.
my-plugin/├── .claude-plugin/│ └── plugin.json # Required: manifest (ONLY file in this dir)├── commands/ # Slash commands (Markdown files)├── skills/ # Agent Skills (SKILL.md per skill)│ └── code-review/│ └── SKILL.md├── agents/ # Custom agent definitions├── hooks/│ └── hooks.json # Event handlers├── .mcp.json # MCP server configurations├── .lsp.json # LSP server configurations└── settings.json # Default settings (only "agent" key supported)The manifest is the only required file. Here is a minimal plugin.json:
{ "name": "my-plugin", "description": "A description of what this plugin does", "version": "1.0.0", "author": { "name": "Your Name" }, "homepage": "https://github.com/your-org/my-plugin", "repository": "https://github.com/your-org/my-plugin", "license": "MIT"}The name field determines the namespace. A plugin named "my-plugin" exposes all of its skills as /my-plugin:skill-name.
Manifest Fields
plugin.json Fields
| Field | Required | Purpose |
|---|---|---|
name | Yes | Plugin identifier — determines the namespace prefix for all skills |
description | No | Human-readable summary shown in /plugin list |
version | No | Semver string for marketplace distribution and updates |
author | No | Object with name field identifying the creator |
homepage | No | URL for the plugin documentation or landing page |
repository | No | URL to the source repository |
license | No | SPDX license identifier (e.g., MIT, Apache-2.0) |
Commands vs Skills
Both commands and skills live in a plugin, but they serve different purposes and follow different conventions.
Commands vs Skills in Plugins
| Aspect | Commands | Skills |
|---|---|---|
| Invocation | /command-name (standalone) or /plugin:command (namespaced) | /plugin-name:skill-name (always namespaced) |
| Scope | Quick actions, UI helpers, session management | Multi-step agent tasks that use tools and reasoning |
| Naming | Markdown files in commands/ directory | SKILL.md files inside skills/<name>/ subdirectories |
| Arguments | Text after the command name | $ARGUMENTS placeholder in SKILL.md captures user input |
| Complexity | Single prompt, no tool orchestration | Full agent loop with tool calls and multi-turn reasoning |
Install and Manage
Use the /plugin family of slash commands to manage plugins from inside a Claude session.
After editing plugin files during a development session, run /reload-plugins to pick up your changes. The CLI does not watch plugin files for changes automatically.
Namespacing
Plugin skills are always prefixed with the plugin name, separated by a colon. This prevents naming conflicts — two plugins can both define a skill called lint without clashing.
Namespace Resolution
| Plugin Name | Skill Name | Invocation |
|---|---|---|
review-tools | security-check | /review-tools:security-check |
review-tools | perf-check | /review-tools:perf-check |
db-utils | migrate | /db-utils:migrate |
You cannot opt out of namespacing. Plugin skills are never available as bare /skill-name — the prefix is mandatory.
Standalone vs Plugin
Choosing between a standalone skill in .claude/skills/ and a plugin depends on who needs the skill and how it will be distributed.
When to Use Which
| Approach | Skill Invocation | Best For |
|---|---|---|
Standalone (.claude/) | /hello | Personal workflows, project-specific tools, quick experiments |
| Plugin | /plugin-name:hello | Team sharing, community distribution, versioned releases |
Local Development
During development, use the --plugin-dir flag to load your plugin from a local directory without installing it:
You can load multiple plugins at once by repeating the flag:
claude --plugin-dir ./plugin-one --plugin-dir ./plugin-twoWhen a local plugin and a marketplace plugin share the same name, the local --plugin-dir version takes precedence. However, managed force-enabled plugins from organization settings always win over --plugin-dir.
Plugin Hooks
Plugins can define hooks in hooks/hooks.json at the plugin root. There is a critical security restriction: plugin hooks only support http and prompt handler types. The command and agent handler types are blocked to prevent arbitrary code execution from third-party plugins.
{ "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "prompt", "prompt": "Check if this bash command is safe: $ARGUMENTS", "timeout": 15 } ] } ]}When both a plugin and the project define hooks, both run — project hooks execute first.
Plugin Precedence
Loading Priority
| Scenario | Winner |
|---|---|
—plugin-dir vs marketplace install (same name) | —plugin-dir (local) |
Managed force-enabled plugin vs —plugin-dir | Managed plugin |
| Plugin hooks vs project hooks | Both run (project hooks first) |
| Plugin skills vs standalone skills | No conflict (different namespaces) |
Only plugin.json goes inside the .claude-plugin/ directory. Everything else — skills/, commands/, agents/, hooks/, .mcp.json, .lsp.json — lives at the plugin root. Putting them inside .claude-plugin/ is a common mistake that silently breaks the plugin.
Commands and skills are separate concepts. Commands are simple slash-invoked prompts (Markdown files in commands/). Skills are multi-step agent tasks (SKILL.md files in skills/<name>/). Mixing them up — for example, putting a SKILL.md in the commands directory — will cause it to be ignored or misinterpreted.
The plugin system requires Claude Code version 1.0.33 or later. Earlier versions ignore plugin directories entirely with no error message. Run claude —version to verify.
After editing plugin files during development, run /reload-plugins to pick up your changes. File watchers do not detect plugin modifications automatically.
Config Resolution Matrix
Different configuration types have different inheritance rules when working in subdirectories. This table summarizes experimentally verified behavior (tested 2026-03-19):
What Inherits from Parent Directories?
| Config Type | Walks Up? | Blocked by .git? | Isolation Mechanism |
|---|---|---|---|
CLAUDE.md | Yes (merges full hierarchy) | No | Separate repositories only |
Skills (.claude/skills/) | Yes | Yes | mkdir .git or —disable-slash-commands |
MCP configs (.mcp.json) | Yes (merges) | No | —strict-mcp-config |
Hooks (settings.json) | No | N/A | Already local-only |
Permissions (settings.json) | No | N/A | Already local-only |
Key implications for monorepo teams:
- A root-level
CLAUDE.mdis visible to every subfolder session with no opt-out. Keep root-level instructions generic. - A root-level
.mcp.jsonshares its servers with all subfolder sessions. Use--strict-mcp-configin subfolders that need isolation. - Parent directory hooks and permission deny rules do not propagate to subfolder sessions. Each subfolder must define its own security hooks.
- An empty child config does not shadow or block parent inheritance. There is no shadowing mechanism for
CLAUDE.mdor.mcp.json.