Coding 工具 · 01
Claude Code
使用 Claude Code 的 Stop hook 把“主 Agent 完成一轮响应”转换为 bluebell completed 事件。先仅本机验证,再打开远程路径。
当前官方生命周期
为什么选择 Stop
Claude Code 将 Stop 定义为主 Agent 完成响应时触发的 hook。它没有 matcher;回调 JSON 通过 stdin 传给命令,并包含会话、工作目录与 transcript 路径等字段。
步骤 1
创建本机转换脚本
把下面脚本保存为你自己的固定路径,例如 ~/.local/bin/claude-bluebell.py。它不读取 transcript 内容,只使用文件大小与会话 ID 生成本轮稳定身份。
claude-bluebell.py
#!/usr/bin/env python3
import hashlib, json, os, subprocess, sys
CLI = "/Applications/bluebellMac.app/Contents/Helpers/bluebellctl"
try:
payload = json.load(sys.stdin)
except Exception:
sys.exit(0)
if payload.get("hook_event_name") != "Stop" or payload.get("stop_hook_active"):
sys.exit(0)
session_id = str(payload.get("session_id") or "")
transcript = str(payload.get("transcript_path") or "")
cwd = str(payload.get("cwd") or "")
if not session_id or not transcript:
sys.exit(0)
try:
transcript_size = os.path.getsize(transcript)
except OSError:
sys.exit(0)
signature = f"{session_id}\0{transcript}\0{transcript_size}"
turn_id = hashlib.sha256(signature.encode()).hexdigest()[:24]
workspace_name = os.path.basename(cwd) or "Claude Code"
subprocess.run([
CLI, "emit",
"--source", "Claude Code",
"--workspace-name", workspace_name,
"--session-id", session_id,
"--turn-id", turn_id,
"--dedupe-key", f"claude-code:{session_id}:{turn_id}",
"--local",
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, timeout=3, check=False)示例保留 --local,先验证本机链路。脚本故意丢弃 bluebell 输出并始终不让通知问题阻塞 Claude Code。
步骤 2
合并到 Claude Code 设置
用户级设置通常位于 ~/.claude/settings.json。将以下对象合并到现有 hooks.Stop;不要覆盖其他 hooks,也不要照抄示例绝对路径。
settings.json fragment
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "python3 /absolute/path/claude-bluebell.py"
}
]
}
]
}
}步骤 3
确认一次可见完成只产生一条记录
- 保持 bluebell Mac 运行,并执行一轮简短 Claude Code 任务。
- 约 2 秒后检查“最近提醒”,确认来源、项目名与一条记录。
- 测试一次继续执行、一次带子任务的工作流,确认没有错误的额外完成。
- 确认稳定后,从脚本删除
--local,开启 Mac 总推送,再做真实设备验证。
如果你的 Claude Code 版本没有 transcript_path,不要把此示例直接用于正式去重;请根据该版本官方 payload 改用稳定的轮次身份。
来源
Claude Code 官方资料
- Claude Code hooks guideHook 配置、输入方式与 Stop 示例