Skip to content

Plugin System

From skill files to distributable extension packages — Plugins are the top-level container in Claude Code’s extension architecture, solving not “how to define a capability” but “how to discover, trust, install, update, and uninstall a set of capabilities.”

Core Question

Skills let you define a reusable prompt template in Markdown. But when you want to package a set of Skills, several Hooks, a pair of MCP servers, and a custom command suite into a distributable product, you need Plugins.

Plugins answer harder questions: How do a thousand users use the same plugin without interfering? How do you verify safety before installation? How do you upgrade without breaking existing config?

Subsystem Overview

MetricValue
Core service files3 main files + Schema definitions
Directorysrc/services/plugins/, src/utils/plugins/
MaturityIntegrated (merged into trunk)
Manifest Schema~1,700 lines of Zod definitions

Plugin Manifest Architecture

Everything starts with the plugin.json manifest. Its validation Schema is the largest single Schema definition in Claude Code (schemas.ts ~1,681 lines), composed of 11 sub-schemas:

Sub-SchemaDescription
MetadataName, version, author, keywords, dependencies (required)
HooksHook definitions (hooks.json or inline)
CommandsCustom commands (commands/*.md)
AgentsCustom agent definitions
SkillsSkill files (skills/**/SKILL.md)
Output StylesOutput style customization
ChannelsMCP message injection
MCP ServersMCP server configuration
LSP ServersLSP server configuration
SettingsPreset values
User ConfigInstallation-time user prompts

All sub-schemas except Metadata use .partial() — a hooks-only plugin and a full-toolchain plugin share the same format.

    graph TB
    M["plugin.json<br/>PluginManifest"]
    M --> Meta["Metadata<br/>name, version, author"]
    M --> Hooks["Hooks<br/>Lifecycle interception"]
    M --> Cmds["Commands<br/>Custom commands"]
    M --> Agents["Agents<br/>Agent definitions"]
    M --> Skills["Skills<br/>SKILL.md files"]
    M --> MCP["MCP Servers<br/>Tool services"]
    M --> LSP["LSP Servers<br/>Language services"]
    M --> Settings["Settings<br/>Preset configs"]

    style M fill:#e3f2fd
    style Meta fill:#fff3e0
  

Lifecycle Management

FileResponsibility
PluginInstallationManager.tsInstall, uninstall, version management
pluginCliCommands.tsCLI entry points (install / uninstall / list)
pluginOperations.tsRuntime loading and operations

Installation Sources

Plugins can be installed from multiple sources: local directories, Git repositories, npm packages, marketplace, etc. The installation process includes a validation chain:

  1. Manifest validation: Full Zod Schema verification
  2. Path safety: All file paths must start with ./, cannot contain ..
  3. Name protection: Cannot impersonate official marketplace names (anthropic-marketplace etc. are reserved)
  4. Version isolation: Different versions use independent cache directories

Error Handling

Plugin loading uses 25 discriminated union error types. This is not simple try/catch — each failure mode has structured error information for diagnosis and recovery.

Plugins vs Skills

DimensionSkillsPlugins
GranularitySingle prompt templateCapability bundle container
DistributionProject-level .claude/skills/Cross-project installable package
LifecycleDiscovery → InvocationInstall → Load → Run → Update → Uninstall
Trust boundaryProject-level trustRequires signature and source verification
ComposabilitySingle skillSkills + commands + hooks + MCP + LSP
Definition formatSKILL.md (YAML + Markdown)plugin.json (Zod Schema validated)

Key Design Decisions

Progressive Composition

Plugins don’t require implementing all 11 component types. The .partial() design lets the simplest plugin need only a metadata plus a hooks config, while the most complex can provide a complete toolchain.

Marketplace Name Reservation

ALLOWED_OFFICIAL_MARKETPLACE_NAMES:
  claude-code-marketplace, claude-code-plugins,
  claude-plugins-official, anthropic-marketplace,
  anthropic-plugins, agent-skills, ...

Reserved name mechanism + inline/builtin special name protection prevents third-party plugins from impersonating official sources.

Versioned Cache Isolation

Different plugin versions use independent cache directories, avoiding state contamination during upgrades. This is especially important for stateful MCP servers and LSP servers.

Lessons for Agent Builders

PatternDescription
Containerized extensionsDon’t make users manually assemble skills + hooks + config — provide a unified installation entry
Schema as documentation1,700 lines of Zod Schema is itself the most precise plugin format documentation
Fail closed25 error types mean every failure has an explicit handling path, not a generic Error
Name governanceEcosystems need name protection from day one
Progressive complexityKeep simple use cases simple (one hook), make complex use cases possible (full toolchain)

Path Evidence

PathRole
src/services/plugins/Plugin service directory
src/services/plugins/PluginInstallationManager.tsInstallation manager
src/services/plugins/pluginCliCommands.tsCLI entry points
src/services/plugins/pluginOperations.tsRuntime operations
src/utils/plugins/schemas.tsManifest Schema definitions (~1,681 lines)
src/utils/plugins/Plugin utility functions

Further Reading

  1. Tool Plane — How plugin-registered tools enter the tool system
  2. Execution Governance — Plugin trust boundaries
  3. Signals & Extensions — Plugins’ position in the extension fabric
  4. Memory System — Plugin-memory interaction