- Add Vite as alternative build (vite.config.ts, scripts/vite-plugin-*)
- Add dab04af7 RSS fix (distRoot, ripgrep path, post-build)
- Pull in packages/builtin-tools/ (+354 files)
- Pull in packages/agent-tools/, mcp-client/, acp-link/, weixin/
- Copy defines.ts from upstream for Vite compatibility
- Update package.json with Vite scripts and deps
6.7 KiB
CC_Pure 遥测清理方案
项目:claude-code-best (ccb) v2.1.888 → CC_Pure 仓库:https://github.com/GhostDragon124/CC_Pure 审计报告:docs/telemetry-cleanup-audit.md
一、背景:ccb 里有哪些遥测系统
ccb 是从 Anthropic 官方 Claude Code 反编译还原的项目。源码中包含 6 个遥测系统:
| # | 系统 | 数据流向 | 默认状态 |
|---|---|---|---|
| 1 | Datadog 日志 | api.datadoghq.com |
✅ ccb 已清空端点/Token,默认禁用 |
| 2 | Sentry 错误上报 | sentry.io |
✅ ccb 未配置 DSN,默认 no-op |
| 3 | OpenTelemetry | 用户自配 OTLP 端点 | ✅ 需显式设 CLAUDE_CODE_ENABLE_TELEMETRY=1 |
| 4 | 1P Event Logging | api.anthropic.com/api/event_logging/batch |
🔴 默认启用 |
| 5 | GrowthBook 远程配置 | api.anthropic.com/ |
🔴 默认启用 |
| 6 | BigQuery Metrics | api.anthropic.com/api/claude_code/metrics |
🔴 默认启用 |
实测验证(strace 网络抓包)
测试:strace -f -e trace=network ccb --print -p "hello"
| 环境变量 | api.anthropic.com 连接数 |
|---|---|
| 无防护 | 1 次 |
DISABLE_TELEMETRY=1 |
1 次(未完全阻断!) |
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 |
0 次 ✅ |
结论:CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 是唯一能完全阻断的配置。
二、清理方案:纵深防御(4 层)
核心思路:环境变量做入口防御 + 源码级切断关键初始化路径,不做"自欺欺人"式的 return true。
第 1 层:ccb wrapper(配置防御)
文件:~/.local/bin/ccb
#!/bin/bash
export PATH="$HOME/.bun/bin:$PATH"
# CC_Pure: 防御层 — 阻断所有非必要网络流量(遥测、自动更新等)
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
exec bun /home/spark/workspace/claude-code-best/dist/cli.js "$@"
原理:该环境变量触发 privacyLevel = 'essential-traffic',使:
isTelemetryDisabled()→trueisAnalyticsDisabled()→true(因为isTelemetryDisabled()为 true)- 从而 Datadog、1P Event Logging、BigQuery Metrics 全部失效
第 2 层:init.ts — 切断启动时遥测初始化
文件:src/entrypoints/init.ts
改动 A(约 L95-106):注释掉 GrowthBook + 1P Event Logging 的动态 import 和初始化:
// 改前:
void Promise.all([
import('../services/analytics/firstPartyEventLogger.js'),
import('../services/analytics/growthbook.js'),
]).then(([fp, gb]) => {
fp.initialize1PEventLogging()
gb.onGrowthBookRefresh(() => {
void fp.reinitialize1PEventLoggingIfConfigChanged()
})
})
// 改后:
// CC_Pure: GrowthBook + 1P Event Logging 已永久禁用
// (原代码保留以供参考)
// void Promise.all([...]).then(...)
原因:即使 isAnalyticsDisabled() 返回 true,这段代码仍会加载模块并连接 GrowthBook。实测中 DISABLE_TELEMETRY=1 下仍有 1 次 api.anthropic.com 连接,很可能就是这一段绕过的。
改动 B(L292):doInitializeTelemetry() 函数体开头加 early return:
// 改前:
async function doInitializeTelemetry(): Promise<void> {
if (telemetryInitialized) { return }
telemetryInitialized = true
try { await setMeterState() } catch ...
// 改后:
async function doInitializeTelemetry(): Promise<void> {
// CC_Pure: 遥测已完全禁用
return;
// ... 原代码保留
原因:setMeterState() 会动态 import ~400KB 的 OpenTelemetry SDK,即使最终不导出数据也不该加载。
第 3 层:sinks.ts — 不挂载遥测事件管道
文件:src/utils/sinks.ts
// 改前:
export function initSinks(): void {
initializeErrorLogSink()
initializeAnalyticsSink() // ← 挂载遥测管道
}
// 改后:
export function initSinks(): void {
initializeErrorLogSink()
// CC_Pure: Analytics sink 已永久禁用
// initializeAnalyticsSink()
}
原因:initializeAnalyticsSink() 会把所有 logEvent("tengu_xxx") 调用路由到 Datadog + 1P Event Logging。注释掉后,所有 logEvent() 调用变成空操作(事件排队但永不 flush)。
注意:initializeErrorLogSink() 保留——它只写本地错误日志,不涉及网络。
第 4 层:main.tsx — 不初始化 Analytics Gate
文件:src/main.tsx L691
// 改前:
void initializeAnalyticsGates();
// 改后:
// CC_Pure: Analytics gate 初始化已永久禁用
// void initializeAnalyticsGates();
原因:initializeAnalyticsGates() 调用 GrowthBook 的 checkStatsigFeatureGate_CACHED_MAY_BE_STALE(),会读取本地缓存的远程配置。虽然第 2 层已切断 GrowthBook 的初始化,但为防御纵深也注释掉。
三、不改的文件及原因
src/services/analytics/config.ts — 不修改
该文件保持原样,isAnalyticsDisabled() 仍为条件判断:
export function isAnalyticsDisabled(): boolean {
return (
process.env.NODE_ENV === 'test' ||
isEnvTruthy(process.env.CLAUDE_CODE_USE_BEDROCK) ||
isEnvTruthy(process.env.CLAUDE_CODE_USE_VERTEX) ||
isEnvTruthy(process.env.CLAUDE_CODE_USE_FOUNDRY) ||
isTelemetryDisabled()
)
}
不做 return true 硬编码。原因:
- 第 1 层(环境变量)已经让它在正常运行时返回 true
- 硬编码
return true是"自欺欺人"——改返回值但不改调用逻辑 - 保留原逻辑可以让后续维护者理解原始设计意图
其他不修改的文件
src/services/analytics/growthbook.ts— 1256 行,初始化入口已在 init.ts 切断src/services/analytics/firstPartyEventLogger.ts— 449 行,同上src/utils/telemetry/*— 初始化入口已在 init.ts 切断package.json、build.ts、tsconfig.json— 完全不碰- 所有功能代码(工具、API、UI、Bridge、Daemon) — 完全不碰
四、改动汇总
| 文件 | 改动行数 | 类型 |
|---|---|---|
~/.local/bin/ccb |
+1 行 | 配置(环境变量) |
src/entrypoints/init.ts |
~20 行注释 | 源码(切断初始化) |
src/utils/sinks.ts |
1 行注释 | 源码(切断管道) |
src/main.tsx |
1 行注释 | 源码(切断门控) |
src/services/analytics/config.ts |
不修改 | — |
总计:3 个源文件,4 处注释级改动。
五、验证方法
# strace 网络抓包
strace -f -e trace=network -o /tmp/ccb_test.log \
ccb --print --dangerously-skip-permissions -p "say hello" 2>&1
# 检查是否有 api.anthropic.com 连接
grep "api.anthropic" /tmp/ccb_test.log
# 期望输出:(空)— 零连接