第 15 期 | 进阶:Plugin Hooks 扩展、性能基准与配置参考

⏱ 预计阅读 20 分钟 更新于 2026/5/7
💡 进群学习加 wx: agentupdate
(申请发送: agentupdate)

15.1 Plugin Hooks 系统

Hooks 是 Claude Code 的事件驱动扩展机制。Plugin 可以注册 Hook,在特定事件发生时自动执行脚本。本教程项目使用了两个 Plugin:claude-mem(持久记忆)和 caveman(token 压缩)。

15.1.1 Hook 事件类型

Claude Code 支持以下 Hook 事件:

事件 触发时机 典型用途
Setup 插件首次安装时 安装依赖、初始化数据
SessionStart 新会话启动时 加载上下文、注入规则
UserPromptSubmit 用户发送消息时 追踪状态、注入提醒
PreToolUse 工具调用前 拦截、记录、修改参数
PostToolUse 工具调用后 记录 observation
Stop agent 停止生成时 会话摘要
SessionEnd 会话结束时 清理资源

15.1.2 Hook 执行流程

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

    Note over CC: SessionStart 事件
    CC->>Hook: 执行 SessionStart hooks
    Hook->>Plugin: 启动后台服务
    Hook-->>CC: 注入 context 到 system-reminder

    loop 每轮对话
        User->>CC: 发送消息
        Note over CC: UserPromptSubmit 事件
        CC->>Hook: 执行 UserPromptSubmit hooks
        Hook-->>CC: 注入提醒(如 caveman mode active)

        Note over CC: Agent 调用工具
        CC->>Hook: PreToolUse hooks (如 Read)
        Hook->>Plugin: 记录文件访问
        Hook-->>CC: 继续执行

        Note over CC: 工具执行完成
        CC->>Hook: PostToolUse hooks
        Hook->>Plugin: 记录 observation
        Hook-->>CC: 继续
    end

    Note over CC: Stop 事件
    CC->>Hook: 执行 Stop hooks
    Hook->>Plugin: 生成会话摘要

15.1.3 本项目的两个 Plugin

claude-mem — 跨会话持久记忆

作用: 自动记录每次工具调用的 observation,在下次会话启动时加载历史上下文。

Hook 配置(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 }
    ]
  }
}

各 Hook 在本项目中做了什么:

Hook 执行内容 对 Teams 开发的影响
SessionStart 启动本地服务(localhost:37777),加载历史 observation 到上下文 team-lead 能看到之前会话的决策和进度
UserPromptSubmit 初始化 session tracking 每轮对话开始时记录
PostToolUse(*) 每次工具调用后记录 observation 自动记录所有 agent 的操作(Edit、Write、Bash 等)
PreToolUse(Read) 读取文件前记录文件上下文 帮助跨会话理解代码结构
Stop 生成会话摘要 下次启动时快速恢复上下文

claude-mem 提供的 MCP 工具:

工具 用途
search 搜索历史 observation
timeline 获取某个时间点前后的上下文
get_observations 获取 observation 详情
smart_search AST 级代码搜索
smart_outline 文件结构概览(不读全文)
build_corpus 构建 topic 知识库
query_corpus 查询知识库

在 Teams 开发中的使用:

# 在 team-lead 会话中搜索历史决策
/mem-search "为什么用 Shunting-yard"

# 构建项目知识库
/knowledge-agent "calculator architecture"

# 智能代码搜索(省 token)
/smart-explore "evaluate function"

caveman — Token 压缩模式

作用: 在 system prompt 中注入压缩规则,让 Claude 用更少的 token 输出,同时保持技术准确性。

Hook 配置(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..."
      }
    ]
  }
}

caveman 的工作原理:

SessionStart hook 执行:
  1. 写 flag 文件 ~/.claude/.caveman-active(值为 "full")
  2. 读取 SKILL.md 中的压缩规则
  3. 将完整规则集注入到 system-reminder 中

UserPromptSubmit hook 执行:
  1. 追踪当前 caveman 状态
  2. 每轮对话注入简短提醒:"CAVEMAN MODE ACTIVE"

