Issue 15 | Advanced: Plugin Hooks Extension, Performance Benchmarks, and Configuration Reference

⏱ Est. reading time: 20 min Updated on 5/7/2026

15.1 Plugin Hooks System

Hooks are Claude Code's event-driven extension mechanism. Plugins can register Hooks to automatically execute scripts when specific events occur. This tutorial project uses two Plugins: claude-mem (persistent memory) and caveman (token compression).

15.1.1 Hook Event Types

Claude Code supports the following Hook events:

Event Trigger Time Typical Use
Setup When plugin is first installed Install dependencies, initialize data
SessionStart When a new session starts Load context, inject rules
UserPromptSubmit When user sends a message Track status, inject reminders
PreToolUse Before tool call Intercept, log, modify parameters
PostToolUse After tool call Log observation
Stop When agent stops generating Session summary
SessionEnd When session ends Clean up resources

15.1.2 Hook Execution Flow

sequenceDiagram
    participant User as User
    participant CC as Claude Code
    participant Hook as Hook Script
    participant Plugin as Plugin Service

    Note over CC: SessionStart Event
    CC->>Hook: Execute SessionStart hooks
    Hook->>Plugin: Start background service
    Hook-->>CC: Inject context into system-reminder

    loop Each turn of conversation
        User->>CC: Send message
        Note over CC: UserPromptSubmit Event
        CC->>Hook: Execute UserPromptSubmit hooks
        Hook-->>CC: Inject reminder (e.g. caveman mode active)

        Note over CC: Agent calls tool
        CC->>Hook: PreToolUse hooks (e.g. Read)
        Hook->>Plugin: Log file access
        Hook-->>CC: Continue execution

        Note over CC: Tool execution complete
        CC->>Hook: PostToolUse hooks
        Hook->>Plugin: Log observation
        Hook-->>CC: Continue
    end

    Note over CC: Stop Event
    CC->>Hook: Execute Stop hooks
    Hook->>Plugin: Generate session summary

15.1.3 The Two Plugins in This Project

claude-mem β€” Cross-session Persistent Memory

Function: Automatically logs observations from each tool call, loading historical context at the start of the next session.

Hook Configuration (hooks.json):

{
  "hooks": {
    "Setup": [
      { "command": "node scripts/smart-install.js", "timeout": 300 }
    ],
    "SessionStart": [
      { "command": "node scripts/smart-install.js", "timeout": 300 },
      { "command": "node scripts/worker-service.cjs start + health check", "timeout": 60 },
      { "command": "node scripts/worker-service.cjs hook context", "timeout": 60 }
    ],
    "UserPromptSubmit": [
      { "command": "node scripts/worker-service.cjs hook session-init", "timeout": 60 }
    ],
    "PostToolUse": [
      { "matcher": "*", "command": "node scripts/worker-service.cjs hook observation", "timeout": 120 }
    ],
    "PreToolUse": [
      { "matcher": "Read", "command": "node scripts/worker-service.cjs hook file-context", "timeout": 2000 }
    ],
    "Stop": [
      { "command": "node scripts/worker-service.cjs hook summarize", "timeout": 120 }
    ],
    "SessionEnd": [
      { "command": "node scripts/worker-service.cjs hook session-complete", "timeout": 30 }
    ]
  }
}

What Each Hook Does in This Project:

Hook Execution Content Impact on Teams Development
SessionStart Starts local service (localhost:37777), loads historical observations into context team-lead can see decisions and progress from previous sessions
UserPromptSubmit Initialize session tracking Logs at the start of each conversation turn
PostToolUse(*) Logs observation after each tool call Automatically logs all agent operations (Edit, Write, Bash, etc.)
PreToolUse(Read) Logs file context before reading a file Helps understand code structure across sessions
Stop Generates session summary Quickly restores context on next startup

MCP Tools Provided by claude-mem:

Tool Purpose
search Search historical observations
timeline Get context before and after a specific time
get_observations Get observation details
smart_search AST-level code search
smart_outline File structure overview (without reading full content)
build_corpus Build topic knowledge base
query_corpus Query knowledge base

Usage in Teams Development:

# Search historical decisions in team-lead session
/mem-search "δΈΊδ»€δΉˆη”¨ Shunting-yard"

# Build project knowledge base
/knowledge-agent "calculator architecture"

# Smart code search (saves tokens)
/smart-explore "evaluate function"

caveman β€” Token Compression Mode

Function: Injects compression rules into the system prompt, allowing Claude to output with fewer tokens while maintaining technical accuracy.

Hook Configuration (plugin.json):

{
  "hooks": {
    "SessionStart": [
      {
        "command": "node hooks/caveman-activate.js",
        "timeout": 5,
        "statusMessage": "Loading caveman mode..."
      }
    ],
    "UserPromptSubmit": [
      {
        "command": "node hooks/caveman-mode-tracker.js",
        "timeout": 5,
        "statusMessage": "Tracking caveman mode..."
      }
    ]
  }
}

