第 15 期 | 进阶:Plugin Hooks 扩展、性能基准与配置参考
💡 进群学习加 wx: agentupdate
(申请发送: 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 |
匹配的工具名(如 Write、Edit、Bash),* 匹配所有 |
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 集成测试 + 无障碍测试覆盖。