caveman 输出对比:

模式 示例输出
正常 "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:"

在 Teams 开发中的建议:

  • team-lead 会话:保持 caveman active,节省 token
  • 子 agent:caveman 规则会通过 CLAUDE.md 间接影响,但子 agent 有自己的上下文
  • 写代码、commit message、PR 时:caveman 自动降级为正常输出

caveman 模式切换:

/caveman          # 查看当前模式
/caveman full     # 完全压缩(默认)
/caveman lite     # 轻度压缩
/caveman ultra    # 极端压缩
stop caveman      # 关闭
normal mode       # 关闭

15.1.4 Plugin 安装与管理

# 查看已安装插件
cat ~/.claude/plugins/installed_plugins.json

# 插件文件结构
~/.claude/plugins/
├── installed_plugins.json       # 安装记录
├── cache/                       # 插件代码缓存
│   ├── thedotmack/claude-mem/12.3.2/
│   │   ├── .claude-plugin/plugin.json   # 插件定义
│   │   ├── hooks/hooks.json             # Hook 配置
│   │   ├── .mcp.json                    # MCP 服务定义
│   │   └── scripts/                     # Hook 脚本
│   └── caveman/caveman/84cc3c14fa1e/
│       ├── .claude-plugin/plugin.json   # 插件定义
│       └── hooks/                       # Hook 脚本
├── blocklist.json
└── marketplaces/

15.1.5 Plugin 与 Teams 的交互

flowchart TD
    subgraph "Plugin Hooks(仅 team-lead 会话)"
        CM["claude-mem hooks"]
        CV["caveman hooks"]
    end
    
    subgraph "子 Agent(ui-dev / logic-dev / qa-engineer)"
        A1["独立 Claude Code 进程"]
        A2["有独立上下文窗口"]
        A3["Plugin hooks 是否触发?"]
    end
    
    CM -.->|"SessionStart 记录上下文"| DB[(observation DB)]
    CM -.->|"PostToolUse 记录操作"| DB
    CV -.->|"注入压缩规则"| TL["team-lead 上下文"]
    
    A3 -->|"取决于 agent 进程
是否加载了 plugin"| A1 style CM fill:#e1f5fe style CV fill:#fff3e0 style DB fill:#e8f5e9

关键事实:

  • Plugin hooks 在 team-lead 的 Claude Code 进程中运行
  • 子 agent 是独立的 Claude Code 进程,不继承 team-lead 的 plugin 配置
  • 这意味着 claude-mem 的自动记录不会捕获子 agent 的操作
  • 子 agent 的操作只能通过 inbox 文件共享文件系统被 team-lead 感知

15.1.6 自定义 Hook(项目级)

除了 Plugin hooks,还可以在 .claude/settings.json 中定义项目级 hooks:

{
  "permissions": { "allow": ["..."] },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'File being written: $TOOL_INPUT' >> /tmp/write-log.txt"
          }
        ]
      }
    ]
  }
}
Hook 字段 说明
matcher 匹配的工具名(如 WriteEditBash),* 匹配所有
type 固定为 command
command 要执行的 shell 命令
timeout 超时时间(秒)

15.1.7 上下文长度问题

每个 agent 有独立的上下文窗口,但共享文件系统。

team-lead 上下文: 包含所有 agent 通知 + 用户对话 + 规划文件
ui-dev 上下文:    包含 CLAUDE.md + requirement.md + 自己的代码
logic-dev 上下文: 包含 CLAUDE.md + requirement.md + 自己的代码
qa-engineer 上下文: 包含所有源代码 + 测试代码

常见问题:

  • team-lead 上下文最长(因为要跟踪所有 agent),最先触发 autocompact
  • autocompact 后历史消息被压缩,可能导致"忘记"某些 agent 的通知
  • 解决方案: 重要状态写入文件(task_plan.md, progress.md),不依赖上下文记忆

15.1.8 Task 依赖设置错误