How caveman Works:

SessionStart hook execution:
  1. Writes flag file ~/.claude/.caveman-active (value "full")
  2. Reads compression rules from SKILL.md
  3. Injects the complete rule set into system-reminder

UserPromptSubmit hook execution:
  1. Tracks current caveman status
  2. Injects a brief reminder each turn: "CAVEMAN MODE ACTIVE"

caveman Output Comparison:

Mode Example Output
Normal "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
caveman full "Bug in auth middleware. Token expiry check uses < not <=. Fix:"

Suggestions for Teams Development:

  • team-lead session: Keep caveman active to save tokens
  • Sub-agent: caveman rules will indirectly affect via CLAUDE.md, but sub-agents have their own context
  • When writing code, commit messages, PRs: caveman automatically degrades to normal output

caveman Mode Switching:

/caveman          # View current mode
/caveman full     # Full compression (default)
/caveman lite     # Light compression
/caveman ultra    # Extreme compression
stop caveman      # Turn off
normal mode       # Turn off

15.1.4 Plugin Installation and Management

# View installed plugins
cat ~/.claude/plugins/installed_plugins.json

# Plugin file structure
~/.claude/plugins/
β”œβ”€β”€ installed_plugins.json       # Installation records
β”œβ”€β”€ cache/                       # Plugin code cache
β”‚   β”œβ”€β”€ thedotmack/claude-mem/12.3.2/
β”‚   β”‚   β”œβ”€β”€ .claude-plugin/plugin.json   # Plugin definition
β”‚   β”‚   β”œβ”€β”€ hooks/hooks.json             # Hook configuration
β”‚ β”‚   β”œβ”€β”€ .mcp.json                    # MCP service definition
β”‚   β”‚   └── scripts/                     # Hook scripts
β”‚   └── caveman/caveman/84cc3c14fa1e/
β”‚       β”œβ”€β”€ .claude-plugin/plugin.json   # Plugin definition
β”‚       └── hooks/                       # Hook scripts
β”œβ”€β”€ blocklist.json
└── marketplaces/

15.1.5 Plugin and Teams Interaction

flowchart TD
    subgraph "Plugin Hooks (team-lead session only)"
        CM["claude-mem hooks"]
        CV["caveman hooks"]
    end
    
    subgraph "Sub-Agents (ui-dev / logic-dev / qa-engineer)"
        A1["Independent Claude Code process"]
        A2["Has independent context window"]
        A3["Do Plugin hooks trigger?"]
    end
    
    CM -.->|"SessionStart logs context"| DB[(observation DB)]
    CM -.->|"PostToolUse logs operations"| DB
    CV -.->|"Injects compression rules"| TL["team-lead context"]
    
    A3 -->|"Depends on whether the agent process
has loaded the plugin"| A1 style CM fill:#e1f5fe style CV fill:#fff3e0 style DB fill:#e8f5e9

Key Facts:

  • Plugin hooks run in the team-lead's Claude Code process
  • Sub-agents are independent Claude Code processes and do not inherit the team-lead's plugin configuration
  • This means claude-mem's automatic logging will not capture sub-agent operations
  • Sub-agent operations can only be perceived by the team-lead via inbox files and the shared file system

15.1.6 Custom Hooks (Project Level)

In addition to Plugin hooks, project-level hooks can also be defined in .claude/settings.json:

{
  "permissions": { "allow": ["..."] },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'File being written: $TOOL_INPUT' >> /tmp/write-log.txt"
          }
        ]
      }
    ]
  }
}
Hook Field Description
matcher Matching tool name (e.g., Write, Edit, Bash), * matches all
type Fixed as command
command Shell command to execute
timeout Timeout (seconds)

15.1.7 Context Length Issues

Each agent has an independent context window but shares the file system.

team-lead context: Contains all agent notifications + user conversations + planning files
ui-dev context:    Contains CLAUDE.md + requirement.md + its own code
logic-dev context: Contains CLAUDE.md + requirement.md + its own code
qa-engineer context: Contains all source code + test code

Common Issues:

  • team-lead context is the longest (because it tracks all agents), triggers autocompact first
  • After autocompact, historical messages are compressed, potentially leading to "forgetting" certain agent notifications
  • Solution: Write important status to files (task_plan.md, progress.md), do not rely on context memory

15.1.8 Task Dependency Setting Errors

// ❌ Incorrect: Dependency direction is reversed
// Task #1 is Phase B, Task #2 is Phase A
// Result: Phase A is blocked by Phase B
TaskUpdate({ taskId: "2", addBlockedBy: ["1"] })

// βœ… Correct
// Confirm the correspondence between Task ID and Phase before setting dependencies
TaskUpdate({ taskId: "2", addBlockedBy: ["1"] })  // Phase B blocked by Phase A

Once blockedBy is set, it cannot be removed! You can only tell the agent to ignore it via SendMessage.

15.1.9 Agent Restart After Failure

