一个自动连接 Claude Code 的多 Agent 活动时间线工具,在浏览器里观察每个 Agent 何时、做了什么、当前在干嘛。
自动 attach 任意终端 / IDE 里运行的 Claude Code 会话,把每次工具调用转成事件,按时间线展示:哪个 Agent、什么时间、做了什么、当前状态、改了什么、遇到什么问题。
想在浏览器里直接看界面效果?这里有一份公开演示页(无需本地后端):
演示页是纯静态的:页面分两部分——上半是介绍,下半是完整界面。由于 GitHub Pages 无法运行后端 / WebSocket,演示页用一个浏览器内模拟引擎持续生成假数据,让 LLM 调用 次数、token 数和时间线实时跳动,看起来就像一次真实进行中的 Claude Code 会话,但全部是前端假数据。
本地预览演示版:
cd frontend && CCLIVE_DEMO=1 npm run dev # 打开 http://localhost:5173正式工具(连真实后端)不受影响,照常 cli.py run 即可。
不是 clone 一个 Claude 子进程,而是旁路收集事件:给 ~/.claude/settings.json 装个极小的 hook shim,再加只读监听 transcript。
关键保证(详见 hook_shim.py、hooks_install.py):
- 恒 exit 0:hook 永远返回成功,Claude Code 判定"无 decision、无错误",不可能阻断会话。
- 超时自断:hook 往本地 socket 写一条 JSON(fire-and-forget),有看门狗兜底;观察端挂了最多几百毫秒后 hook 自行退出,且因恒 exit 0 不影响 cc。
- 路径无空格:hook 指向无空格路径的 wrapper,内部再引号引用真实路径,避免带空格目录被截断。
- 零侵入:不动 Claude 的输入/行为,只读观察;卸载后不留痕迹。
效果:你正常开 cc 干活,时间线 1 秒内实时刷新。即使 ClaudeCode Live Timeline 挂了,你的 Claude Code 照常工作。
cd "backend"
python3 cli.py run(若 python3 不是你的解释器,换成你的 python 可执行文件路径,例如
<你的python绝对路径> cli.py run)
这会:
- 装 hooks 到
~/.claude/settings.json(保留已有其他 hooks) - 启动后端(
127.0.0.1:8000,含 socket server + transcript 只读监听) - 启动前端(
127.0.0.1:5173)并自动打开浏览器 - 任何终端 / IDE 新建的 Claude Code 会话,一有动作就实时进时间线
按 Ctrl+C 停止,自动卸载我们装的 hooks。
python3 cli.py hooks # 查看已装的 hooks(标注哪些是 cc-live 的)
python3 cli.py hooks --remove # 只卸载 cc-live 装的 hooks(保留其他)| 变量 | 默认 | 说明 |
|---|---|---|
CCLIVE_HOST |
127.0.0.1 |
后端监听地址 |
CCLIVE_PORT |
8000 |
后端端口 |
CCLIVE_FRONTEND_PORT |
5173 |
前端端口 |
CCLIVE_SOCK |
/tmp/cclive.sock |
hook 本地 IPC socket 路径 |
不想一键装 hooks 时,可以用 dev.sh 分开启动/停止前端与后端(各自后台运行、带 PID 文件和日志):
./dev.sh backend # 只启动后端 (uvicorn :8000)
./dev.sh frontend # 只启动前端 (vite dev :5173,/api、/ws 自动代理到后端)
./dev.sh all # 先后端再前端,并跟随日志输出
./dev.sh status # 查看前后端运行状态
./dev.sh stop # 停止前端 + 后端后台日志在 /tmp/cclive-backend.log、/tmp/cclive-frontend.log;可用环境变量
CCLIVE_HOST / CCLIVE_PORT / CCLIVE_FRONTEND_PORT / PYTHON 覆盖默认值。
注意:
dev.sh不会安装 hooks,因此适合先看界面 / 单独开发前端或后端; 要真正观察 Claude Code 会话,仍用./dev.sh backend起后端 + 在另装 hooks(cli.py hooks),或直接用cli.py run。
# 后端
python3 -m uvicorn app.main:app --host 127.0.0.1 --port 8000
# 前端(另起终端)
cd frontend && npm run dev每个正在工作的 Agent 是一个卡片(叫 Workcell),用一位像素发光伙伴 + 现场道具表达它此刻在做什么:
- Live / 正在工作中:所有 running 会话并排,每个 Agent 是一位 16×20 像素光心伙伴,随状态切换身体语言:
- 🧠 思考 → 歪头、头顶冒「···」悬浮泡
- 📖 阅读 → 光弧小臂捧页,眼睛俯视
- ✏️ 写码 → 光弧小臂挥笔,面前代码页
- 🔧 执行 → 双臂前后摆动,旁边日志面板
- 🧪 测试 → 捧烧杯,气泡上浮
- ☕ 等待 → 站住,头顶"待机"牌闪烁
- 🎉 完成 → 向后靠、闭眼
- 🐛 出错 → 光色转红、心核急闪(柔光熄灭前的不安)
- 时间线:卡片下方是从下到上推进的纵向时间线,合并后的节点各占一行,标注时间 + 图标 + 简要说明(最近一次 detail 前几字),最新在上;正在执行的节点升格呼吸,hover 看每次 detail;相邻同类合并成一个节点,角标
×N。 - 当前动作播报:伙伴旁一条"now"播报,显示正在执行的命令 / 文件。
- LLM 用量读数:会话卡片顶部一条浅色读数栏,展示这次会话的 LLM 调用情况:
in / out / cache·读 / cache·写的 token 数、次调用数,以及单次 avg / p99耗时。旁路从 transcript 统计,不影响 cc(注:首字符响应时长 TTFT transcript 拿不到,故不统计)。 - 历史:已结束的会话移到侧边栏,点击回放完整时间线,同样支持多 Agent 卡片。
Claude Code (任意终端/IDE)
│ hook 事件 (socket) + transcript JSONL(只读)
▼
Hook Adapter (hook_shim.py)
│
▼
Event Collector → Parser (语义化: READING/WRITING/…)
│
▼
SQLite (SQLModel)
│
▼
Timeline Processor
│
▼
WebSocket
│
▼
React UI
代码结构:
backend/
cli.py # cc-live CLI(run / hooks)
app/
main.py # FastAPI 入口 + REST + WebSocket + 拉起观察者
hook_shim.py # hook shim:fire-and-forget、恒 exit 0、超时自断
hooks_install.py # 安装/卸载 ~/.claude/settings.json 的 hooks
watcher.py # 观察者:socket server(hook 通道)+ transcript 监听 + 用量采集 + 落库广播
parser.py # 原始工具调用 → 语义化事件 + subagent 区分
db.py # SQLite (SQLModel) 存储 + timeline 组装
models.py # Agent / Session / AgentEvent
ws_manager.py # WebSocket 连接与广播管理
frontend/
src/
App.jsx # Live 总览 + 历史 + 时间线回放
Workcell.jsx # 一个 Agent 卡片:16×20 像素光心伙伴 + 光弧小臂/眼/触角/心核灯 + 现场道具 + 时间线
eventMeta.js # 事件 emoji/颜色/动画分组
index.css # 暖纸纸面网格主题 + 动作/道具 keyframes
| 类型 | Emoji | 说明 | 动画分组 |
|---|---|---|---|
| THINKING | 🧠 | 分析 | 进行类(打字) |
| READING | 📖 | 读取文件 | 进行类(打字) |
| WRITING | ✏️ | 修改文件 | 进行类(写字) |
| RUNNING | 🔧 | 执行命令 | 进行类(齿轮) |
| TESTING | 🧪 | 测试 | 进行类(烧杯) |
| ERROR | 🐛 | 错误 | 错误 |
| SUCCESS | 🎉 | 成功 | 完成(睡觉) |
| WAITING | ☕ | 等待 | 状态 |
| MESSAGE | 💬 | 消息 | 状态 |
| START | 🚀 | 会话开始 | 状态 |
数据模型支持一 Session 多 Agent。目前从 hook payload 识别 subagent_id:带 subagent 标识的工具调用归独立的 🤖 Subagent 泳道,否则归主 👩💻 Claude。依赖 Claude Code 在 subagent 场景透传该字段,若未透传则回落为主 agent。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/session |
创建 Session |
| GET | /api/sessions |
列出所有 Session |
| GET | /api/session/{id}/timeline |
获取某 Session 的时间线 |
| POST | /api/session/{id}/end |
结束 Session |
| DELETE | /api/session/{id} |
删除 Session(含其事件,清理测试数据用) |
| POST | /api/events |
上报事件 |
| WS | /ws/session/{id} |
实时推送事件流 |
| GET | /api/health |
健康检查 |
- Backend: Python · FastAPI · SQLModel · SQLite · WebSocket
- 前端: React + Vite + TailwindCSS
- 可视化: CSS 动画(MVP);未来可扩展 SVG/Canvas
- cc 某次会话没进时间线? hooks 从 SessionStart 起才生效;若观察端是后来启动的,之前的事件不补。确保
cli.py run(socket 监听)在跑,且 hooks 已安装。 - 想彻底不用时:
python3 cli.py hooks --remove卸载,然后停后端/前端即可。 - 端口占用:设置
CCLIVE_PORT/CCLIVE_FRONTEND_PORT换端口。
