我用 Claude Code 给 Claude Code 做了一个 DevTools

0 阅读5分钟

背景:黑盒里的 Agent

用过 Claude Code 的人大概都有同感——它很强,但你永远不知道它在想什么。

一次复杂的 coding session 下来,Agent 可能调了几十次工具、spawn 了若干子代理、读了上百个文件,最终给你一个结果。中间发生了什么?token 花在了哪里?哪个环节做了多余的事?你只能盯着终端滚动的文字猜。

这种"黑盒感"在调试复杂任务时尤为痛苦。当 Agent 给出错误结果,你需要回溯它的决策链路;当 token 用量异常飙高,你想知道是哪个工具调用吃掉了预算;当多个子代理协作时,你想看清它们之间的分支关系。

Chrome 有 DevTools,凭什么 Claude Code 没有?

于是我做了 Claude Devtools——一个本地运行的可视化调试工具,把 Agent 的执行流程从黑盒变成白盒。而有意思的是,这个项目本身就是完全由 Claude Code 编写的

系统架构

整个系统由四个组件构成,各司其职:

graph TD
    CLI["Claude Code CLI"]
    MITM["mitmproxy\ncapture.py · :9581"]
    API["Anthropic API"]
    PROXY["Proxy Server\nWebSocket · :5555"]
    TRACE["Trace API Server\nExpress · :3001"]
    FE["Frontend · :3000\nDAG 可视化 | Live Monitor"]
    JSONL[("~/.claude/projects\nJSONL 会话文件")]

    CLI -- "HTTPS 请求" --> MITM
    MITM -- "转发" --> API
    API -- "SSE 流式响应" --> MITM
    MITM -- "HTTP POST\n捕获的请求/响应" --> PROXY
    PROXY -- "WebSocket\n实时推送" --> FE
    TRACE -- "REST API" --> FE
    JSONL -. "读取 JSONL" .-> TRACE

mitmproxy + capture.py 作为中间人代理,拦截 Claude CLI 发往 API 的每一次 HTTPS 请求,解析 SSE 流式响应,提取 token 用量、模型参数、对话内容,然后推送给 Proxy Server。

Proxy Server 是一个 WebSocket 广播站,接收 mitmproxy 推来的数据,实时推送给浏览器前端。同时它也承担模板管理——捕获 CLI 的 system prompt 和 tools 定义,供后续复用。

Trace API Server 负责读取 Claude Code 写在本地的 JSONL 会话文件(~/.claude/projects/),提供 RESTful 接口给前端查询项目列表、会话列表和完整事件流。

Frontend 是一个 React 单页应用,包含两个核心视图。

核心功能

Session Traces:DAG 可视化

这是系统的核心。每一次 Claude Code 会话本质上是一条事件链——用户输入、助手回复、工具调用、子代理分派——我把它渲染成一张交互式的有向无环图(DAG)。

节点按类型着色:蓝色 USER、绿色 ASSISTANT、橙色 TOOL、青色 TASK。纵轴是时间线,横轴用泳道(swimlane)展示子代理的并行分支。当 Agent spawn 子代理时,Task 节点向右分叉出独立的执行链,多代理协作关系一目了然。

graph TD
    U1["🟦 USER\n用户输入"]
    A1["🟩 ASSISTANT\n助手回复 + thinking"]
    T1["🟧 TOOL: Bash\n执行命令"]
    A2["🟩 ASSISTANT\n分析结果"]
    T2["🟧 TOOL: Edit\n修改文件"]
    TASK["🟦 TASK: spawn 子代理"]

    subgraph 主链
        U1 --> A1 --> T1 --> A2 --> T2 --> TASK
    end

    SA1["🟩 SubAgent ASSISTANT"]
    ST1["🟧 SubAgent TOOL: Read"]
    SA2["🟩 SubAgent ASSISTANT\n返回结果"]

    subgraph 子代理分支
        TASK --> SA1 --> ST1 --> SA2
    end

    style U1 fill:#1e3a5f,stroke:#60a5fa,color:#f1f5f9
    style A1 fill:#0a2a18,stroke:#4ade80,color:#f1f5f9
    style A2 fill:#0a2a18,stroke:#4ade80,color:#f1f5f9
    style T1 fill:#2d1a06,stroke:#fb923c,color:#f1f5f9
    style T2 fill:#2d1a06,stroke:#fb923c,color:#f1f5f9
    style TASK fill:#0a1a18,stroke:#2dd4bf,color:#f1f5f9
    style SA1 fill:#0a2a18,stroke:#4ade80,color:#f1f5f9
    style ST1 fill:#2d1a06,stroke:#fb923c,color:#f1f5f9
    style SA2 fill:#0a2a18,stroke:#4ade80,color:#f1f5f9

