PRD 1 of 8

Building a Claude Code
Plugin Ecosystem

A declarative plugin architecture with a critical two-layer hook system, skills, agents, commands, and MCP server integrations — no build system required.

Plugin Ecosystem Architecture

1. Problem Statement

Claude Code ships with powerful built-in capabilities, but every environment is different. Teams need custom hooks for coding standards, security teams need audit trails, and developers need persistent memory and domain-specific agents. Without an extension mechanism, every customization requires forking Claude Code itself.

The plugin ecosystem provides a declarative, file-based extension model. Drop files in a directory — markdown for agents, YAML for config, shell scripts and Python for hooks. No compilation, no package registry, no build toolchain.

Critical Architecture Detail: Two-Layer Hooks

Claude Code reads hooks from settings.json for PostToolUse and Stop events — not from plugin hooks.json. Plugins that only wire hooks in their manifest will silently fail to fire critical lifecycle hooks. The solution: wire hooks in both settings.json (what CC reads) and plugin hooks.json (what the plugin lifecycle manages). This is the single most important implementation detail.

2. Architecture Overview

Plugin Directory Structure

~/.claude/plugins/local/my-plugin/
├── plugin.json              # Manifest: name, version, hooks, config schema
├── CLAUDE.md                # Plugin-specific instructions
├── hooks/
│   ├── hooks.json           # Plugin-layer hook definitions
│   └── *.py / *.sh          # Hook implementations
├── skills/
│   └── my-skill/
│       ├── SKILL.md         # Skill definition with frontmatter
│       └── references/      # Domain knowledge files
├── agents/
│   └── my-agent.md          # Agent persona definition
└── commands/
    └── my-command.md         # Slash command definition

Two-Layer Hook Wiring

Layer 1: settings.json

What Claude Code actually reads for all event types. Required for PostToolUse, Stop, SessionEnd, and Notification events. Scripts referenced here fire reliably.

Layer 2: plugin hooks.json

What the plugin system manages. Works for SessionStart and PreToolUse. Provides plugin-scoped configuration, matchers, and timeouts. Both layers can reference the same script files.

7 Hook Event Types

EventWhenCan Block?Where to Wire
SessionStartSession beginsNoEither layer
UserPromptSubmitUser sends messageNosettings.json
PreToolUseBefore tool executionYesEither layer
PostToolUseAfter tool executionNosettings.json (required)
PreCompactBefore context compressionNoplugin hooks.json
StopSession endsNosettings.json (required)
SessionEndAfter session cleanupNosettings.json

4 Active Plugins (Reference Implementation)

PluginVersionAgentsSkillsCommandsFocus
Conductor1.0.02971Multi-agent orchestration with tiered workflows
Claude Memory1.0.01660-tool MCP server, 12 hooks, vector memory lifecycle
Governance0.1.03Identity manifests, audit bus, policy engine, trust broker
Context Guard3.0.04-tier context window monitoring with velocity prediction

3. Key Components

3.1 Plugin Manifest (plugin.json)

{
  "name": "my-plugin",
  "description": "What this plugin does",
  "version": "1.0.0",
  "author": { "name": "Your Name" },
  "hooks": "./hooks/hooks.json",
  "configuration": {
    "threshold": { "type": "number", "default": 0.9 },
    "enabled_features": { "type": "array", "default": ["audit", "dedup"] }
  }
}

3.2 Hook Implementation Patterns

Tool Facade (PreToolUse)

Intercepts search tools (Grep, Glob) and serves memory content as the tool result. Claude gets the answer without needing to decide to check memory. The memory-first-gate.sh script embeds the search query, queries Qdrant, and if a match exists, returns it directly.

Constitutional Observer (PreToolUse)

Fires on every tool call. Checks actions against session objectives for scope drift, target drift, and destructive operations. Buffers flags to JSONL. Must complete in <2s and never block.

Task Outcome (Stop)

Reads tool chain buffer, classifies task type, calculates success metrics, stores to heuristics collection. Feeds self-assessment at next session start. Must run before flush_insights.py.

Auto-Recall (SessionStart)

Queries Qdrant for memories relevant to the current working directory. Injects top matches into the session context. Also triggers self-assessment and sets constitutional objectives.

3.3 Skills, Agents, Commands

4. Requirements

