C Claude Code Internals
EN | ES

Plugins

Plugins extend Claude Code with modular packages that bundle commands, skills, agents, output styles, hooks, MCP servers, LSP servers, channels, and settings. They are installed from a marketplace, loaded via CLI flag, or bundled as built-ins.

9 capability types 6 marketplace source formats 3 plugin sources 11 /plugin subcommands
i One package, many capabilities
A single plugin can contribute any combination of slash commands, skills, agents, output styles, hooks, MCP servers, LSP servers, messaging channels, and settings overrides. The only required file is .claude-plugin/plugin.json. Everything else is optional and auto-detected by directory convention.

Plugin Sources & Storage

Source ID Format Description
Marketplace plugin@marketplace Installed from a marketplace repository
Session (path-based) Loaded via --plugin-dir CLI flag
Built-in plugin@builtin Bundled with Claude Code (currently none registered)

Storage locations

# Cached plugin files
~/.claude/plugins/cache/{marketplace}/{plugin}/{version}/

# Enabled plugins list
~/.claude/settings.json → enabledPlugins: [...]

# Per-plugin options
~/.claude/settings.json → pluginConfigs: {...}

Plugin Directory Structure

my-plugin/
├── .claude-plugin/
│   ├── plugin.json        # Manifest (REQUIRED)
│   └── marketplace.json   # For publishers
├── commands/              # Slash commands (auto-detected)
│   ├── build.md
│   └── deploy.md
├── agents/                # Custom agents (auto-detected)
│   └── test-runner.md
├── skills/                # Skills (auto-detected)
│   └── my-skill/
│       └── SKILL.md
├── output-styles/         # Output styles (auto-detected)
│   └── concise.md
├── hooks/
│   └── hooks.json         # Hook configurations
└── .mcp.json              # MCP servers (optional)

The manifest at .claude-plugin/plugin.json is the only required file. Claude Code auto-detects capabilities from standard directories without manifest declarations.

Auto-detected directories

commands/ Any .md files → slash commands
agents/ Any .md files → custom agent types
skills/ Dirs containing SKILL.md → skills
output-styles/ Any .md files → output styles
hooks/hooks.json Hook configurations
.mcp.json MCP server configurations

Plugin Manifest (plugin.json)

Complete schema

{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "What this plugin does",
  "author": {
    "name": "Author Name",
    "email": "author@example.com",
    "url": "https://example.com"
  },
  "homepage": "https://example.com/plugin",
  "repository": "https://github.com/org/plugin",
  "license": "MIT",
  "keywords": ["testing", "deployment"],
  "dependencies": [
    "other-plugin",
    "dep-plugin@other-marketplace"
  ],

  "commands": { ... },
  "agents": [ ... ],
  "skills": [ ... ],
  "outputStyles": [ ... ],
  "hooks": { ... },
  "mcpServers": { ... },
  "lspServers": { ... },
  "channels": [ ... ],
  "userConfig": { ... },
  "settings": { ... }
}

Metadata fields

Field Req. Description
name Yes kebab-case, no spaces
version No Semver (e.g. "1.2.3")
description No Short description
author No name required if object present
license No SPDX identifier
keywords No Search keywords
dependencies No "name" or "name@marketplace"

Plugin Capabilities (9 Types)

Commands

Slash commands like /build, /deploy.

"commands": {
  "build": {
    "source": "./commands/build.md",
    "description": "Build the project",
    "argumentHint": "[target]",
    "model": "claude-sonnet-4-6",
    "allowedTools": ["Bash", "Read"]
  },
  "about": {
    "content": "# About\nInline content.",
    "description": "Show plugin info"
  }
}

Also accepts: single path string or array of paths.

Agents

Custom AI agent types with their own tools and model.

"agents": [
  "./agents/test-runner.md",
  "./agents/reviewer.md"
]

Agent .md files use the same frontmatter format as user-defined agents (tools, model, disallowedTools).

Skills

Skill directories containing SKILL.md.

"skills": [
  "./skills/my-skill",
  "./skills/another-skill"
]

Auto-detected: any directory in skills/ containing SKILL.md.

Output Styles

Custom response formatting.

---
name: Concise
description: Short, direct responses
keepCodingInstructions: true
forceForPlugin: false
---

Respond in 1-2 sentences. No preamble.

forceForPlugin: true overrides user settings when the plugin is active.

Hooks

Supports all 27 hook events. Three declaration formats:

// Inline object
"hooks": { "PostToolUse": [...] }

// File reference
"hooks": "./hooks/extra.json"

// Array mixing both
"hooks": [
  "./hooks/formatting.json",
  { "Stop": [...] }
]

MCP Servers

External tool integrations. Special variables available:

"mcpServers": {
  "my-server": {
    "type": "stdio",
    "command": "node",
    "args": ["`${plugin_root}`/server.js"],
    "env": {
      "API_KEY": "`${user_config.API_KEY}`"
    }
  }
}

Also accepts: ./file.json, ./server.mcpb, or remote URL.

LSP Servers

Language server protocol for code intelligence.

command — start command (required)
extensionToLanguage — file ext → lang ID (required)
transport — stdio / socket
restartOnCrash / maxRestarts
startupTimeout / shutdownTimeout (ms)

Channels

Messaging channels for KAIROS assistant mode.

"channels": [{
  "server": "my-chat-server",
  "displayName": "Team Chat",
  "userConfig": {
    "CHANNEL_ID": {
      "type": "string",
      "title": "Channel ID"
    }
  }
}]

server must match a key in mcpServers. MCP server must declare claude/channel capability.

Settings

Configuration overrides when the plugin is enabled.