为了避免线性链路上几十个节点挤在一起,我实现了自动折叠——连续的无分支节点被压缩成一个带计数的折叠节点,点击后在侧面板展开详情。这让一个 200+ 事件的会话仍然保持可读。

点击任意节点,右侧面板展示完整元数据:thinking 块、工具输入参数、执行结果、Edit 操作的 diff 对比,以及原始 JSON。

Live Monitor:实时流量监控

第二个视图是实时 API 监控。通过 mitmproxy 拦截,你可以看到 Claude Code 发出的每一次 API 调用——请求参数被结构化拆解为 model、messages、system prompt、tools 定义、temperature 等语义模块,每项可折叠展开。

实时 Token 统计面板汇总 input/output/cache_read/cache_creation 四类 token 数量和累计费用,让你精确掌握成本开销。对话轮次可逐轮展开,审查 Agent 实际发出的 Bash 命令、文件编辑操作和思考过程。

其他细节

  • 会话浏览器:左侧边栏按项目目录组织所有会话,显示事件数、时间戳、子代理数量标记
  • 全局搜索:按关键词过滤节点,快速定位目标事件
  • 深色/浅色主题:右上角一键切换,所有组件通过 CSS 变量统一响应
  • 一键启动脚本start-devtools.sh 自动拉起全部四个服务并配置代理环境变量

技术选型

graph LR
    subgraph 前端
        React["React 18"]
        TS["TypeScript"]
        XY["@xyflow/react"]
        Dagre["dagre 布局"]
        TW["Tailwind CSS"]
    end

    subgraph 后端
        Express["Express 4"]
        WS["WebSocket (ws)"]
        JSONL["JSONL 逐行解析"]
    end

    subgraph 流量捕获
        Mitm["mitmproxy"]
        Py["capture.py addon"]
    end

    subgraph 构建
        Vite["Vite 5"]
        TSX["tsx runtime"]
    end

前端用 React 18 + TypeScript,图渲染基于 @xyflow/react(前身 React Flow),布局算法是自研的时间戳 + 泳道布局配合 dagre 辅助。后端用 Express + WebSocket,流量捕获用 mitmproxy 的 Python addon。全程本地运行,不上传任何数据。

用 Claude 构建 Claude 的调试器

这个项目有一个自指的有趣之处:整个 Claude Devtools 从第一行代码到最终产品,全部由 Claude Code 编写

我的角色更像是产品经理——提出需求、审查产出、决定方向。具体的架构设计、代码实现、bug 修复,全部交给 Claude Code 完成。下面是整个开发过程中的人机协作流程:

graph LR
    ME["👤 我\n提需求 / 审查 / 决策"]
    CC["🤖 Claude Code\n架构 / 编码 / 调试"]
    DT["🛠️ Claude Devtools\n可视化产物"]

    ME -- "描述功能需求" --> CC
    CC -- "生成完整实现" --> DT
    DT -- "观测 Agent 行为" --> ME
    ME -- "发现问题,反馈优化方向" --> CC

这形成了一个闭环:我用 Claude Code 写代码 → Devtools 观测它的执行过程 → 发现可优化的点 → 再用 Claude Code 改进。工具自己成了自己的调试对象

整个项目开发周期约一周,期间没有手写一行业务代码。React 组件、Express 服务、mitmproxy 插件、DAG 布局算法、WebSocket 通信协议——所有模块都是在对话中通过自然语言描述需求,由 Claude Code 一次性或迭代生成的。这本身也验证了 Claude Code 处理中等复杂度全栈项目的能力。

截图

image.png

对话轮次展示

image.png

工具列表

image.png

响应内容

image.png

写在最后

这个工具本质上解决的是可观测性问题。LLM Agent 的执行流程越来越复杂——多轮对话、工具编排、子代理协作——如果没有合适的观测手段,调试和优化就只能靠猜。

Claude Devtools 把 Agent 的每一步决策摊开在 DAG 上,让你像调试程序一样调试 Agent。而它自身的诞生过程,恰恰证明了被调试对象的能力——用 Claude 构建 Claude 的调试器,这大概是最好的能力背书。 github地址如下,欢迎各位大佬star

github.com/invictuskai…