claude-code-best/docs/Claude_Code_的光明和阴影面.md
James Feng 7eb5530b2c docs: sync 光明和阴影面 doc + update README numbers to 3699
- Copy doc from user manual to docs/
- Quality table: 3383 → 3699 (+692)
- Local dev section: 3383 tests → 3699 tests
- Version table: add v2.2.1, v2.2.2 entries
2026-06-04 21:03:57 +08:00

468 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Claude Code 的光明和阴影面
> **副标题:** Anthropic 遥测系统的逆向工程、纵深防御与自用改造
>
> **作者:** James Feng基于 CC_Pure 代码库逆向分析2026年6月
>
> **标签:** `逆向工程` `遥测` `隐私` `GrowthBook` `OpenTelemetry` `数据分析`
---
## 目录
1. [前言:为什么要写这篇文章](#1-前言)
2. [光明面:一套工业级的数据工厂](#2-光明面)
3. [阴影面:数据去哪了](#3-阴影面)
4. [解剖:遥测系统的五层架构](#4-解剖)
5. [防御:我们做了什么](#5-防御)
6. [为己所用:如何让这套系统服务于你](#6-为己所用)
7. [附录:事件词典](#7-附录)
---
## 1. 前言
Claude Code内部代号 "tengu")是 Anthropic 的终端 AI 编程助手。它不仅仅是一个命令行工具——它是一套完整的**数据采集和分析基础设施**。每当你输入一个命令、调用一个工具、触发一次 API 请求,几十个遥测事件在后台被捕获、采样、路由和上报。
本文基于对 **CC_Pure**Claude Code 反编译还原项目)的深度代码审计,完整拆解这套遥测系统:
- 它收集了什么?
- 数据流向了哪里?
- 我们如何发现并防御?
- 更重要的是,**我们如何把它变成自己的利器**
> **核心结论:** Anthropic 的遥测基础设施本身就是一套值得学习的工业级数据工程范例。我们不需要摧毁它——我们需要**接管它**。
---
## 2. 光明面
### 2.1 工程设计的精妙之处
Claude Code 的遥测系统不是简单的埋点+上报。它是一套分层架构:
```
logEvent()
├── 本地 JSONL 写入(我们加的防御层)
├── 事件队列sink 未初始化时的缓冲)
├── GrowthBook 动态采样(云端控制的抽样引擎)
├── Datadog 监控(运维告警)
└── 1P 事件上报Anthropic 内部 BigQuery 分析)
```
**亮点 1零依赖入口设计**
`logEvent()` 函数(`src/services/analytics/index.ts`)本身没有任何模块级依赖。所有事件先进入队列,等 `attachAnalyticsSink()` 在应用初始化时被调用后才真正路由到后端。这个设计避免了循环依赖,也让测试变得极其容易。
```typescript
// 精妙:零依赖的入口
export function logEvent(eventName, metadata) {
// ① 本地写入(我们的注入点)
writeLocalEvent(eventName, metadata)
// ② 如果 sink 未就绪,入队;否则直接发送
if (sink === null) {
eventQueue.push({ eventName, metadata, async: false })
return
}
sink.logEvent(eventName, metadata)
}
```
**亮点 2GrowthBook 动态实验平台**
整个项目的 feature flag 系统建立在 GrowthBook 之上。这不是简单的 `if (feature_enabled)` —— 它是一个完整的 A/B 实验平台:
- **远程评估remote eval** 服务器预先计算每个 feature 的值,客户端直接使用,无需本地规则引擎
- **磁盘缓存 + 会话内刷新:** 首次获取后写 `~/.claude.json`,后续进程启动用缓存,会话期间通过 `onGrowthBookRefresh` 推送更新
- **实验曝光追踪:** 每个被访问的 feature 自动记录实验分配事件到 1P 事件管道
- **动态配置JSON config** 不仅是开关,还支持复杂的 JSON 配置如事件采样率、批处理参数、sink kill switch
`src/services/analytics/growthbook.ts` 文件高达 **1256 行**,处理了远程评估响应格式的 workaround、env-var override、config override、刷新信号机制等细节。
**亮点 3ToolSearchTool —— RL 数据工厂的核心**
`ToolSearchTool` 不仅是一个工具搜索功能,它是一台**强化学习数据收集机器**
```typescript
// 搜索评分权重(精确调优的参数)
if (parsed.parts.includes(term)) {
score += parsed.isMcp ? 12 : 10 // MCP 工具名精确匹配权重更高
} else if (parsed.parts.some(part => part.includes(term))) {
score += parsed.isMcp ? 6 : 5 // 部分匹配
}
// searchHint 匹配
score += 4
// 描述匹配
score += 2
```
每一次搜索都上报 `tengu_tool_search_outcome` 事件,包含:
- `query`:用户的搜索词
- `queryType``select` 或 `keyword`
- `matchCount`:命中数量
- `totalDeferredTools`:延迟工具总数
- `hasMatches`:是否有命中
这套数据让 Anthropic 能够**量化分析模型如何使用工具**,从而持续优化工具描述、搜索算法和评分权重。
**亮点 4多层 PII 防护**
代码中随处可见隐私保护设计:
- `AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS` 类型标记——强制开发者验证不上传代码/路径
- `sanitizeToolNameForAnalytics()` —— MCP 工具名(可能暴露用户配置)被替换为 `mcp_tool`
- `stripProtoFields()` —— PII 标记字段只在 1P 特权列中,不进入通用 Datadog
- `getFileExtensionForAnalytics()` —— 只上传文件扩展名,不上传完整路径
- `getUserBucket()` —— 用户 ID 哈希分桶,去匿名化计数但不暴露身份
### 2.2 事件体系全景
通过代码审计,我们统计出 **190+ 处 `logEvent()` 调用**,分布在 52 个文件中。主要事件类别:
| 类别 | 事件数 | 代表事件 |
|------|--------|---------|
| API 查询 | ~20 | `tengu_query_error`, `tengu_api_success`, `tengu_token_budget_completed` |
| 工具使用 | ~15 | `tengu_tool_search_outcome`, `tengu_bash_tool_used` |
| 权限决策 | ~10 | `tengu_tool_use_granted`, `tengu_tool_use_rejected` |
| 认证/OAuth | ~15 | `tengu_oauth_success`, `tengu_oauth_token_refresh_failure` |
| 会话生命周期 | ~10 | `tengu_started`, `tengu_exit`, `tengu_init` |
| 压缩/内存 | ~5 | `tengu_auto_compact_succeeded`, `tengu_orphaned_messages_tombstoned` |
| 实验/A/B | ~8 | `tengu_willow_mode`, GrowthBook assignment |
| Bridge/Remote | ~15 | `tengu_bridge_message_received`, `tengu_ws_transport_reconnected` |
| 迁移 | ~8 | `tengu_opus_to_opus1m_migration` |
| 遥测自监控 | ~3 | `analytics_sink_attached` |
### 2.3 数据工厂:四线并行
Anthropic 实质上运行着**四条独立的数据管道**
1. **Datadog运维**:白名单制,只发送 ~40 种预定义事件到 Datadog用于 API 错误率、OAuth 故障率等 SRE 告警
2. **1P Event Logging分析**:基于 OpenTelemetry SDK Logs**所有事件**通过 `/api/event_logging/batch` 上报到 Anthropic 的 BigQuery是核心分析管道
3. **GrowthBook实验**Feature flag 赋值 + 实验曝光事件,独立上报,用于 A/B 测试结果评估
4. **Customer OTLP客户遥测**:可选的企业客户 OTLP 导出metrics/logs/traces`CLAUDE_CODE_ENABLE_TELEMETRY` 控制
---
## 3. 阴影面
### 3.1 数据收集的广度
让我们诚实地审视Claude Code **实际收集了什么**
```
每次启动:
✓ 操作系统版本、终端类型、包管理器列表
✓ Git 仓库远程 URL 的哈希("rh" 字段)
✓ 用户订阅级别(免费/Pro/Max/Team/Enterprise
✓ 是否为 CI 环境、GitHub Action 类型
每次 API 查询:
✓ 使用的模型名称、beta 列表
✓ token 消耗量、上下文窗口大小
✓ 是否触发了 fallback 模型
✓ 查询前后的 attachment 对比
每次工具调用:
✓ 工具名称、是否成功
✓ 文件扩展名(不是路径,但足以推断工程类型)
✓ Bash 命令类型diff/grep/sed 等)
✓ 权限决策always allow / reject / ask
每次会话:
✓ 启动次数、使用时长
✓ 压缩频率、孤儿消息数量
✓ KAIROS后台 agent活跃状态
```
### 3.2 技术上的透明度
Anthropic 并不是在偷偷做这件事。代码中的设计模式表明:
1. **所有遥测都在 `src/services/analytics/` 下集中管理**,模块边界清晰
2. **隐私分级明确**`AnalyticsMetadata_I_VERIFIED_...` 类型标记)
3. **提供了 opt-out 机制**`DISABLE_TELEMETRY` / `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`
但从"后门"到"数据工厂"的距离并不远。这一套基础设施如果被滥用(或遭遇供应链攻击),可以轻松变成:
- 代码片段收集器(绕过文件路径截断,直接上传内容)
- 用户行为画像(通过 token 消耗模式推断工作习惯)
- 工程结构嗅探(通过文件扩展名统计推断技术栈)
### 3.3 我们发现的"异常"
在 CC_Pure 的代码审计中,我们注意到几个不寻常的地方:
1. **`USER_TYPE === 'ant'` 条件分支:** 代码中有 **50+ 处**检查用户是否为 Anthropic 内部员工。内部版本能看到额外的调试信息、工具ConfigTool, TungstenTool, REPLTool、错误日志。这不是安全问题但说明"内部版本"和"外部版本"的差异比文档披露的更大。
2. **ToolSearchTool 的 RL 评分权重:** `12/10/6/5/4/3/2` 的精细评分体系不是手工调整的——它暗示着**持续的 A/B 实验和 RL 优化**在背后运行。
3. **GrowthBook 动态配置的深度:** 不仅是 feature flag还包括事件采样率、批处理大小、sink kill switch、甚至 `tengu_max_version_config` 这种远程杀死特定版本的开关。
---
## 4. 解剖:遥测系统的五层架构
### 第一层事件生成Event Generation
事件在代码各处通过 `logEvent('event_name', metadata)` 生成。事件名称遵循 `tengu_<领域>_<动作>` 的命名规范。
```typescript
// 典型的事件生成点
logEvent('tengu_tool_search_outcome', {
query, queryType, matchCount, totalDeferredTools, maxResults, hasMatches
})
```
metadata 的类型约束是 `{ [key: string]: boolean | number | undefined }` —— 禁止传递字符串,避免意外上传代码。
### 第二层事件增强Event Enrichment
在进入 sink 之前,每个事件被 `getEventMetadata()` 增强,注入:
- **会话上下文:** sessionId, clientType, isInteractive
- **环境上下文:** 操作系统、终端、包管理器、CI 检测
- **模型信息:** 当前使用的模型、betas、provider
- **用户信息:** userType, subscriptionType, userBucket
- **进程指标:** RSS, heapUsed, cpuUsage仅在 Datadog 路径)
`src/services/analytics/metadata.ts` 长达 **966 行**,是这个增强引擎的核心。
### 第三层采样与过滤Sampling & Filtering
事件在发送前经过多层过滤:
```
1. isAnalyticsDisabled() ← 总开关
├── NODE_ENV === 'test'?
├── 3P provider (Bedrock/Vertex/Foundry)?
└── isTelemetryDisabled()?
├── DISABLE_TELEMETRY?
└── CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC?
2. shouldSampleEvent() ← GrowthBook 动态采样
└── tengu_event_sampling_configJSON 配置,按事件名设置采样率)
3. isSinkKilled('datadog' | 'firstParty') ← 按 sink 单独杀死
└── tengu_frond_boric GrowthBook 配置
4. 对 Datadog 额外白名单DATADOG_ALLOWED_EVENTS+ 非生产环境跳过
```
### 第四层事件路由Event Routing
`logEventImpl()``sink.ts` 中将事件分发给两个后端:
```
logEventImpl(eventName, metadata)
├── shouldTrackDatadog()? → trackDatadogEvent()
│ └── POST https://http-intake.logs.datadoghq.com/api/v2/logs
│ 批次大小: 100, 刷新间隔: 15s
└── logEventTo1P() → FirstPartyEventLoggingExporter
└── POST https://api.anthropic.com/api/event_logging/batch
批次大小: 200 (可配置), 刷新间隔: 10s (可配置)
```
### 第五层持久化与重试Persistence & Retry
1P 事件导出器(`firstPartyEventLoggingExporter.ts`**806 行**)具有工业级可靠性:
- **磁盘持久化:** 发送失败的事件写入 `~/.claude/telemetry/1p_failed_events.{sessionId}.{batchId}.json`
- **二次退避重试:** `baseDelay * attempts²`,最长达 30s最多 8 次
- **跨进程恢复:** 启动时重试之前会话的失败文件
- **分级失败处理:** 一个批次失败 → 短路剩余批次 → 全部入队重试
- **并发安全:** 追加写append而非全量写避免覆盖并发事件
---
## 5. 防御:我们做了什么
### 5.1 纵深防御策略
我们的防御策略不是"关掉遥测"——那样会丢失学习这套系统的机会。而是**在遥测管道的最前端插入一个本地分支**
```
logEvent()
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
[本地 JSONL] [Datadog] [Anthropic 1P]
永远执行 可被关闭 可被关闭
自己的数据 运维数据 BigQuery 分析
```
**关键改动(仅 3 个文件,不改任何工具代码):**
1. **`src/services/analytics/localSink.ts`**54 行新文件)
```typescript
// 将事件追加写入 ~/.claude/local_analytics.jsonl
export function writeLocalEvent(eventName, metadata) {
const line = JSON.stringify({
ts: new Date().toISOString(),
event: eventName,
...metadata,
}) + '\n'
fs.appendFileSync(LOCAL_ANALYTICS_FILE, line, 'utf-8')
}
```
2. **`src/services/analytics/index.ts`**(在 `logEvent()` 入口处插入 3 行)
```typescript
// 在所有上游 sink 之前执行
const { writeLocalEvent } = require('./localSink.js')
writeLocalEvent(eventName, metadata)
```
3. **`scripts/analyze_analytics.py`**(分析脚本)
### 5.2 为什么这个方案优于直接关掉遥测
| 方案 | 优点 | 缺点 |
|------|------|------|
| `DISABLE_TELEMETRY=1` | 简单,一键关闭 | 丢失所有数据,学不到东西 |
| 直接删除 analytics 代码 | 彻底 | 破坏代码结构,每次更新需重新修改 |
| **我们的方案:前端分叉** | 保留完整基础设施,数据归自己 | 需额外 200 行代码 + 分析工具 |
### 5.3 .gitignore 防护
```gitignore
# Local analytics data (never upload)
*.jsonl
.claude/
```
确保本地遥测数据绝不会被意外提交到仓库。
---
## 6. 为己所用
### 6.1 本地数据文件
`~/.claude/local_analytics.jsonl` —— 一行一个 JSON 事件:
```json
{"ts":"2026-06-03T10:15:23.456Z","event":"tengu_started","sessionId":"abc123"}
{"ts":"2026-06-03T10:15:24.789Z","event":"tengu_bash_tool_used","toolName":"Bash"}
{"ts":"2026-06-03T10:15:25.012Z","event":"tengu_api_success","model":"claude-sonnet-4-20250514"}
```
### 6.2 分析脚本
```bash
# 查看事件统计报告
python3 scripts/analyze_analytics.py
# 实时追踪事件流
tail -f ~/.claude/local_analytics.jsonl
# 搜索特定事件
grep "tengu_query_error" ~/.claude/local_analytics.jsonl | python3 -m json.tool
# 按天统计使用次数
grep "tengu_started" ~/.claude/local_analytics.jsonl | wc -l
```
### 6.3 你能分析什么
| 分析维度 | 数据来源 | 回答的问题 |
|---------|---------|-----------|
| 工具使用频率 | `tengu_tool_use_*` | 我最常用什么工具Bash 占比多少? |
| 模型 fallback 率 | `tengu_model_fallback_triggered` | 我的 API 稳定性如何? |
| 上下文压缩频率 | `tengu_auto_compact_succeeded` | 我的对话是否经常超出窗口? |
| API 错误类型 | `tengu_query_error` + `http_status` | 什么类型的错误最多? |
| 会话时长/频率 | `tengu_started` / `tengu_exit` | 我每天用多少次?每次多久? |
| 工具搜索行为 | `tengu_tool_search_outcome` | 模型是否能正确找到工具? |
### 6.4 进阶:扩展分析
因为本地 JSONL 包含所有事件的完整 metadata你可以构建
1. **个人使用画像:** 统计最常用的模型、工具组合、操作模式
2. **成本分析:** 结合 token 消耗事件,估算每日 API 费用
3. **效率仪表板:** Pandas/Streamlit 可视化,实时监控 CCB 使用
4. **异常检测:** 监控错误率突增、fallback 异常等
### 6.5 从 Anthropic 学习的最佳实践
这套遥测系统本身就是一个教科书级的案例:
1. **零依赖入口 + 延迟绑定:** `logEvent()` 无依赖sink 通过 `attachAnalyticsSink()` 延迟注入 —— 适合任何需要插拔式后端的系统
2. **多层过滤链:** 总开关 → 采样 → sink kill switch —— 灵活且可远程控制
3. **磁盘兜底 + 指数退避:** 即使网络失败也不丢事件
4. **隐私类型系统:** TypeScript 的 `never` 类型 + 标记模式强制代码审查
5. **GrowthBook 集成模式:** 将 feature flag 变成数据采集工具
---
## 7. 附录:事件词典
以下是代码审计中发现的全部遥测事件(部分代表性事件):
### API & Query
| 事件名 | 描述 |
|--------|------|
| `tengu_query_error` | API 查询错误 |
| `tengu_api_success` | API 调用成功 |
| `tengu_model_fallback_triggered` | 触发模型降级 |
| `tengu_max_tokens_escalate` | Token 上限触发 |
| `tengu_token_budget_completed` | Token 预算耗尽 |
| `tengu_query_before_attachments` | 查询前 attachment 状态 |
| `tengu_query_after_attachments` | 查询后 attachment 状态 |
| `tengu_streaming_tool_execution_used` | 流式工具执行启用 |
| `tengu_streaming_tool_execution_not_used` | 流式工具执行未启用 |
| `tengu_post_autocompact_turn` | 自动压缩后的对话轮次 |
### 工具使用
| 事件名 | 描述 |
|--------|------|
| `tengu_tool_search_outcome` | 工具搜索结果RL 数据) |
| `tengu_bash_tool_used` | Bash 工具被调用 |
| `tengu_tool_use_success` | 工具调用成功 |
| `tengu_tool_use_error` | 工具调用错误 |
| `tengu_tool_use_granted_in_prompt_permanent` | 工具权限永久授予 |
| `tengu_tool_use_granted_in_prompt_temporary` | 工具权限临时授予 |
| `tengu_tool_use_rejected_in_prompt` | 工具权限拒绝 |
### 会话生命周期
| 事件名 | 描述 |
|--------|------|
| `tengu_started` | 启动 |
| `tengu_init` | 初始化完成 |
| `tengu_exit` | 退出 |
| `tengu_cancel` | 用户取消 |
| `tengu_auto_compact_succeeded` | 自动压缩成功 |
| `tengu_orphaned_messages_tombstoned` | 孤儿消息清理 |
### OAuth & 认证
| 事件名 | 描述 |
|--------|------|
| `tengu_oauth_success` | OAuth 登录成功 |
| `tengu_oauth_error` | OAuth 错误 |
| `tengu_oauth_token_refresh_failure` | Token 刷新失败 |
| `tengu_oauth_token_refresh_success` | Token 刷新成功 |
| `tengu_oauth_flow_start` | OAuth 流程启动 |
### 遥测自监控
| 事件名 | 描述 |
|--------|------|
| `analytics_sink_attached` | 遥测 sink 已连接 |
| `tengu_bridge_message_received` | Bridge 消息接收 |
| `tengu_ws_transport_reconnected` | WebSocket 重连 |
---
> **最后的话:** 这套遥测系统的存在本身不是问题——问题在于数据的主权归属。我们的改造方案证明:**你可以在不破坏基础设施的前提下,将数据的所有权从云端拉回本地**。这套代码本身就是最好的教学材料:学习 Anthropic 的工程实践,掌控自己的数据,然后用这些数据来优化自己的工作流。
>
> 光明在于工程的精湛,阴影在于主权的缺失。我们选择照亮阴影,而不是关掉灯光。
---
*文档版本v1.0 | 最后更新2026-06-03*