17 — 遥测、隐私与运营控制:生产环境的暗面
范围:
services/analytics/(9 个模块,~148KB)、utils/undercover.ts、utils/attribution.ts、utils/commitAttribution.ts、utils/fastMode.ts、services/remoteManagedSettings/、constants/prompts.ts、buddy/、voice/、tasks/DreamTask/一句话: 你看不见的生产基础设施——双通道遥测管道、模型代号隐匿、远程紧急开关,以及隐藏在编译时门控背后的未来功能。
目录
- 双通道遥测管道
- 数据采集全景:究竟收集了什么
- 退出困境:用户能否关闭遥测
- 模型代号体系
- Feature Flag 混淆命名
- 卧底模式:隐匿 AI 署名
- 远程控制与紧急开关
- 内外有别的双层体验
- 未来路线图:源码中的证据
1. 双通道遥测管道
源码坐标: src/services/analytics/(9 个文件,合计 ~148KB)
每一次工具调用、每一次 API 请求、每一次会话启动——都会产生遥测事件,流经双通道管道。一条通道直连 Anthropic 自有后端;另一条通向第三方可观测性平台。两者共同构成了 CLI 工具领域最全面的分析系统之一。
1.1 通道 A:第一方直连(Anthropic 自有)
// 源码: src/services/analytics/firstPartyEventLogger.ts:300-302
const DEFAULT_LOGS_EXPORT_INTERVAL_MS = 10000 // 10 秒批量刷新
const DEFAULT_MAX_EXPORT_BATCH_SIZE = 200 // 每批最多 200 事件
const DEFAULT_MAX_QUEUE_SIZE = 8192 // 内存队列上限 8K第一方管道使用 OpenTelemetry 的 LoggerProvider——不是全局实例(那个服务于客户的 OTLP 遥测),而是一个专用的内部 Provider。事件被序列化为 Protocol Buffers,发往:
POST https://api.anthropic.com/api/event_logging/batch容错机制极为激进。导出器(FirstPartyEventLoggingExporter,27KB)实现了:
- 二次退避重试,可配置最大重试次数
- 磁盘持久化——失败的批次写入
~/.claude/telemetry/,进程崩溃后下次启动时自动重试 - 批次配置可通过 GrowthBook(
tengu_1p_event_batch_config)远程调整,即 Anthropic 无需发版即可修改刷新间隔、批次大小甚至目标端点
热插拔安全性值得关注:
// 源码: src/services/analytics/firstPartyEventLogger.ts:396-449
// 当 GrowthBook 在会话中途更新批次配置时:
// 1. 先将 logger 置空——并发调用在守卫处 bail out
// 2. forceFlush() 排空旧处理器的缓冲区
// 3. 切换到新 Provider;旧的在后台关闭
// 4. 磁盘持久化重试文件使用稳定键名(BATCH_UUID + sessionId)
// 新导出器自动接管旧导出器的失败记录1.2 通道 B:Datadog(第三方可观测性)
// 源码: src/services/analytics/datadog.ts:12-17
const DATADOG_LOGS_ENDPOINT = 'https://http-intake.logs.us5.datadoghq.com/api/v2/logs'
const DATADOG_CLIENT_TOKEN = 'pubbbf48e6d78dae54bceaa4acf463299bf'
const DEFAULT_FLUSH_INTERVAL_MS = 15000 // 15 秒刷新
const MAX_BATCH_SIZE = 100Datadog 通道更加严格。只有 64 种预批准事件类型能通过白名单过滤。
三种基数缩减技术防止 Datadog 成本爆炸:
- MCP 工具名归一化:以
mcp__开头的工具统一折叠为"mcp" - 模型名归一化:未知模型折叠为
"other" - 用户分桶:通过
SHA256(userId) % 30将用户哈希到 30 个桶中,实现近似唯一用户告警
1.3 事件采样:GrowthBook 控制的音量旋钮
// 源码: src/services/analytics/firstPartyEventLogger.ts:38-85
export function shouldSampleEvent(eventName: string): number | null {
const config = getEventSamplingConfig() // 来自 GrowthBook
const eventConfig = config[eventName]
if (!eventConfig) return null // 无配置 → 100% 采集
const sampleRate = eventConfig.sample_rate
if (sampleRate >= 1) return null // 1.0 → 全量采集
if (sampleRate <= 0) return 0 // 0.0 → 全量丢弃
return Math.random() < sampleRate ? sampleRate : 0 // 概率采样
}→ 交叉引用: 第 16 集: 基础设施 了解 GrowthBook 集成细节
2. 数据采集全景:究竟收集了什么
源码坐标: src/services/analytics/metadata.ts(33KB——最大的分析文件)
每个遥测事件携带三层元数据,由 getEventMetadata() 组装:
2.1 第一层:环境指纹
┌─────────────────────────────────────────────────────────────────┐
│ 环境指纹(14+ 字段) │
├──────────────────┬──────────────────────────────────────────────┤
│ 运行时 │ platform, arch, nodeVersion │
│ 终端 │ 终端类型 (iTerm2 / Terminal.app / ...) │
│ 开发环境 │ 已安装的包管理器和运行时 │
│ CI/CD │ CI 检测, GitHub Actions 元数据 │
│ 操作系统 │ WSL 版本, Linux 发行版, 内核版本 │
│ 版本控制 │ VCS 类型 │
│ Claude Code │ 版本号, 构建时间戳 │
└──────────────────┴──────────────────────────────────────────────┘2.2 第二层:进程健康指标
┌─────────────────────────────────────────────────────────────────┐
│ 进程指标(8+ 指标) │
├──────────────────┬──────────────────────────────────────────────┤
│ 计时 │ 进程运行时间 │
│ 内存 │ rss, heapTotal, heapUsed, external, arrays │
│ CPU │ 使用时间, 百分比 │
└──────────────────┴──────────────────────────────────────────────┘2.3 第三层:用户与会话身份
┌─────────────────────────────────────────────────────────────────┐
│ 用户与会话追踪 │
├──────────────────┬──────────────────────────────────────────────┤
│ 模型 │ 当前活跃模型名 │
│ 会话 │ sessionId, parentSessionId │
│ 设备 │ deviceId(跨会话持久化) │
│ 账户 │ accountUUID, organizationUUID │
│ 订阅 │ 套餐层级 (max, pro, enterprise, team) │
│ 仓库 │ 远端 URL 哈希(SHA256,取前 16 字符) │
└──────────────────┴──────────────────────────────────────────────┘仓库指纹值得关注——系统对远端 URL 取 SHA256 后截断为 16 位十六进制。这不是匿名化,而是伪匿名化。知道目标仓库 URL 的人可以轻松计算哈希并匹配。
2.4 Bash 命令扩展名追踪
当执行涉及 17 种特定命令(rm、mv、cp、touch、mkdir、chmod、chown、cat、head、tail、sort、stat、diff、wc、grep、rg、sed)的操作时,系统会提取并记录参数中的文件扩展名,形成你的工作模式画像。
3. 退出困境:用户能否关闭遥测
源码坐标: src/services/analytics/firstPartyEventLogger.ts:141-144
3.1 分析功能何时禁用
// 源码: src/services/analytics/config.ts
// isAnalyticsDisabled() 仅在以下情况返回 true:
// 1. 测试环境 (NODE_ENV !== 'production')
// 2. 第三方云供应商 (Bedrock, Vertex)
// 3. 全局遥测退出标志对于直连 Anthropic API 的用户(绝大多数),isAnalyticsDisabled() 返回 false。没有设置面板、没有 CLI 参数、没有环境变量能让普通用户在保持完整产品功能的同时禁用第一方事件记录。
3.2 远程关闭开关
讽刺的是,Anthropic 自己可以远程禁用分析——但这个能力不属于用户:
// 源码: src/services/analytics/sinkKillswitch.ts
const SINK_KILLSWITCH_CONFIG_NAME = 'tengu_frond_boric'
// GrowthBook 标志,可远程禁用分析通道3.3 合规影响
(1)无用户侧退出机制、(2)持久化设备和会话追踪、(3)仓库指纹、(4)组织级识别——这四者组合创建的数据集完全落入 GDPR 第 6 条和 CCPA §1798.100 的管辖范围。
→ 设计模式: 失败时仍投递(stale-while-error)策略——磁盘持久化 + 重试优先保证投递完整性,而非用户控制权。
4. 模型代号体系
源码坐标: src/utils/undercover.ts:48-49、src/constants/prompts.ts、src/migrations/migrateFennecToOpus.ts、src/buddy/types.ts
Anthropic 为内部模型版本分配动物代号——源码揭示了具体代号、演化谱系,以及为防止泄露而构建的精密机制。
4.1 四个已知代号
| 代号 | 动物 | 角色 | 证据 |
|---|---|---|---|
| Capybara | 水豚 | Sonnet 系列,当前 v8 | 模型字符串中的 capybara-v2-fast[1m] |
| Tengu | 天狗 | 产品/遥测前缀 | 250+ 分析事件和功能标志均使用 tengu_* |
| Fennec | 耳廓狐 | Opus 4.6 的前身 | 迁移脚本: fennec-latest → opus |
| Numbat | 袋食蚁兽 | 下一代未发布模型 | 注释: "Remove this section when we launch numbat" |
4.2 代号保护机制
三层防线阻止代号泄露到外部构建中:
第一层: 构建时扫描器 — scripts/excluded-strings.txt 包含构建输出中会被 CI 扫描的模式,匹配则构建失败。
第二层: 运行时混淆 — 代号在用户可见字符串中被主动遮蔽(cap***** -v2-fast)。
第三层: 源码级碰撞规避 — Buddy 宠物系统的"capybara"物种名与模型代号扫描器冲突。解决方案:运行时用 String.fromCharCode 逐字符编码。
4.3 Capybara v8:五个已记录的行为缺陷
| # | 缺陷 | 影响 | 源码位置 |
|---|---|---|---|
| 1 | 停止序列误触发 | 当 <functions> 出现在提示词尾部时约 10% 概率 | prompts.ts |
| 2 | 空 tool_result 零输出 | 收到空白工具结果时模型不生成任何内容 | toolResultStorage.ts:281 |
| 3 | 过度注释 | 需要专门的反注释提示词补丁 | prompts.ts:204 |
| 4 | 高错误声称率 | 29-30% FC 率 vs Capybara v4 的 16.7% | prompts.ts:237 |
| 5 | 验证不充分 | 需要"彻底性反制"提示词注入 | prompts.ts:210 |
代码库包含 8+ 个 @[MODEL LAUNCH] 标记,涵盖:默认模型名、家族 ID、知识截止日期、定价表、上下文窗口配置等。
5. Feature Flag 混淆命名
源码坐标: src/services/analytics/growthbook.ts(41KB)
5.1 Tengu 命名约定
每个功能标志和分析事件遵循 tengu_<词1>_<词2> 的命名模式,词汇对从受限词库中选取——对内部人员可记忆,对外部观察者不透明。
| 标志名 | 解码后的用途 | 类别 |
|---|---|---|
tengu_frond_boric | 分析通道紧急关闭 | 紧急开关 |
tengu_amber_quartz_disabled | 语音模式紧急关闭 | 紧急开关 |
tengu_turtle_carbon | Ultrathink 门控 | 功能门控 |
tengu_marble_sandcastle | 快速模式(Penguin)门控 | 功能门控 |
tengu_onyx_plover | Auto-Dream(后台记忆) | 功能门控 |
tengu_event_sampling_config | 按事件采样率 | 配置 |
tengu_1p_event_batch_config | 1P 批处理器配置 | 配置 |
tengu_ant_model_override | 内部模型覆盖 | 内部 |
5.2 三层标志解析架构
┌─────────────────────────────────────────────────────────────────┐
│ 第 1 层: 编译时死代码消除 (DCE) │
│ 机制: feature('FLAG_NAME') via bun:bundle │
│ 效果: 代码分支在构建时被完全移除 │
├─────────────────────────────────────────────────────────────────┤
│ 第 2 层: 运行时环境变量检查 │
│ 机制: process.env.USER_TYPE === 'ant' │
│ 效果: 代码存在但对外部用户被跳过 │
├─────────────────────────────────────────────────────────────────┤
│ 第 3 层: 运行时 GrowthBook 标志 │
│ 机制: getFeatureValue('tengu_*') via GrowthBook SDK │
│ 效果: 可按用户、按会话、按实验动态变更 │
└─────────────────────────────────────────────────────────────────┘部分功能使用双重门控——第 1 层编译时门控 + 第 3 层运行时标志。在外部构建中,feature('ULTRATHINK') 为 false,整个函数体被死代码消除。
5.3 通道紧急开关的循环依赖
tengu_frond_boric 的实现揭示了一个循环依赖陷阱:GrowthBook 初始化调用 is1PEventLoggingEnabled(),后者如果调用 isSinkKilled() 又会调用 GrowthBook——无限递归。解决方案:在每个事件分发点检查紧急开关,而非在全局启用检查中。
→ 交叉引用: 第 16 集: 基础设施 §1.3
6. 卧底模式:隐匿 AI 署名
源码坐标: src/utils/undercover.ts(90 行)、src/utils/attribution.ts(394 行)
当 Anthropic 员工使用 Claude Code 向开源仓库贡献代码时,一套专用系统会自动激活,擦除所有 AI 参与痕迹。
6.1 激活逻辑
// 源码: src/utils/undercover.ts:28-37
export function isUndercover(): boolean {
if (process.env.USER_TYPE === 'ant') { // 仅限 Anthropic 员工
if (isEnvTruthy(process.env.CLAUDE_CODE_UNDERCOVER)) return true // 强制开启
return getRepoClassCached() !== 'internal' // 非内部仓库 → 自动开启
}
return false // 外部用户: 始终关闭(生产构建中被 DCE)
}关键设计决策:没有强制关闭选项。如果系统无法确认当前仓库在 Anthropic 内部白名单上,卧底模式自动激活。
6.2 卧底提示词
激活后,模型收到七条明确的隐匿指令,禁止在 commit 消息和 PR 中出现:
- 内部模型代号(Capybara、Tengu 等动物名)
- 未发布模型版本号
- 内部仓库或项目名称
- 内部工具、Slack 频道或短链接
- "Claude Code"或任何 AI 相关表述
- Co-Authored-By 行或任何其他署名
6.3 署名擦除
// 源码: src/utils/attribution.ts:52-55
export function getAttributionTexts(): AttributionTexts {
if (process.env.USER_TYPE === 'ant' && isUndercover()) {
return { commit: '', pr: '' } // 空字符串 = 无署名
}
}正常模式下 commit 附带 Co-Authored-By: Claude Opus 4.6,PR 附带 🤖 Generated with Claude Code。卧底模式下两者均返回空字符串。
6.4 增强版 PR 署名(非卧底模式)
非卧底状态下,署名系统生成丰富的统计信息:
🤖 Generated with Claude Code (93% 3-shotted by claude-opus-4-5, 2 memories recalled)包含:Claude 代码贡献百分比、提示词轮次(N-shotted)、模型名、记忆文件访问次数。
6.5 伦理思考
卧底模式引发关于 AI 透明度的根本性问题:贡献者真实性、开源许可证合规性、社区信任、以及与 EU AI Act 第 50 条的潜在冲突。
→ 设计模式: 失败时隐匿(Fail-safe concealment)——不确定时默认隐藏,需显式白名单才会暴露。
7. 远程控制与紧急开关
源码坐标: src/services/remoteManagedSettings/(5 个文件,~43KB)
Claude Code 不仅是本地工具——它维持着与 Anthropic 服务器的持久连接,Anthropic 可以远程改变其行为、执行策略或关闭功能。
7.1 远程托管设置
// 源码: src/services/remoteManagedSettings/index.ts:52-54
const SETTINGS_TIMEOUT_MS = 10000 // 10 秒超时
const DEFAULT_MAX_RETRIES = 5 // 最多 5 次重试
const POLLING_INTERVAL_MS = 3600000 // 每小时后台轮询获取生命周期实现了 stale-while-revalidate 语义:
- 启动时缓存优先:有磁盘缓存则立即应用
- 后台获取:5 次指数退避重试
- ETag 缓存:SHA256 校验和支持 HTTP 304
- 每小时轮询:后台定时检查设置变更
- 失败开放:所有获取失败则继续使用陈旧缓存
7.2 "接受或退出"对话框
当远程设置包含"危险"变更时,出现阻塞式安全对话框:
// 源码: src/services/remoteManagedSettings/securityCheck.tsx:67-73
export function handleSecurityCheckResult(result: SecurityCheckResult): boolean {
if (result === 'rejected') {
gracefulShutdownSync(1) // 退出码 1 —— 进程终止
return false
}
return true
}用户只有两个选择:接受新设置,或进程以退出码 1 终止。没有"稍后再说"选项。在非交互模式(CI/CD)下,安全检查被完全跳过——危险设置静默应用。
7.3 六大紧急开关
| # | 开关 | 机制 | 触发效果 |
|---|---|---|---|
| 1 | 权限体系旁路 | bypassPermissionsKillswitch.ts | 禁用整个权限系统 |
| 2 | 自动模式断路器 | autoModeDenials.ts | 紧急中断自主执行 |
| 3 | 快速模式(Penguin) | tengu_marble_sandcastle + API | 切换到更便宜的模型 |
| 4 | 分析通道 | tengu_frond_boric | 禁用 Datadog/1P 日志 |
| 5 | 代理团队 | tengu_amber_flint | 门控多代理协作 |
| 6 | 语音模式 | tengu_amber_quartz_disabled | 紧急禁用语音输入 |
7.4 Penguin 模式(快速模式远程控制)
Anthropic 可远程将用户从昂贵模型切换到更便宜的替代品。结合 GrowthBook A/B 分配和独立紧急开关,用户请求所使用的模型可在会话中途根据 Anthropic 的运营决策而改变。
→ 交叉引用: 第 16 集: 基础设施 了解五层设置合并系统
8. 内外有别的双层体验
源码坐标: src/constants/prompts.ts、src/tools/、src/commands.ts
Anthropic 员工与外部用户体验着根本不同版本的 Claude Code。差异横跨提示词、工具、命令和模型行为。
8.1 提示词差异:六个维度
| 维度 | 外部用户 | Anthropic 员工 (ant) |
|---|---|---|
| 输出风格 | 标准格式 | GrowthBook 覆盖 |
| 错误声称缓解 | Capybara v8 补丁 | 同上 + 数值锚定提示 |
| 验证机制 | 标准验证 | 验证代理 + 彻底性反制 |
| 注释控制 | 标准指导 | 专用反过度注释补丁 |
| 主动纠错 | 标准行为 | 增强型"果断性反制"(PR #24302) |
| 模型感知 | 无法看到代号 | 可见内部模型名 + 调试工具 |
8.2 内部专用工具(5 个)
| 工具 | 用途 | 门控层级 |
|---|---|---|
| REPLTool | 内联代码执行 | 第 2 层(环境变量) |
| TungstenTool | 内部调试诊断 | 第 2 层 |
| VerifyPlanTool | 计划验证代理 | 第 3 层(tengu_hive_evidence) |
| SuggestBackgroundPR | 后台 PR 建议 | 第 1 层(feature()) |
| Nested Agent | 进程内子代理 | 第 2 层 |
8.3 隐藏命令(7 个)
| 命令 | 用途 | 访问权限 |
|---|---|---|
/btw | 旁白注入 | 仅内部 |
/stickers | 终端贴纸/艺术 | 可解锁 |
/thinkback | 回放上次思维链 | 调试模式 |
/effort | 调整思维深度 | 仅内部 |
/buddy | 召唤虚拟伙伴(见 §9) | feature() 门控 |
/good-claude | 正向强化 | 仅内部 |
/bughunter | 激活 Bug 猎手模式 | 仅内部 |
9. 未来路线图:源码中的证据
源码坐标: src/tasks/DreamTask/、src/buddy/、src/voice/、src/coordinator/
源码包含大量编译时门控但架构上已完整的功能实现。
9.1 Numbat:下一代模型
prompts.ts 中的 @[MODEL LAUNCH] 标记引用了 opus-4-7 和 sonnet-4-8 等模型 ID,强烈暗示 Numbat 是下一代主要模型家族的代号。
9.2 KAIROS:自主代理模式
feature('KAIROS') 背后存在完整的自主执行模式——基于心跳的 tick 驱动、焦点感知、OS 推送通知、GitHub PR 订阅、定时休眠/唤醒。
9.3 语音模式
feature('VOICE_MODE') 背后:按键说话、WebSocket 实时语音转文字(21KB)、mTLS 认证、OAuth 限制、技术术语自定义词表。
9.4 Buddy 虚拟伙伴系统
最具趣味性的功能——完整的虚拟宠物系统(6 个文件,~76KB):
18 个物种(全部通过 String.fromCharCode 编码以规避代号扫描器):
duck, goose, blob, cat, dragon, octopus, owl, penguin,
turtle, snail, ghost, axolotl, capybara, cactus, robot,
rabbit, mushroom, chonk5 个稀有度等级(加权分布):Common(60%) → Uncommon(25%) → Rare(10%) → Epic(4%) → Legendary(1%)
闪光变体:~1% 概率,由 hash(userId) 确定性决定,防止用户"刷号"。
每个伙伴有灵魂(模型生成的名字和性格,存储在配置中)和骨架(物种、稀有度、属性,每次读取从 hash(userId) 重新生成)——确保用户无法通过编辑配置文件升级到传说级。
9.5 未发布工具(11 个)
| 工具 | 用途 | 门控 |
|---|---|---|
| SleepTool | 定时暂停/恢复 | feature('KAIROS') |
| PushNotificationTool | OS 通知推送 | feature('KAIROS') |
| SubscribePRTool | GitHub PR 订阅 | feature('KAIROS') |
| DaemonTool | 后台进程管理 | feature('DAEMON') |
| CoordinatorTool | 多代理协调 | feature('COORDINATOR_MODE') |
| MorerightTool | 上下文窗口扩展 | feature('MORERIGHT') |
| DreamConsolidationTool | 后台记忆整合 | feature('AUTO_DREAM') |
| DxtTool | DXT 插件打包 | feature('DXT') |
| UltraplanTool | 高级多步规划 | feature('ULTRAPLAN') |
| VoiceInputTool | 语音转文字输入 | feature('VOICE_MODE') |
| BuddyTool | 虚拟伙伴召唤 | feature('BUDDY') |
9.6 三大战略方向
未发布功能聚集为三个清晰的战略方向:
- 自主代理(KAIROS + Dream + Coordinator):从被动工具迈向主动代理
- 多模态输入(Voice + Computer Use 增强):突破纯文本交互
- 社交/情感(Buddy + Stickers + Team Memory):创建参与循环和团队协作
这些方向表明 Claude Code 的长期愿景不是"更好的代码补全",而是"具备社交功能的自主软件工程代理"。
源码坐标汇总
| 组件 | 关键文件 | 规模 |
|---|---|---|
| 分析管道 | services/analytics/(9 个文件) | 148KB |
| 卧底模式 | utils/undercover.ts | 3.7KB |
| 署名系统 | utils/attribution.ts + commitAttribution.ts | 44KB |
| 远程设置 | services/remoteManagedSettings/(5 个文件) | 43KB |
| 快速模式 | utils/fastMode.ts | 18KB |
| GrowthBook | services/analytics/growthbook.ts | 41KB |
| Buddy 系统 | buddy/(6 个文件) | 76KB |
| 语音系统 | voice/ + services/voice*.ts | 45KB |
可复用设计模式
| 模式 | 应用场景 | 要点 |
|---|---|---|
| 双通道分析 | 1P + Datadog | 内外分析通道使用不同保留策略 |
| 基数缩减 | 用户分桶、MCP 归一化 | 哈希分桶 (mod N) 实现近似唯一用户计数 |
| 热插拔重配置 | 1P 日志器重建 | 置空守卫 → 刷新 → 切换 → 后台关闭 |
| 失败时隐匿 | 卧底模式 | 默认最大程度隐匿;需显式白名单才暴露 |
| 接受或退出 | 安全对话框 | 无"稍后再说"防止无限期推迟安全决策 |
| 三层功能门控 | DCE + env + GrowthBook | 编译时、构建时、运行时三层纵深防御 |
| 代号碰撞规避 | Buddy 物种编码 | String.fromCharCode 防止静态扫描器误报 |
| 陈旧时仍验证 | 远程设置 | 缓存优先启动 + 后台刷新最小化用户可感知延迟 |
下一集: 第 00 集: 总纲 — 三万英尺高空
上一集: 第 16 集: 基础设施与配置