When an agent stops due to permission issues or other reasons, it needs to be re-spawned:

// A new spawn will create a new agent (e.g., ui-dev-2, ui-dev-3)
// Old agent records remain in team config
// Suggestion: Explicitly state to ignore blockedBy in the new agent prompt

Agent({
  name: "ui-dev-3",  // New name
  mode: "bypassPermissions",
  team_name: "calc-dev",
  prompt: `You are ui-dev, taking over previous work.

Do not call any Skills. Write code directly.
Ignore any blockedBy tags and start directly.

...`
})

15.1.10 Complete Pitfall Checklist

Pitfall Symptom Solution
Permission format error Agent gets stuck when executing Bash commands Bash(cmd:*) uses a colon, not a space
Skill call popup Agent stops after calling a Skill Prohibit Skill calls in the prompt
tmux cannot find agent calc-dev session panes are all zsh Use tmux list-panes -a to find the actual session
Notifications not received Agent completes but team-lead doesn't receive notification Read inbox file to verify
Task dependency reversed Phase A shows as blocked Carefully check Task ID and Phase correspondence before creation
blockedBy cannot be removed Cannot clear after mistakenly setting dependency Tell agent to ignore via SendMessage
Context compression Long sessions lose historical information Write important status to files
Multiple spawn remnants Multiple dead agents in team config Clean up with TeamDelete after completion

15.2 Configuration Reference

15.2.1 Full settings.json

{
  "permissions": {
    "allow": [
      "Bash(ls:*)",
      "Bash(cat:*)",
      "Bash(head:*)",
      "Bash(tail:*)",
      "Bash(find:*)",
      "Bash(grep:*)",
      "Bash(wc:*)",
      "Bash(open:*)",
      "Bash(which:*)",
      "Bash(node:*)",
      "Bash(npx:*)",
      "Bash(npm:*)",
      "Bash(python3:*)",
      "Bash(git:*)",
      "Bash(mkdir:*)",
      "Bash(cp:*)",
      "Bash(mv:*)",
      "Bash(touch:*)",
      "Bash(rm:*)",
      "Bash(echo:*)",
      "Bash(tmux:*)",
      "Bash(bash:*)",
      "Edit",
      "Write",
      "Read",
      "WebSearch",
      "Skill",
      "Agent",
      "SendMessage",
      "TeamCreate",
      "TeamDelete",
      "TaskCreate",
      "TaskGet",
      "TaskList",
      "TaskUpdate"
    ]
  }
}

15.2.2 Agent Prompt Template

You are {agent-name}, responsible for {description of duties}.

Important rules:
- Do not call any Skills (e.g., no /planning-with-files)
- Write code directly, do not create plan files
- Planning is already done in task_plan.md, you are only responsible for implementation

First read requirement.md to understand the requirements.

Task 1: {description}
- {specific requirements}

Task 2: {description}
- {specific requirements}

When each task is completed:
1. TaskUpdate to mark as completed
2. SendMessage to notify team-lead

Working directory: {path}

15.2.3 tmux Common Commands Quick Reference

# Create/Attach
tmux new -s calc-dev          # Create session
tmux attach -t calc-dev       # Attach

# Pane Operations
Ctrl+B β†’ Arrow keys           # Switch pane
Ctrl+B β†’ z                    # Fullscreen current pane (press again to restore)
Ctrl+B β†’ [                    # Enter copy mode (scroll)
q                             # Exit copy mode

# Monitoring
tmux list-sessions            # List all sessions
tmux list-panes -a -F '#{session_name}.#{pane_index} #{pane_current_command}'
tmux switch-client -t 2       # Switch to session 2

# Mouse
:set -g mouse on              # Enable mouse scroll

15.3 Appendix: Teams File System

~/.claude/
β”œβ”€β”€ teams/calc-dev/
β”‚   β”œβ”€β”€ config.json              # Team configuration (members, agent ID, prompt)
β”‚   └── inboxes/                 # Message delivery
β”‚       β”œβ”€β”€ team-lead.json       # team-lead's inbox
β”‚       β”œβ”€β”€ ui-dev.json          # ui-dev's inbox
β”‚       β”œβ”€β”€ logic-dev.json       # logic-dev's inbox
β”‚       └── qa-engineer.json     # qa-engineer's inbox
└── tasks/calc-dev/              # Shared task list
    └── (task files)

Key fields in config.json:

{
  "name": "calc-dev",
  "leadAgentId": "team-lead@calc-dev",
  "members": [
    {
      "name": "ui-dev",
      "agentId": "ui-dev@calc-dev",
      "model": "claude-opus-4-7",
      "tmuxPaneId": "%12",
      "isActive": false
    }
  ]
}
  • isActive: Whether agent is still running (process alive)
  • tmuxPaneId: Agent's tmux pane identifier (but actually runs in another session)

This tutorial is based on a real development session review from 2026-04-25. Project successfully delivered: dual-mode web calculator, 48+ unit tests passed, DOM integration tests + accessibility tests covered.