// ❌ 错误:依赖方向反了
// Task #1 是 Phase B,Task #2 是 Phase A
// 结果:Phase A 被 Phase B 阻塞
TaskUpdate({ taskId: "2", addBlockedBy: ["1"] })

// ✅ 正确
// 确认 Task ID 和 Phase 的对应关系后再设依赖
TaskUpdate({ taskId: "2", addBlockedBy: ["1"] })  // Phase B blocked by Phase A

blockedBy 一旦设置无法移除! 只能通过 SendMessage 告诉 agent 忽略。

15.1.9 Agent 失败后的重启

当 agent 因权限问题或其他原因停止后,需要重新 spawn:

// 新 spawn 会创建新 agent(如 ui-dev-2, ui-dev-3)
// 旧 agent 记录仍在 team config 中
// 建议:新 agent prompt 中明确说明忽略 blockedBy

Agent({
  name: "ui-dev-3",  // 新名字
  mode: "bypassPermissions",
  team_name: "calc-dev",
  prompt: `你是 ui-dev,接替之前的工作。

不要调用任何 Skill。直接写代码。
忽略任何 blockedBy 标记,直接开始。

...`
})

15.1.10 完整避坑清单

症状 解决方案
权限格式错误 agent 执行 Bash 命令时卡住 Bash(cmd:*) 用冒号不是空格
Skill 调用弹窗 agent 调用 Skill 后停止 prompt 中禁止调用 Skill
tmux 找不到 agent calc-dev session pane 都是 zsh tmux list-panes -a 找实际 session
通知收不到 agent 完成但 team-lead 没收到 读 inbox 文件验证
Task 依赖反向 Phase A 显示被阻塞 创建前仔细核对 Task ID 与 Phase 对应
blockedBy 无法移除 误设依赖后无法清除 SendMessage 告诉 agent 忽略
上下文压缩 长会话丢失历史信息 重要状态写入文件
多次 spawn 残留 team config 中有多个死 agent 完成后用 TeamDelete 清理

15.2 配置参考

15.2.1 完整 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 模板

你是 {agent-name},负责 {职责描述}。

重要规则:
- 不要调用任何 Skill(不用 /planning-with-files 等)
- 直接写代码,不要创建 plan 文件
- planning 已在 task_plan.md 里完成,你只负责实现

先读 requirement.md 了解需求。

任务 1:{描述}
- {具体要求}

任务 2:{描述}
- {具体要求}

每个任务完成时:
1. TaskUpdate 标记 completed
2. SendMessage 通知 team-lead

Working directory: {path}

15.2.3 tmux 常用命令速查

# 创建/附加
tmux new -s calc-dev          # 创建 session
tmux attach -t calc-dev       # 附加

# 窗格操作
Ctrl+B → 方向键               # 切换 pane
Ctrl+B → z                    # 全屏当前 pane(再按恢复)
Ctrl+B → [                    # 进入复制模式(翻页)
q                             # 退出复制模式

# 监控
tmux list-sessions            # 列出所有 session
tmux list-panes -a -F '#{session_name}.#{pane_index} #{pane_current_command}'
tmux switch-client -t 2       # 切换到 session 2

# 鼠标
:set -g mouse on              # 启用鼠标滚轮

15.3 附录:Teams 文件系统

~/.claude/
├── teams/calc-dev/
│   ├── config.json              # 团队配置(成员、agent ID、prompt)
│   └── inboxes/                 # 消息投递
│       ├── team-lead.json       # team-lead 的 inbox
│       ├── ui-dev.json          # ui-dev 的 inbox
│       ├── logic-dev.json       # logic-dev 的 inbox
│       └── qa-engineer.json     # qa-engineer 的 inbox
└── tasks/calc-dev/              # 共享任务列表
    └── (task files)

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: agent 是否仍在运行(进程存活)
  • tmuxPaneId: agent 的 tmux pane 标识(但实际运行在其他 session 中)

本教程基于 2026-04-25 真实开发会话复盘。项目成功交付:双模式网页计算器,48+ 单元测试通过,DOM 集成测试 + 无障碍测试覆盖。