Claude Code · 遥测检查
Claude Code 会把什么发出去?
我检查 Claude Code 有没有读取 MAC 地址和机器序列号时,也翻了本机的遥测目录。里面有 8 个发送失败的事件文件,共 173 条记录。
这次拆的是 macOS arm64 版 2.1.280,磁盘上的记录则来自 2.1.197 到 2.1.220。我用它们对照字段和生成代码,没有把旧日志当作新版本的运行结果。安装包哈希和复核方法放在文末。
设备 ID 从哪来
~/.claude/telemetry/ 中的这 173 条记录用了同一个设备 ID。其中 53 条带有账户和组织 UUID,37 条带有 Git HEAD SHA,也就是 Git 当前提交的标识。除了能把记录归到同一份安装下,部分记录还可以对应到账户和代码提交。
记录里还有一个叫 additional_metadata 的附加字段。它是 Base64 编码的 JSON,解码后能看到提示词长度、耗时、hook 名、模型提供商和操作分类。Base64 不提供加密保护,这些字段在本地就能读出来。
设备 ID 来自 ~/.claude.json 中的 userID。生成它的代码使用密码学随机数,没有拿 MAC 或序列号作输入。这个值保存到本地后会被反复使用,在 Anthropic 事件里叫 device_id。因此,即使没有硬件编号,同一份安装产生的多条记录仍能按这个值关联。
配置里另一个字段 machineID 也来自随机字节。Datadog 错误报告会取它的前 12 个字符。模型请求也有自己的标识字段:metadata.user_id 中包含设备和会话标识。
~/.claude.json 中的 userID登录后部分记录还带账户 UUID
这些文件属于发送失败队列。我没有对应时段的网络记录,不知道哪些后来重试成功,也不知道服务端收到了多少。
改了 API 地址,还会往哪里发
模型请求会携带你的问题、放进上下文的代码,以及工具执行结果,发到当前使用的模型服务端。关闭遥测后,完成任务所需的这些请求仍会发送。
在 2.1.280 的代码里,我还找到了 Anthropic 事件批次接口和 Datadog 日志的发送路径。前者接收使用事件,后者接收一部分事件的副本及错误报告。能否发出,还要经过提供商、凭据、禁用设置和采样等条件的检查。官方网络文档列出的两个 Datadog 接收地址,也分别对应运行事件和错误报告。
OpenTelemetry 用来把监控日志和指标导出到配置的接收地址。这个地址可以由用户设置,也可以由组织的托管配置下发。它和 Anthropic 自己的运行遥测分开,配置方法见官方监控文档。
接收提示词、上下文、工具结果和会话标识等。
核心代码和内置 telemetry 插件构造的事件,可发往 api.anthropic.com。
选定事件的副本和错误报告,分别使用两个日志接收地址。
通过导出器,把日志和环境属性发到配置的 OTLP 接收端。
我还查了自定义模型地址 ANTHROPIC_BASE_URL。已追到的核心遥测代码没有直接把这个变量作为禁用条件,所以单凭改了模型地址,还不能判断其他上报是否停止。自定义地址如何影响凭据,以及这些影响会不会继续阻止发送,这次没有全部追完。
日志里会不会有提示词和代码
我按 JavaScript 中直接写出的事件名统计了调用点:2,603 处调用,1,713 种事件名,分布在 261 个模块里。它们覆盖的是程序可能记录的操作,不是一次会话实际发送的条数。动态拼出的事件名没有计入;通过展开运算符合并进去的字段,也需要回头查它们的来源。
内置 telemetry 插件不接受任意文本字符串,只收布尔值、有限数值和预先列好的选项。核心事件则在各个调用位置处理参数。普通模式下,没有统一的字段白名单覆盖所有事件。
例如,查过的 Bash 事件会先解析命令,再记录命令类别、白名单中的程序名和结构特征;API 错误事件记录限定的错误类型、状态和重试次数;一些工具异常会把错误消息处理成哈希和堆栈特征。几个名叫 paths 的字段里,实际装的是计数或枚举值,没有路径原文。
tengu_* 调用↓分别处理事件参数↓附加数据编码为 Base64 JSON普通模式下没有覆盖所有事件的统一字段白名单$.telemetry.log / mark↓拒绝任意文本字符串↓接收布尔值、有限数值、预设选项只有内置和核心来源能调用该接口/api/event_logging/v2/batch我也按绝对路径、邮箱和令牌的常见格式扫描了那 173 条旧记录,没有命中。在查过的默认遥测代码中,没有发现发送完整提示词、源文件正文或原始 Bash 命令的路径。不过,上千种事件的字段还没有全部查完,这个结果不能推广到整套程序。
Datadog 的两类上报也会处理字段。事件副本先删去一组敏感字段,再统一工具名、模型名和 HTTP 状态的格式;错误报告会清洗异常消息和堆栈,并限制单个进程中排队的报告数量。清洗规则可能漏掉用户自定义的秘密值。包里还能搜到 sentry.io,但沿着 logError 查到实际的 POST 后,这条 CLI 错误上报用的是 Datadog。
OpenTelemetry 可以通过配置记录提示词原文。OTEL_LOG_USER_PROMPTS 默认关闭;开启它,并启用相应的日志导出后,提示词内容就能进入配置的监控接收端。
官方文档还列出默认关闭的 OTEL_LOG_RAW_API_BODIES,可以记录包含对话历史的模型 API 请求和响应 JSON。设为 1 时,正文写进日志事件,超过内容长度限制会被截断;文件模式把未截断内容写到本地,事件里放文件引用。文件保存在本地,不代表文件正文已随事件上传。这部分是文档中的配置说明,没有在本机补做导出测试。
MAC、序列号和时区
在提取出的 JavaScript 中,我没有找到常见的 MAC 地址和机身序列号读取调用。不过,随包的 OpenTelemetry 组件里有一处 ioreg 调用,会读取 IOPlatformUUID。这项结果能否导出,还取决于相应的环境信息检测和 OTLP 导出是否启用;本次检查的普通本机会话中,没有看到已配置的 OTLP 接收地址。
hostname,也就是主机名,用在监控环境信息、远程控制的设备名和本地同意记录等地方。本机 IP 还要区分读取网卡地址与网络连接本身:已检查的 JS 没有主动读取网卡 IP 的应用调用,接收请求的服务器仍然能看到连接的来源 IP。
包内还有截屏、输入和录音相关的三个原生扩展。我没有发现它们在后台自动录制并通过默认遥测上传的证据,但也没有完成这些扩展的反编译审计。
getMachineId 调用 ioreg需要相应的环境信息检测和 OTLP 导出生效时区还有一条旧版本的线索。2026 年 6 月,一位用户在 Claude Code 仓库提交的报告展示了日期行的变化:自定义 API 主机名不同,系统提示词会换用外观接近的撇号;某些时区还会改变日期分隔符。变化直接出现在发给模型的文字里,没有使用单独的遥测字段。报告描述了现象,不能据此确认这些字符变化的用途。
我对照检查了 2.1.280 的日期行构造。它用普通 ASCII 撇号和 YYYY-MM-DD 格式,没有找到旧报告里的字符选择逻辑。这个结果只针对本次的 macOS 安装包。
'’ʼʹYYYY/MM/DDToday's date isYYYY-MM-DD哪些开关能关闭上报
按 2026 年 9 月 24 日核对的官方数据使用文档,可以用下面的命令启动 Claude Code,关闭非必要流量:
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 claude
单独关闭使用指标用 DISABLE_TELEMETRY=1,关闭错误报告用 DISABLE_ERROR_REPORTING=1。前者和关闭非必要流量的总开关,还会停用 Remote Control 依赖的功能标志检查;只关错误报告不会。
这些功能标志由服务端下发,客户端据此启用或关闭部分功能。检查当天,我的本机缓存里有 700 个 GrowthBook 标志。其中一条远程控制路径会在相应标志关闭后停止服务。
tengu_ccr_bridgeDISABLE_TELEMETRY 等700 个是当天的缓存数量,我没有逐项审完。这条远程控制代码能说明服务端配置会影响功能,但不能证明远端可以绕过本地遥测禁用设置。
关掉非必要流量以后,WebFetch 的域名安全预检仍会运行。它有独立的设置 skipWebFetchPreflight;设为 true 会跳过检查,也会放弃这层域名安全保护。官方插件市场的自动安装也不受上述总开关控制,要单独用 CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL=1 关闭。这些例外在同一份官方文档中列出。
在公司环境里,还要看组织下发的 OpenTelemetry 配置。即使自己的终端没有设置接收地址,托管配置也可能提供它。需要限制出站连接时,可以按官方网络文档核对目的地,在网关或防火墙上设置规则,再检查实际请求是否符合预期。
公开排查结果前,先删去凭据和标识符。不要把完整的 ~/.claude.json、遥测队列或抓包文件贴到网上。
安装包信息与复核方法
检查对象为 macOS arm64 版 Claude Code 2.1.280,安装文件 SHA-256 是 387a5c5dcdbb815085edf0baf79591f9d8894efe922bceaf3d75b1b08055229d。本机观察发生在 2026 年 9 月。
我先在二进制里搜索 IOPlatformUUID、networkInterfaces 和时区字符串,再解析 Bun 单文件程序的模块图,提取 JS。字符串搜索用来找入口;后面的检查沿着事件生成、字段处理和发送函数继续看,避免把字符串出现的位置误当作实际调用。
版本、签名、SHA-256
1,991 个 JS 模块
序列化、POST
可以看到已生成和缓存的字段
也没有服务端接收记录
模块图包含 37,884,508 字节可读的 JS 源文本和 82,505,096 字节字节码。提取出的 1,991 个 JavaScript 模块全部通过语法解析。文件多叫 chunk-xxxxxxxx.js,函数名经过压缩,也没有随包源码映射;事件名、上报地址和字段名仍能读到。Bun 文档说明,启用字节码编译并不会隐藏源代码。
复核时先用下面的命令确认版本文件、哈希、签名和 Bun 段,再按模块图提取 JS。固定偏移只适用于对应的安装包,换版本后不能直接沿用;按偏移硬截一段二进制,也可能混入非源码内容。
CC="$HOME/.local/share/claude/versions/2.1.280"
shasum -a 256 "$CC"
codesign -dv --verbose=2 "$CC"
otool -l "$CC" | rg -A8 'sectname __bun|segname __BUN'
这份包中,chunk-m200zvyg.js 包含核心事件的序列化和 Datadog 事件副本处理,chunk-h8651pre.js 包含内置 telemetry 插件,chunk-s8swgzep.js 包含错误上报的条件检查。模块名会随版本变化。
没有搜到字符串,也可能是实现换了写法或编译到了其他位置。本次没有逐指令审计 Bun 运行时和三个原生扩展,没有对应会话的 TLS 明文抓包,也没有服务端保存记录。