内容
<p align="center"><img src="assets/cctrace-logo.svg" width="84" alt="cctrace"></p>
# cctrace
> **查看 Claude 真实的发送内容。**
>
> Claude Code 发出的每个请求 —— 消息、OAuth、用量/积分、MCP ——
> 都在您的浏览器中实时捕获。
简体中文 | [English](README.md)
[](https://github.com/thevibeworks/cctrace/actions/workflows/test.yml)
[](https://github.com/thevibeworks/cctrace/tags)
[](LICENSE)
[](https://bun.sh)
<p align="center">
<img src="assets/cctrace-demo.gif" alt="cctrace live demo" width="100%">
</p>
cctrace 位于 Claude Code 和 Anthropic API 之间,记录每个 HTTP 调用到实时的分类 Web UI 中 —— 然后保存一个自包含的 HTML 快照,您可以随时打开。无需云,无需账户,无需任何内容离开您的机器。
```bash
cctrace
```
就这样。Claude 正常启动。您会看到一个浏览器选项卡,显示它正在执行的所有操作。
## 为什么
cctrace 旨在执行两个任务:
1. **LLM 跟踪** —— 精确查看 Claude Code 发送和接收的每个回合:系统提示、上下文、工具定义、流式回复、token/缓存使用情况。
2. **安全性和隐私跟踪** —— 审计实际离开您的机器的内容:哪些主机被联系,哪些遥测数据被发送, 每个有效载荷中包含什么。
这两个任务都需要完整的图景 —— 每个请求,而不仅仅是方便的请求 —— 而获取它比想象的要难:
Claude Code 作为 Bun 编译的**原生二进制文件**发布。经典的技巧是在 `node --require` 中注入 `fetch()` 钩子,但这对原生二进制文件无效 —— 它已经死了,吉姆。cctrace 捕获流量就像它实际工作一样:一个本地的 **TLS 拦截代理** (Charles/mitmproxy 风格,但零配置),Claude 通过 `HTTPS_PROXY` 路由到它,信任自动生成的 CA。
因为它在传输层拦截 —— 在构建 URL 之前 —— 所以它看到了**所有内容**,包括 OAuth 和用量/积分端点,而基本 URL 代理无法物理到达这些端点(Claude 硬编码了它们的 host)。
## 您获得的内容
- **完整的图景。** `/v1/messages` 、 OAuth、**用量/积分** 、 MCP 注册、引导、遥测 —— 不仅仅是聊天端点。
- **实时、分类的 UI。** 过滤芯片带有计数、彩色徽章、可展开的头部/正文、解码的 SSE 流。它看起来不错。您会真正想要保持它打开。
- **可分享的快照。** 每次运行都会写入一个自包含的 `.html` ,在离线状态下渲染相同的 UI,无需服务器。将其发送给同事。
- **零配置。** 自动生成其 CA,自动检测您的 Claude 安装,并默认捕获所有内容。无需编辑配置文件,无需记住标志。
- **默认安全。** 凭证从头部、正文、**和** URL 中被编辑后,任何内容都不会写入磁盘(请参见 [安全性和隐私](#安全性和隐私))。您的 API 密钥保持不变。
## 比较
| | **cctrace** | 基本 URL 代理 | claude-trace (`node --require`) | Charles / mitmproxy |
|---|:---:|:---:|:---:|:---:|
| 在原生二进制文件上运行 | 是 | 是 | **否** | 是 |
| 捕获 `/v1/messages` | 是 | 是 | 是 | 是 |
| 捕获 **OAuth / 用量 / 积分** | 是 | **否** | **否** | 手动 |
| 零配置(自动 CA + 信任) | 是 | 是 | 是 | **否** |
| Claude 感知 UI(分类、SSE 解码) | 是 | -- | 部分 | **否** |
| 仅限本地,无内容离开您的机器 | 是 | 是 | 是 | 是 |
`fetch()` 钩子方法(claude-trace 等)在 Claude Code 变成原生时停止工作。基本 URL 代理仍然有效,但只能看到 `/v1/messages` —— 您对 OAuth、用量和积分一无所知。像 Charles 这样的通用 TLS 代理可以看到所有内容,但需要手动设置 CA,并且不了解 Claude 的端点。cctrace 是中间路径:零配置,看到所有内容,并了解 Claude。
## 快速入门
需要 [Bun](https://bun.sh)、 `openssl` 和 Claude Code(`claude` 在 PATH 上)。
### 从 npm 安装
```bash
npm install -g @thevibeworks/cctrace
```
### 或在不安装的情况下运行
```bash
bunx @thevibeworks/cctrace
```
### 或克隆仓库
```bash
git clone https://github.com/thevibeworks/cctrace
cd cctrace
bun install
bun link # 可选: 将 `cctrace` 放入您的 PATH 中
```
### 或构建独立二进制文件(推荐)
```bash
git clone https://github.com/thevibeworks/cctrace
cd cctrace
make install # 编译 dist/cctrace,安装到 ~/.local/bin
```
`make install` (或 `make build` )将 cctrace 编译为单个可执行文件,通过 `bun build --compile` —— Bun 需要构建,**运行时不需要** 。这也是使 `cctrace -- <claude args>` 原样工作(请参见下面的传递说明)的安装。`make help` 列出所有目标; `PREFIX=/usr/local make install` 更改目标。
然后直接运行:
```bash
cctrace # 捕获所有内容,打开实时 UI
cctrace -- --continue # 恢复您的最后一个 Claude 会话,已跟踪
cctrace -- -p "hello" # 将参数直接传递给 Claude
cctrace -- --dangerously-skip-permissions # 完全自动,已跟踪
```
启动时,您将看到:
```
[cctrace] 实时 UI: http://localhost:9317
[cctrace] 捕获: MITM 代理 http://127.0.0.1:44775 (所有 Anthropic 主机)
```
打开 **实时 UI** URL 并观察请求流式传输。当您完成时,按 Ctrl-C —— cctrace 打印保存的 `.cctrace/trace-<timestamp>.html` 的路径。
## 运行 cctrace(Bun 和 `bin`)
cctrace **在 [Bun](https://bun.sh) 上运行** —— CLI 是 `src/cli.ts` 直接执行(shebang `#!/usr/bin/env bun` )。没有编译的 JS,也没有 Node 回退;所有内容都使用 `Bun.serve`/`Bun.spawn`。
| 命令 | 工作 | 备注 |
|---|---|---|
| `cctrace` (在 `make install` 之后) | 是 | 编译的二进制文件,运行时无需 Bun, `--` 传递完整 |
| `bun run src/cli.ts [args]` | 是 | 从克隆仓库 |
| `bun start` | 是 | 上面的别名 |
| `./src/cli.ts` | 是 | 通过 Bun shebang 直接执行 |
| `cctrace` (在 `bun link` 之后) | 是 | 需要 `~/.bun/bin` 在您的 `PATH` 上;bun 会吃掉前导 `--` |
| `node .../cli.ts` / `npm i -g` 无 Bun | **否** | 失败并报错: `env: 'bun': No such file or directory` |
**先决条件 —— 所有三个都很重要:**
- **Bun** —— 运行时(或构建工具,如果您 `make install` 编译的二进制文件)。如果您没有 Bun, [请安装它](https://bun.sh)。
- **`openssl` 在 PATH 上** —— `mitm` 模式调用它来生成 CA + 叶证书。没有 openssl?使用 `--mode base-url` (无需 CA,但您只能看到消息)。
- **真正的 Claude Code 安装** —— 自动模式读取您的 `claude` 二进制文件的神奇字节以选择捕获模式。没有 `claude` 在 PATH 上?cctrace 以 `Claude not found` 退出(或传递 `--claude-path`)。
> **独立二进制文件:** `make build` 为您的平台编译一个(`bun build --compile`); `make install` 将其放入您的 PATH 中。一个注意事项:编译的二进制文件不包括旧的 `node` 捕获模式(它需要源代码)—— 原生 Claude 安装默认使用 `mitm` (默认)。
## 捕获模式
cctrace 根据您的 Claude 安装自动选择;使用 `--mode` 覆盖。
| 模式 | 捕获 | 设置 |
|------|----------|-------|
| **`mitm`** (默认,原生二进制文件) | **所有内容** —— 消息、OAuth、用量/积分、MCP、遥测 | 自动生成 CA;Claude 通过 `NODE_EXTRA_CA_CERTS` 信任它 |
| **`base-url`** | 仅 `/v1/messages` | 零 —— 只设置 `ANTHROPIC_BASE_URL` |
| **`node`** (自动适用于 npm/JS 安装) | 通过 `fetch()` 钩子捕获所有内容 | 旧式;仅适用于非原生(JS)Claude |
非 Anthropic 主机也被**完全拦截** —— cctrace 动态生成每个主机的 TLS 证书(由同一个 CA 签名),因此您可以看到 Claude 联系的每个请求的完整请求和响应。外部流量在 UI 中有自己的过滤器类别。
## Web UI
- **行内摘要** —— 每个请求行一目了然:模型、进/出 token、缓存读取/写入 +命中率、 `count_tokens` 结果、用量窗口百分比(5 小时 / 7 天 / 每个模型)、遥测事件计数、错误类型。
- **类别过滤芯片** 带有实时计数:消息、用量/积分、OAuth、MCP、引导、遥测、其他。单击以过滤;与文本搜索结合使用。
- **分割详细面板** —— 单击一行,详细面板在列表旁边打开(可通过请求 ID 深度链接)。消息以对话优先的方式渲染,带有解码的 SSE 流;用量请求渲染限制条;原始头部/正文保持在一个折页中。 `j`/`k` 遍历过滤后的列表。
- **会话视图** —— 请求线和重建的对话并排显示:主聊天和子代理运行的线程(与其任务调度匹配),实用程序噪声折叠,工具结果折叠到其工具调用中,每个回合的 token/持续时间链接回请求线。
- **会话连续性** —— `cctrace -- --continue` (或 `--resume` )从以前的跟踪运行中继续:每个 Claude Code 请求在其线路上携带其会话 ID,因此 cctrace 通过精确匹配找到日志目录中较早运行的跟踪并合并它们。旧回合保留其 token、计时和线路链接,而不是渲染为纯历史;合并的请求标记为 `prev` ,并带有隐藏它们的切换。 `--fresh` 退出; `--with FILE` 强制合并任何跟踪文件。
- **离线快照** —— 保存的 `.html` 嵌入完整的跟踪,并渲染相同的 UI,无需服务器。 一年后打开它,仍然有效。
## 处理保存的跟踪
子命令在磁盘上操作已经存在的跟踪 —— 无需代理,无需 Claude 进程。
这三个管理命令**默认是只读的** (它们打印一个逐项计划,不会修改任何内容);添加 `--yes` 以应用。
```bash
# 重新生成快照 .html 并打开它 - 按文件,会话 ID 或文件名部分
cctrace view .cctrace/trace-2026-07-08T05-51-43.jsonl
cctrace view 4f9a2c1e # 一个 Claude Code 会话 ID(或前缀)
# 回收空间:删除可再生 .html 快照和 0 字节中止跟踪
cctrace clean # 仅限干运行:列出将被删除的内容
cctrace clean --yes
# 将一个会话的运行( --continue 跨文件)合并为一个 .jsonl
cctrace merge # 一个会话-<id>.jsonl per 会话
cctrace merge --prune --yes # 还删除完全合并的源
# 存档备份:gzip -9(.jsonl.gz 直接读取 .jsonl)
cctrace compress --older-than 7 --yes # 仅限 7 天以上的跟踪
```
管理操作永远不会缩小您的数据。 `clean` 仅删除一个仍然存在的 `.jsonl`/`.jsonl.gz 源的 `.html` (检查,而不是假设 —— 孤立的快照被保留)。 `merge` 和 `compress` 与现有输出联合,因此重新运行它们只会增长合并的文件或存档。 `merge` 仅在每个对都被归因于一个会话时才修剪源,因此一个持有 OAuth/用量/遥测(无会话 ID)的跟踪永远不会被删除。
## 选项
```
cctrace [选项] [-- CLAUDE_ARGS...]
```
| 选项 | 描述 |
|--------|-------------|
| `--mode MODE` | `auto` (默认), `mitm` , `base-url` , `node` |
| `-s, --static` | 静态模式(无实时服务器,仅限文件) |
| `-p, --port PORT` | 实时 UI 端口(默认:9317;如果忙则自动回退) |
| `--messages-only` | 仅捕获 `/v1/messages` |
| `--no-open` | 不自动打开浏览器 |
| `--print-ca` | 打印 MITM CA 证书路径并退出 |
| `--log NAME` | 自定义日志文件基名 |
| `--dir PATH` | 日志目录(默认: `.cctrace` ) |
| `--fresh` | 不合并先前的跟踪会话 |
| `--with FILE` | 将特定跟踪文件合并到视图中(可重复) |
| `--claude-path PATH` | 自定义 Claude 二进制文件路径 |
| `--cache-dir PATH` | MITM CA / 缓存目录(默认: `~/.cache/cctrace` ;或 `CCTRACE_CACHE_DIR` ) |
### 将参数传递给 Claude
`--` 之后的所有内容都会原样传递到 Claude CLI; `--` 之前的标志属于 cctrace:
```bash
cctrace -- --continue # claude --continue,已跟踪
cctrace -- -p "为什么失败了?" # claude 打印模式,已跟踪
cctrace --mode base-url -- --model opus # cctrace 标志 + Claude 标志
```
cctrace 不识别的标志在 `--` 之前是一个错误,并带有提示 —— 输入错误或放置不当的 Claude 标志永远不会被静默忽略。只有一个冲突需要注意: `--` 之前的 `-p` 是 cctrace 的端口, `--` 之后是 Claude 的打印模式。
> **Bun 运行注意事项:** 当 cctrace 通过 Bun 的 CLI 运行( `bunx` , `bun run` , `bun link` 垫片)时, Bun 本身会吃掉一个**前导** `--` ,因此 `cctrace -- --help` 作为 `cctrace --help` 传递。编译的二进制文件( `make install` )是免疫的——这是推荐的安装。在 Bun 运行安装中,请在 `--` 之前放置任何 cctrace 标志(例如 `cctrace --no-open -- --continue` )。
## 输出
每次运行都会写入 `.cctrace/` (或 `--dir` ):
- `trace-<timestamp>.jsonl` —— 每行一个请求/响应对(机器可读)
- `trace-<timestamp>.html` —— 自包含的分类查看器(人类可读)
## 工作原理
```mermaid
flowchart LR
CC["Claude Code<br/>(原生二进制文件)"]
FD{"cctrace<br/>连接前门"}
TLS["TLS 終止器<br/>(我们的叶证书)"]
BT["TLS 終止器<br/>(动态证书)"]
API[("api.anthropic.com")]
ORI[("非 Anthropic<br/>源站)"]
TEE(["复制响应流")]
RD["编辑<br/>\n头部 · 正文 · URL"]
UI["实时 UI<br/>(分类)"]
OUT[[".cctrace/ · jsonl + html"]]
CC -- "HTTPS_PROXY +<br/>NODE_EXTRA_CA_CERTS" --> FD
FD -- "Anthropic host" --> TLS
FD -- "other host" --> BT
TLS --> API
BT --> ORI
ORI -- "response stream" --> TEE
API -- "response stream" --> TEE
TEE -- "streamed to Claude,<br/>no buffering" --> CC
TEE -- "captured copy" --> RD
RD --> UI
RD --> OUT
classDef accent stroke:#3fb950,stroke-width:2px;
class RD accent
```
代理终止 TLS 连接,使用自动生成的叶证书(带有 Anthropic SAN),转发到真实 API,并复制响应流,以便 Claude 可以立即获得字节,同时 cctrace 捕获一份副本 - 零缓冲响应。
我们只向 Claude 的环境中注入两项内容:`HTTPS_PROXY` (将流量路由到我们)和 `NODE_EXTRA_CA_CERTS` (将我们的 CA 追加到 Bun 的信任存储中,以便 Claude 信任我们的叶证书,而公共 TLS 仍然有效)。
我们**不**设置 `SSL_CERT_FILE` 或 `HTTP_PROXY` -- 这些会泄漏到 Claude 的子进程中(bash 工具的 `curl` / `python` ,MCP 服务器)并破坏它们的网络连接。这是那种让你在凌晨 2 点质疑人生选择的 bug。
## 安全性和隐私
cctrace 是一个本地调试工具,但它会拦截真实的凭证流量,
所以它会编辑后写入:
- **头部** —— `authorization` , `x-api-key` , `cookie` 等被编辑为 10/4 预览(足以辨别 **哪个** 密钥,而不是密钥本身)。
- **正文** —— 凭证字段( `access_token` , `refresh_token` , `client_secret` , `code` , `api_key` , ...)在 JSON 和表单编码正文中被编辑。您的 `/v1/messages` 对话内容保持完整。
- **URL** —— 包含凭证的查询参数(例如 OAuth `?code=` )被编辑。
编辑发生在单个阻塞点,因此它统一应用于 `.jsonl` 、可共享的 `.html` 和实时 WebSocket。 `.cctrace/` 输出默认被 gitignore。
**仍然:** 跟踪是您真实会话的记录。在分享前请检查它。不要在公共问题中粘贴原始输出。认真。
## 路线图
- **Codex 支持** —— 通过相同的 MITM 前门跟踪 OpenAI Codex CLI。代理层已经是代理无关的;剩下的是 OpenAI 主机过滤器、端点类别和其线格式的对话重建。
- **对话转储** —— 以 Markdown 或 JSON 导出重建的对话,准备共享或事后分析。
- **代理技能** —— 一个用于与 cctrace 以编程方式交互的专用 Claude Code 技能/MCP 服务器:查询捕获的流量、检查特定请求、导出对话。
- **多会话实时视图** —— 通过将每个会话路由到路径(如 `http://localhost:9317/<project>/<session-id>` )来运行多个 cctrace 会话而无需端口冲突。
- **令牌指标** —— 每回合和累计令牌使用情况、缓存命中率、成本估算和 `service_tier` / `inference_geo` 可见性。
参见 [CHANGELOG.md](CHANGELOG.md) 获取已发布的更改。
## 开发
```bash
bun test # 单元测试
bun run tests/e2e-live.ts mitm "hi" # 实时测试对抗真实的 Claude
```
参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
## 许可证
[MIT](LICENSE)
连接信息
猜你喜欢
暂无推荐服务器