REQ-PLG-001 Plugin manifests shall be validated against a JSON schema at startup, rejecting malformed plugins with clear errors.
REQ-PLG-002 Critical hooks (PostToolUse, Stop, SessionEnd) shall be wired in settings.json where CC reliably reads them, not only in plugin hooks.json.
REQ-PLG-003 Hook matchers shall support regex on tool_name and glob patterns on file paths to filter which tool calls trigger the hook.
REQ-PLG-004 PreToolUse hooks shall support three return modes: allow (proceed), block (halt with reason), and modify (alter parameters).
REQ-PLG-005 Skills shall be discoverable via the Skill tool and lazy-loaded (content loaded on invocation, not startup).
REQ-PLG-006 Agent definitions shall declare capabilities (tools, trust level, data classification) enforceable by governance at runtime.
REQ-PLG-007 Plugins shall support bundling MCP server configurations via .mcp.json that auto-register when the plugin loads.
REQ-PLG-008 Configuration shall cascade: global settings.json → project settings → plugin plugin.json, with each level overriding the previous.
REQ-PLG-009 Failed hooks shall not crash the session — errors are logged and non-blocking hooks proceed (fail-open).
REQ-PLG-010 Plugins shall persist state across sessions via SessionStart (load) and Stop (save) hooks without requiring an external database.
REQ-PLG-011 Hook execution order shall be deterministic across plugins, with priority configurable.
REQ-PLG-012 Both hook layers (settings.json + plugin hooks.json) shall be able to reference the same script files, avoiding duplication.

5. Prompt to Build It

Build a Claude Code plugin system:

1. PLUGIN MANIFEST (plugin.json):
   - JSON schema: name, description, version, author, hooks ref, config schema
   - Validation at startup with clear rejection messages

2. TWO-LAYER HOOK SYSTEM:
   - Layer 1 (settings.json): Wire PostToolUse, Stop, SessionEnd, Notification here
     because CC only reads these events from settings.json
   - Layer 2 (plugin hooks.json): Wire SessionStart, PreToolUse, PreCompact here
     for plugin-scoped configuration and matchers
   - Both layers can reference the same script files
   - 7 events: SessionStart, UserPromptSubmit, PreToolUse, PostToolUse,
     PreCompact, Stop, SessionEnd
   - Matchers: regex on tool_name, glob on file paths
   - PreToolUse returns: allow / block (with reason) / modify (altered params)
   - Error isolation: failed hooks log but don't crash

3. SKILLS (skills/*/SKILL.md):
   - YAML frontmatter (name, description, version)
   - references/ subdirectory for domain knowledge
   - Lazy loading: discovered at startup, content loaded on Skill invocation

4. AGENTS (agents/*.md):
   - Markdown personas with frontmatter: name, description, tools
   - Capability declarations for governance integration
   - Dispatched via Agent tool with subagent_type

5. COMMANDS (commands/*.md):
   - Slash command definitions with argument schemas
   - Invoked by /command-name in prompt

6. MCP INTEGRATION:
   - .mcp.json in plugin root for MCP server configuration
   - Auto-registered at plugin startup

7. CONFIGURATION CASCADE:
   - Global settings.json → Project settings → Plugin plugin.json
   - Each level overrides previous

Create a scaffold at ~/.claude/plugins/local/my-plugin/ with examples of each.

6. Design Decisions

Two-Layer Hooks over Plugin-Only

CC's hook loading has a gap: PostToolUse and Stop from plugin hooks.json don't reliably fire. Wiring in settings.json guarantees execution. Both layers reference the same scripts — no duplication, just reliable delivery.

Declarative over Imperative

No build system, compilation, or package registry. Drop files in a directory. Markdown for agents/skills/commands, JSON for manifests, Python/bash for hooks. Eliminates toolchain friction.

Tool Facades over Explicit Checks

Rather than hoping Claude "decides" to check memory, the Tool Facade pattern intercepts search tools and serves memory results directly. This architectural pattern is reusable for any data source a plugin wants to inject transparently.

Fail-Open Hook Execution

Non-blocking hooks that fail (error, timeout) let the tool call proceed. Only PreToolUse hooks returning "block" can halt execution. A buggy plugin can't make CC unusable.

7. Integration Points

→ Agent Governance

Governance validates hook actions through its policy engine. PreToolUse hooks that allow elevated tools are checked against agent manifests. PostToolUse events feed the governance audit bus.

→ Memory System

Memory uses all 7 event types across both hook layers. MCP tools are exposed through the plugin's .mcp.json. The Tool Facade pattern emerged from the memory plugin's need to inject context transparently.

→ Context Guard

Context monitoring uses PostToolUse (wired in settings.json) to track token consumption. Velocity prediction and escalation levels all depend on reliable PostToolUse firing.

→ Multi-Agent Orchestration

Conductor defines 29 agents as markdown files, orchestrates via state machine hooks, and validates state through PostToolUse schema checks. The plugin architecture makes the entire orchestration system portable.