"settings": {
  "agent": {
    "my-agent": {
      "tools": ["Read", "Grep"],
      "model": "haiku"
    }
  }
}

Currently only the "agent" key is supported. Merged into the settings cascade when enabled.

User Configuration (userConfig)

Plugins can define options prompted at enable time. Values are injected as $`${user_config.KEY}` in MCP/LSP configs, hooks, and skill content — and as CLAUDE_PLUGIN_OPTION_KEY env vars in hook commands.

Schema example

"userConfig": {
  "API_KEY": {
    "type": "string",
    "title": "API Key",
    "description": "Your API key",
    "required": true,
    "sensitive": true      // stored in Keychain
  },
  "MAX_RESULTS": {
    "type": "number",
    "title": "Max Results",
    "default": 10,
    "min": 1,
    "max": 100
  },
  "VERBOSE": {
    "type": "boolean",
    "default": false
  },
  "PROJECT_DIR": { "type": "directory" },
  "CONFIG_FILE": { "type": "file" }
}

Config option types

Type Input Extra fields
string Text input multiple (array)
number Numeric min, max
boolean Toggle
directory Path picker
file File picker

Storage

Non-sensitive: settings.json → pluginConfigs[pluginId].options
Sensitive: macOS Keychain or .credentials.json

Marketplace System

Plugin source formats

Type Format
Relative path "./plugins/my-plugin"
NPM { "source": "npm", "package": "@org/plugin", "version": "^1.0" }
Pip { "source": "pip", "package": "my-plugin" }
Git URL { "source": "url", "url": "https://...", "ref": "main" }
GitHub { "source": "github", "repo": "owner/repo", "ref": "v1.0" }
Git subdirectory { "source": "git-subdir", "url": "...", "path": "plugins/my" }

Anti-impersonation

Marketplace names are validated against known registries. A marketplace cannot impersonate another marketplace's plugins. Cross-marketplace dependencies require explicit allowCrossMarketplaceDependenciesOn.

extraKnownMarketplaces in settings.json

{
  "extraKnownMarketplaces": [
    {
      "type": "github",
      "repo": "org/plugins",
      "ref": "main"
    },
    {
      "type": "url",
      "url": "https://plugins.example.com/marketplace.json"
    },
    {
      "type": "npm",
      "package": "@org/marketplace"
    },
    {
      "type": "directory",
      "path": "/local/marketplace"
    },
    {
      "type": "settings",
      "name": "inline-marketplace",
      "plugins": [
        { "name": "my-plugin", "source": "./path" }
      ]
    }
  ]
}

Installation & Loading Flow

Installation (10 steps)

1. User runs /plugin install or enables via menu
2. Resolve marketplace source (extraKnownMarketplaces → defaults)
3. Find plugin entry in marketplace.json, resolve source type
4. Download: npm pack, GitHub sparse checkout, git clone, or pip install
5. Cache at ~/.claude/plugins/cache/{marketplace}/{plugin}/{version}/
6. Validate manifest + auto-detect commands/, agents/, skills/…
7. Check dependencies — detect and error on circular deps
8. Prompt for userConfig values if defined
9. Add to enabledPlugins in settings.json
10. Load plugin capabilities into session

Loading on startup (5 steps)

1. assemblePluginLoadResult() — parallel loading from marketplace, session (--plugin-dir), and built-in sources
2. mergePluginSources() — session plugins override marketplace by name; policy wins over all
3. verifyAndDemote() — unsatisfied deps demote plugin to disabled
4. createPluginFromPath() per plugin — reads manifest, auto-detects dirs, loads hooks and .mcp.json
5. Register capabilities: commands, skills, agents, output styles, hooks, MCP servers, LSP servers

Caching & auto-update

Plugins are version-checked on startup. Cache supports ZIP mode. If forceRemoveDeletedPlugins: true in the marketplace, removed plugins are auto-disabled.

/plugin Command

Aliases: /plugins, /marketplace

Command Description
/plugin Open interactive plugin management menu
/plugin install [name@marketplace] Install a plugin from marketplace
/plugin manage Manage installed plugins (enable/disable/configure)
/plugin uninstall <name> Remove a plugin
/plugin enable <name> Enable a disabled plugin
/plugin disable <name> Disable a plugin
/plugin validate [path] Validate a plugin manifest
/plugin marketplace add <source> Add a marketplace source
/plugin marketplace remove <name> Remove a marketplace source
/plugin marketplace update [name] Update marketplace index
/plugin marketplace list List configured marketplaces

Permissions & Enterprise Policies

Policy controls

Setting Description
allowedPlugins Allowlist of permitted plugins (name or name@marketplace)
deniedPlugins Denylist — always takes precedence over allowlist (fail-closed)
strictPluginOnlyCustomization Lock surfaces (e.g., mcp) to plugin-only — user-configured MCP servers blocked

Plugin MCP server naming

plugin:<pluginName>:<serverName>

Deduplicated against manually-configured servers — manual wins. Plugin MCP servers follow the same permission system as regular MCP tools.

Plugin ID format

// String
"my-plugin@my-marketplace"

// Object with options
{
  "id": "my-plugin@my-marketplace",
  "version": "^1.0.0",
  "required": true,
  "config": { "API_KEY": "value" }
}

Both parts validated: [a-z0-9][-a-z0-9._]*

! No built-in plugins are registered yet
The plugin system scaffolding is complete — manifests, marketplace, installation, loading, and policy controls are all implemented. However, src/plugins/bundled/index.ts currently registers zero built-in plugins. The infrastructure exists for migrating bundled skills to user-toggleable plugin form, but as of the current source the built-in registry is empty.