遥测¶
Claude-mem 包含匿名使用情况分析(通过 PostHog),用于帮助确定修复和功能的优先级。
默认开启(可选择退出)。 事件是匿名的,仅通过随机安装 UUID 标识,并且每个分析属性都经过严格的白名单过滤 — 请参阅下面的收集哪些数据和绝不收集哪些数据。关闭它只需一条命令:
标准的 DO_NOT_TRACK 环境变量也会被遵循,并覆盖所有其他设置。安装程序会在 npx claude-mem install 结束时询问一次,因此对于新安装而言,默认设置绝不会默默生效 — 你的回答(无论内容如何)都会被记住,并且绝不会再次询问;当设置了 DO_NOT_TRACK 或在 CI/非交互式安装中时,该提示会被完全跳过。
埋点工作原理¶
Claude-mem 只有一条埋点路径(src/services/telemetry/instrument.ts 中的 instrument())。每个可观测事件只描述一次,然后分发到两个接收端:
- 本地日志 — 始终以完整保真度记录。 即使遥测关闭,日志记录仍会继续工作,且本地日志绝不会经过清理器。完整、未脱敏的详细信息就在这里 — 在你的机器上。
- 遥测 — 仅在获得同意时发送。 遥测副本会经过清理(结构化属性使用白名单;错误文本使用先允许后脱敏),并且对于高量级事件,会在发送之前汇总为按会话/按时间窗口的聚合数据。
因此,单一事实来源同时生成了丰富的本地日志和最小化、保护隐私的遥测数据 — 二者永远不会产生偏差,清理只发生在遥测分支上。
关于会话回放的说明: PostHog 会话回放不适用于 claude-mem。回放记录的是浏览器 DOM 会话;claude-mem 是一个没有浏览器界面的 Node 后台工作进程,因此没有任何内容可供回放,它也永远不会被启用。
收集哪些数据¶
启用后,事件是匿名的,仅通过随机安装 UUID(crypto.randomUUID(),在首次使用时于本地生成)标识。
低量级生命周期事件(install_*、uninstall_completed、worker_started)会构建一个以该随机 UUID 为键的分析画像,从而可以计算聚合留存率和同期群统计 — 该画像仅包含下面白名单中的字段(平台、版本、IDE/提供商选择)。它不可能与你关联起来:其中没有姓名、邮箱、IP、硬件 ID 或任何其他标识符。所有高量级活动均以 $process_person_profile: false 发送,且完全不构建任何画像。
关于所观测 IDE 会话的身份,claude-mem 仅收集其模型 ID(observed_model)和计费层级(observed_billing)— 绝不收集账户 ID、邮箱或令牌。
高量级事件会被汇总,而不是流式发送。 与为每次压缩或上下文注入各发送一个事件不同,claude-mem 在本地聚合它们并发送一份摘要:
observer_turn_rollup— 一个按会话的累加器。会话中的每次压缩都会并入一个持续运行的汇总,并在会话结束时一次性发出(而不是每轮发出一个session_compressed事件)。它带有一个rollup_reason说明刷新原因(session_end|worker_shutdown|safety_flush),以及一个window_seq部分刷新计数器(普通一次性会话为0;只有当长期会话触发周期性安全扫描时才为0,1,2,…)。context_injected_rollup— 一个针对上下文注入的5 分钟时间窗口累加器。
正是这种汇总模型将高量级事件流削减了约 99.9%。现在不再有任何代码路径会直接发出原始 session_compressed 或 context_injected 事件 — 该活动到达 PostHog 的唯一路径就是汇总。
每个事件属性都会经过严格的白名单清理器 — 表中没有的键会在发送前被静默丢弃:
| 字段 | 示例 | 描述 |
|---|---|---|
| 事件名称 | observer_turn_rollup |
下列事件中发生了哪一个 |
distinct_id |
7f3c…(随机 UUID) |
匿名安装 ID — 不来源于你或你的机器 |
version |
13.4.2 |
claude-mem 版本 |
os |
darwin |
操作系统平台 |
os_version |
10.0.22631 |
操作系统内核发布字符串 — 用于区分例如 Windows 10 和 11 |
is_wsl |
false |
是否在适用于 Linux 的 Windows 子系统下运行 |
arch |
arm64 |
CPU 架构 |
runtime |
bun |
bun 或 node |
runtime_version |
1.2.0 |
运行时版本字符串 |
node_version |
22.14.0 |
Node.js 版本字符串 |
duration_ms |
1843 |
操作耗时 |
outcome |
ok |
粗略结果 — 一个封闭枚举:ok / error / partial / invalid_output / aborted |
error_category |
provider_error |
粗略错误分类 — 绝不是错误消息 |
locale |
en-US |
语言标签 |
is_ci |
false |
是否在 CI 中运行 |
endpoint |
by-file |
哪个 claude-mem 搜索路由 — 始终是我们的路由名称之一,绝不会是查询 |
ide |
claude-code |
安装程序选择的 IDE(安装程序自己的 ID 列表),或者在 observer_turn_rollup 中为所观测会话的平台来源(claude / codex / cursor / …) |
provider |
claude |
LLM 提供商选择:claude / codex / gemini / openrouter / openai-compatible |
runtime_mode |
worker |
worker 或 server 运行时 |
trigger |
heartbeat |
worker_started 是真实启动还是每日心跳 |
count |
7 |
整数计数,例如一次压缩中存储的观测数量 |
has_summary |
true |
压缩是否同时生成了会话摘要 |
is_update |
false |
安装是否覆盖了已有安装 |
interactive |
true |
安装程序是否在交互式终端中运行 |
install_method |
npm |
哪个包管理器启动了 CLI:npm / bun / pnpm / yarn |
bun_version / uv_version |
1.3.9 / 0.7.2 |
安装期间检测到的工具链版本 |
claude_code_version |
2.0.14 |
Claude Code CLI 版本,若可检测到 |
trial_days |
30 |
分配的 CMEM Pro 安装程序优惠时长:30 天(较早的事件可能上报 7 或 14) |
trial_variant |
test_30 |
试用分配标识符:control_7 / test_14 / test_30;当前所有分组均授予 30 天 |
offer_surface / funnel_source |
installer / installer |
安装程序优惠展示事件上的封闭来源标签 |
stage |
awaiting_checkout |
安装程序试用轮询阶段:awaiting_login / awaiting_checkout / awaiting_approval |
phase |
login |
安装程序 OAuth 配对阶段 — 封闭枚举:login / enrollment / deferred |
provider_source |
default |
安装程序如何决定提供商 — 封闭枚举:flag(传入了 --provider)/ default(非交互式全新安装回退到 claude)/ persisted(非交互式运行复用了已配置的提供商)/ prompt(交互式选择) |
mode |
code |
当前 claude-mem 模式 ID(我们的模式列表) |
model |
claude-haiku-4-5 |
用于压缩的模型 ID |
observed_model |
claude-fable-5-1 |
被观测的 IDE 会话本身所运行的模型 ID(从其记录中读取)— 与作为压缩模型的 model 不同。无法确定时为 unknown |
observed_billing |
max |
被观测会话的计费状态 — 封闭枚举:max / pro / team / enterprise / subscription / api_key / bedrock / vertex / foundry / unknown。绝不包含账户 ID、邮箱或令牌 |
hook |
ingest |
触发压缩的原因:init / ingest / summarize |
observation_type, obs_type_* |
bugfix, 3 |
观测类型分桶(bugfix / discovery / decision / refactor / other)— 仅计数 |
compression_ms |
2140 |
压缩模型调用的延迟 |
tokens_input / tokens_output |
5800 / 420 |
单次压缩中模型 API 上报的实际 Token 用量 |
compression_ratio |
13.8 |
tokens_input ÷ tokens_output |
cost_usd |
0.0021 |
单次压缩调用由提供商上报的成本(美元,经 Claude SDK / openrouter.ai)— 绝非估算值;若提供商未上报则缺失 |
endpoint_class |
openrouter |
OpenRouter 提供商的目标是 openrouter.ai 还是自定义网关 |
rollup_reason |
session_end |
发出按会话的 observer_turn_rollup 的原因 — 封闭枚举:session_end / worker_shutdown / safety_flush |
window_seq |
0 |
某次汇总的部分刷写序号 — 正常的单次会话为 0,仅当长生命周期会话触发安全清扫时递增 |
observation_count, session_count |
50, 12 |
有多少条观测/多少个会话为一次上下文注入提供输入 |
timeline_depth_days |
90 |
被注入的最早观测的年龄(天) |
has_session_summary |
true |
注入中是否包含会话摘要 |
tokens_injected |
17914 |
注入上下文的估算 Token 数 |
tokens_saved_vs_naive |
144379 |
与重新发现该工作相比节省的估算 Token 数 |
search_strategy |
timeline |
构建注入所用的检索策略(我们的枚举) |
db_observation_count, db_session_count, db_summary_count, db_project_count |
92501, 5243, 9698, 379 |
本地记忆数据库中的总行数 — 仅计数,绝不包含名称或文本 |
db_size_mb |
364.4 |
记忆数据库文件大小(MB) |
install_age_days |
104 |
自安装首次记录会话以来的天数 |
obs_count_7d / obs_count_30d |
1887 / 10357 |
最近 7 / 30 天内存储的观测数 |
days_since_last_obs |
0 |
自最近一条观测被存储以来的天数 |
result_count |
12 |
一次记忆搜索返回的结果数 — 仅计数,绝不包含结果或查询 |
chroma_available |
true |
搜索时向量搜索后端是否可达 — 仅表示可达性;零结果回退会在此处上报 true,因此请通过 fallback_reason 统计回退 |
fallback_reason |
none |
搜索为何从向量搜索回退:none / chroma_connection / chroma_error / chroma_not_initialized / chroma_zero_results — 封闭枚举,绝不包含错误消息 |
invalid_output_class |
idle |
不可用压缩输出的粗略分类:xml / idle / prose(xml = 看起来符合预期格式但解析失败)— 绝不包含输出本身 |
consecutive_invalid_outputs |
0 |
遗留的不可用输出计数器,保留为已清洗的数值字段 |
respawn_triggered |
false |
旧版无效输出重启的遗留恢复标志 |
abort_reason |
idle |
压缩会话被中止的原因:idle / shutdown / overflow / restart_guard / quota / rate_limit / auth / provider_switch / deadline_exceeded(模型请求的存活时间超过了 CLAUDE_MEM_LLM_TIMEOUT_MS)/ output_retry(排队的批次既未返回观测 XML 也未返回跳过标签,因此被再次请求一次)/ drift(观测器持续使用观测 schema 之外的标签回复,因此重新开始了一次生成)/ none — 封闭枚举 |
outcomes_aborted_deadline_exceeded |
1 |
在 observer_turn_rollup 中:会话的 outcomes_aborted 中有多少次是模型请求因达到单个请求时限而被放弃 — 仅计数 |
previous_shutdown |
clean |
上一次 Worker 运行如何结束(在启动时检测):crash / clean / unknown |
previous_uptime_seconds |
86400 |
上一次 Worker 运行持续的时间(整数秒) |
uptime_seconds |
3600 |
Worker 停止时已运行的时间(整数秒) |
shutdown_reason |
restart |
Worker 停止的原因:stop / restart / signal / idle |
process_rss_mb |
187 |
Worker 进程常驻内存(整数 MB) |
heap_used_mb |
92 |
Worker 正在使用的 JS 堆(整数 MB) |
hook_type |
observation |
哪种 Hook 类型失败:context / session-init / observation / summarize / session-end / file-context — 我们的处理器名称 |
limit_window |
five_hour |
触发 usage_limit_hit 时哪个订阅时间窗口已耗尽:five_hour / seven_day / seven_day_opus / seven_day_sonnet / overage / unknown — 封闭枚举 |
overage_status |
rejected |
额外用量积分能否覆盖该请求:allowed / allowed_warning / rejected / unknown — 一个封闭枚举 |
is_using_overage |
false |
该请求是否已经在按额外用量计费 |
resets_in_minutes |
112 |
距耗尽窗口重置的整分钟数,向下取整为 0 — 绝不是提供商的提示文本 |
error_mode |
worker_unavailable |
粗粒度的 hook 失败模式:worker_unavailable / blocking_error — 绝不是错误消息 |
consecutive_failures |
3 |
连续发生了多少次 hook 失败(fail-loud 计数器) |
threshold_tripped |
true |
连续失败计数是否达到 fail-loud 阈值 |
pre_latch_state |
false |
是否由早于 fail-loud 闩锁(13.24.18 之前)的 claude-mem 版本最后写入该计数器。当 true 时,consecutive_failures 可能包含来自该旧版本的失败 |
skill_id |
mem-search |
调用了哪个内置技能 — 由 plugin/skills/ 目录名构成的封闭枚举,或 other。绝不发送第三方技能名称。 |
skill_source |
first_party |
first_party(随产品提供的 plugin/skills/ 技能)或 third_party(折叠为 skill_id: other) |
skill_trigger |
tool |
技能是如何被调用的:tool(宿主 Skill 工具)或 prompt(在会话初始化时输入 /skill)。绝不包含 prompt 正文。 |
有一个值是在服务端推导出来的,而非由客户端发送:PostHog 在接收数据时将请求发送方的 IP 解析为粗略位置(国家 / 地区 / 城市),随后 IP 本身即被丢弃。客户端绝不会在任何事件上附加 IP,原始 IP 也绝不被存储 — 参见绝不收集的内容。
事件¶
| 事件 | 时机 | 额外属性 |
|---|---|---|
install_completed |
npx claude-mem install 完成时 |
ide、provider、provider_source、runtime_mode、is_update、outcome、duration_ms、interactive、install_method、bun_version、uv_version、claude_code_version |
installer_oauth_started |
安装程序打开浏览器登录链接时 | version — 绝不包含链接、配对 ID、密钥或设备码 |
installer_oauth_completed |
浏览器登录完成时 | version |
installer_oauth_timeout |
登录轮询到达配对的过期时间(服务器的 expires_in,上限 30 分钟;当服务器未报告时为 4 分钟) |
version、phase(login / enrollment)、duration_ms |
installer_oauth_start_failed |
POST /api/installer/oauth/start 未返回可用的配对时 |
version、outcome(http_error / network / timeout / bad_body)、interactive、phase(login / deferred) |
installer_oauth_deferred |
非交互式安装跳过登录,并在结束时打印可选的登录链接时 | version、interactive(始终为 false) |
install_failed |
安装程序中止时 | error_category(我们的错误分类 ID)、interactive、install_method、claude_code_version |
pro_offer_viewed |
安装程序中显示 CMEM Pro 优惠时 | trial_days、trial_variant、offer_surface(installer)、funnel_source(installer) |
trial_email_submitted |
用户提交邮箱以启动安装程序试用流程时 | 仅 version — 绝不包含邮箱 |
trial_link_sent |
试用启动 API 接受请求并发送登录链接时 | version、duration_ms — 绝不包含邮箱、链接、配对密钥或设备码 |
trial_activated |
浏览器批准后接收并保存试用凭证时 | version、duration_ms |
trial_poll_timeout |
浏览器完成轮询被取消、过期、超时或无法访问时 | version、stage、outcome、duration_ms |
uninstall_completed |
npx claude-mem uninstall 完成时 |
— |
worker_started |
后台 worker 启动时,外加每 24 小时运行时长发送一次心跳 | trigger(start / heartbeat)、duration_ms、ide、provider、mode、runtime_mode、进程内存(process_rss_mb、heap_used_mb)、安装快照:db_observation_count、db_session_count、db_summary_count、db_project_count、db_size_mb、install_age_days、obs_count_7d、obs_count_30d、days_since_last_obs;在真正启动时还包含崩溃检测:previous_shutdown(crash / clean / unknown),以及正常关闭后的 previous_uptime_seconds |
observer_turn_rollup |
每个会话一次,在会话结束时发出 — 对每个会话进行汇总,聚合该会话中的所有压缩(已存储观察、无效输出丢弃、失败、中止),而不是每个回合发送一条事件 | rollup_reason(session_end / worker_shutdown / safety_flush)、window_seq、聚合的 outcomes_* 计数(包括 outcomes_aborted_deadline_exceeded)、total_tokens_input、total_tokens_output、total_cost_usd、avg_duration_ms、avg_compression_ms、top_model、top_abort_reason(会话中中止回合里最常见的 abort_reason;仅在存在中止回合时出现)、observed_model、observed_billing、observations_created(会话中生成的观察总数 — 与 total_cost_usd 搭配可得出每条观察的成本)、求和的 obs_type_* 桶、window_start_ts,以及它所汇总的每回合字段(provider、ide) |
context_injected_rollup |
上下文注入的 5 分钟时间窗汇总(将存储的记忆注入新会话) | 聚合的 outcomes_ok / outcomes_error 计数、count、total_tokens、avg_tokens、total_observations_injected(从缓存提供到 prompt 中的观察总数)、total_tokens_saved_vs_naive、window_start_ts |
work_state_usage_rollup |
所捕获工作状态活动和指令返回的 5 分钟汇总;也会在 worker 关闭时刷新 | platform、agent_role、instruction_state、下文所述的计数器、window_start_ts |
search_performed |
记忆搜索运行时(绝不包含查询文本) | endpoint、outcome、duration_ms、result_count、search_strategy、chroma_available、fallback_reason |
skill_invoked |
捆绑技能被调用时——宿主 Skill 工具加载其指令,或用户在会话初始化时输入第一方 /skill。并非工作完成;没有 duration_ms / 结果。仅限 Worker 路径。未知的 /foo 不产生任何事件。 |
skill_id(封闭枚举 + other)、skill_source(first_party / third_party)、skill_trigger(tool / prompt)、ide |
worker_stopped |
后台 worker 正常关闭时 | uptime_seconds、shutdown_reason(stop / restart / signal / idle) |
supervisor_registry_degraded |
worker 无法写入其进程注册表(supervisor.json,例如数据目录不可写),改为在内存中保存时。每次降级阶段发送一次,而非每次写入失败发送一次 |
error_category(文件系统错误码,例如 EACCES / EROFS / ENOSPC,或 unknown) |
worker_start_failed |
此启动器启动的 worker 在就绪前退出时。由启动它的启动器发送,绝不会由仅等待其他启动器所启动 worker 的启动器发送 | outcome(dead)、error_category(当崩溃可复现时为 boot_crash,当 worker 端口无法绑定时为 port_unbindable,当守护进程完全无法启动时为 launch_failed,例如没有 Bun 运行时或 Start-Process 被拒绝,否则为 unreachable_after_boot);绝不包含崩溃文本,崩溃文本保留在本地日志中 |
usage_limit_hit |
观察器背后的 Claude 订阅将某个窗口报告为 rejected 时——由于观察器与所观察会话共用同一账户,这意味着用户自己的 Claude Code 会话用量耗尽。每个已耗尽的窗口发送一次(按窗口重置时间去重;在仍处于限额状态时重启 worker 会重新发送一次)。仅在观察器以订阅登录方式运行于 Claude 时触发——API-key、Gemini 和 OpenRouter 观察器永远不会看到此事件 |
limit_window(five_hour / seven_day / seven_day_opus / seven_day_sonnet / overage / unknown)、overage_status(allowed / allowed_warning / rejected / unknown)、is_using_overage、resets_in_minutes、ide、provider、observed_model、observed_billing |
hook_failed |
claude-mem 钩子严重失败时——worker 超过 fail-loud 阈值后不可达,或发生阻塞性错误 | hook_type、error_mode、consecutive_failures、threshold_tripped、pre_latch_state |
error_occurred |
worker 返回 HTTP 5xx 时 | error_category |
$exception |
为错误跟踪捕获真实错误时——受同意机制门控,并可独立通过 kill-switch 禁用 | 脱敏后的 error_type / error_message / error_stack、occurrence_count,以及白名单上下文。关于确切保留与脱敏内容,参见错误跟踪 |
工作状态用量与诊断限制¶
工作状态汇总仅包含计数。它们绝不包含任务标题、字段、提示词、项目名称、路径、原始会话或 agent ID,也不包含推断出的模型。platform 是固定的受支持宿主名称、other 或 unknown;agent_role 是 main、subagent 或 unknown(使用与捕获相同的 subagent 谓词)。
| 计数器 | 度量内容 |
|---|---|
instruction_returned_count |
钩子返回完整的工作状态指令块(包括缓存块)。这是向宿主的交接,并非宿主已接受或模型已遵循的证明。 |
instruction_disabled_count、instruction_excluded_count、instruction_missing_count、instruction_unknown_count |
已知的配置排除、成功返回但未包含指令块,或上下文读取失败/未知。 |
captured_prompt_count、captured_session_count |
新记录的、非私有的提示词,其原始钩子时间戳位于 30 天回放窗口内,以及它们首次捕获的会话/agent 范围。无时间戳的转录提示词会被省略。 |
captured_tool_count、unidentified_tool_event_count |
具有稳定 ID 的不同捕获工具调用;无稳定 ID 的调用仅计入第二个诊断计数器。两者都要求具备原始事件时间戳以及此前已知的公开回合边界。记忆/项目/隐私/agent 排除规则仍然适用。 |
native_todo_count |
捕获的 TodoWrite、SetTodoList 或 update_plan 调用,包括那些被排除在记忆生成之外的调用。当 instruction_state=returned 时,这是一个有用的竞争性 todo 诊断,并非不合规的判定。 |
captured_read_count、captured_write_count |
工具后捕获所看到的不同工作状态工具回执,归属于被捕获的宿主和 agent 角色。 |
mcp_read_count、mcp_write_count |
在本插件的 MCP 服务器中的执行,包括在 worker 能够应答之前发生的失败。agent 和宿主归属为 unknown。回执保留在本地暂存区,直到 worker 可以收集它们。 |
captured_ 和 mcp_ 的读/写计数器也都有以 _ok_count、_error_count、_excluded_count、_disabled_count 或 _unknown_count 结尾的结果计数器。只有明确保存的回执才能确认写入成功。两个来源可能观察到同一次调用:切勿将它们作为不同用量相加。
instruction_state 描述该确切本地会话/agent 作用域中事件之前的最近一次已知钩子交接。早于最近交接的延迟活动具有 instruction_state=unknown;后续指令绝不会追溯应用。没有原始时间戳的捕获提示词和工具会被省略。在观察到交接之前,其为 unknown。直接 MCP 调用、仅服务器运行时捕获、缺失钩子以及 worker 不可用都可能使覆盖范围未知。Live Pi、OpenCode 和 OMP 的提示词回调带有其原始时序;Pi 即使在回放时也使用持久化的用户消息时间戳。通用 DSH 客户端调用和 OpenClaw 合成初始化路径缺乏经过验证的提示词时序,因此仍不计入捕获的提示词/工具计数。OMP 有其自身的受限平台标签;缺失稳定工具 ID 只会产生未识别到达的诊断信息。较旧的适配器已经提供了默认宿主,无法与明确报告宿主的宿主区分开。缺失计数器或事件并不证明零用量或零遵从;一个普通问题可能正确地不需要任何写入。不会计算合规百分比或任务分类。
本地哈希回执密钥可在 30 天内抑制跨 worker 重启的重复提示、工具重放和重复的 spool 投递。在活动期间进行清理,每小时至多一次,移除较早的回执;较早的事件会被丢弃而不是重新计数。即使分析功能关闭,也会维护一个本地的、不含内容的公开/私有轮次位,因此在私有工作期间重新选择加入时,无法重用之前的公开提示。只有严格更新且带有时间戳的公开提交才能重新打开公开覆盖,包括当重复文本重用某条提示行时;私有轮次在时间戳并列时胜出。这些密钥和该位都不会发送给 PostHog。该 worker 使用现有的 30 秒同意缓存。遥测仍然尽力而为:退出选择会禁用分析,而在 rollup 刷新之前发生崩溃可能会丢失计数。此功能不会回填过去的版本。
错误跟踪¶
Claude-mem 会以 $exception 事件的形式将真实错误捕获到 PostHog Error Tracking。这是对旧有的仅白名单立场的刻意改变: 错误消息和堆栈跟踪是自由格式文本,因此属性白名单(只允许已知封闭集合的键)会把它们全部丢弃。相反,错误文本走一条独立的 先允许后脱敏 路径(src/services/telemetry/error-scrub.ts):我们保留诊断文本,并积极剥离任何可能泄露 PII 或秘密的内容。
以下内容会保留(并已脱敏):
- 错误类型(构造函数名称,如
TypeError),上限 100 字符。 - 错误消息,已脱敏且上限 500 字符。
- 堆栈跟踪——仅保留顶部 10 帧,每帧均已脱敏,总大小上限约 2KB。
- 一个
occurrence_count(当前窗口内该错误指纹触发了多少次)。
以下内容会从该文本中被脱敏掉(依次替换为 [REDACTED]):
- 主目录(
/Users/you→~)——首先处理,这样嵌入在主目录路径中的用户名绝不会残留。 - 绝对文件系统路径 → 折叠为基名(POSIX、Windows 驱动器路径和 UNC 路径)——保留下“哪个文件”,但不保留目录树。
- URL / 连接字符串凭据和查询字符串——任何
scheme://…(http、ws、postgres、redis、mongodb+srv、amqp 等)中的 userinfo(user:pass@)以及?…/#…都会被剥离,因此数据库连接字符串凭据和签名 URL 令牌都会失效。 - 电子邮件。
- API 令牌和密钥:带提供方前缀的密钥(
sk-、phc_、ghp_、xoxb-等)、Bearer 令牌、AWS 访问密钥 ID(AKIA…)、JWT、UUID、长 hex 块(24+ 字符)以及通用高熵令牌。 - IPv4 地址(会在网络错误中泄露的内部 IP/主机名)。
脱敏管道是纯函数且永不抛错的——恶意输入(null、循环引用、带有会抛出异常的 getter 的对象、200KB 的 blob)始终会产生安全且受限的结果,因为遥测绝不能破坏或阻塞 worker。在任何正则运行之前,原始输入会被硬性限制为 8KB(ReDoS 防御)。
速率限制。 每个错误指纹每 60 秒至多发送一条 $exception 事件。错误通过“类型 + 规范化消息模板 + 顶部堆栈帧”进行指纹识别,因此带有不同 ID/数字的“相同”错误风暴会被去重为一次发送,并附带发生次数。这同样适用于我们手动捕获和任何 SDK 自动捕获。(自动捕获在发送前会额外重新脱敏——posthog-node 从磁盘读取的原始源码上下文行会被删除,文件名会脱敏为基名。)
受同意机制约束,并带有独立的紧急停止开关。 错误捕获受常规遥测同意链约束(退出遥测也会禁用错误捕获)并受独立的 CLAUDE_MEM_TELEMETRY_ERRORS 开关约束——参见 如何退出。不会为 $exception 事件构建个人画像($process_person_profile: false)。
Warning
单向门(不可逆)。 与白名单分析事件不同——其每个字段都是数字、布尔值或封闭集合中的值——$exception 事件携带真实(但已脱敏的)消息文本。一旦错误消息被摄入 PostHog,事后无法被选择性删除。这是为了获得可操作的崩溃诊断而做出的刻意权衡,并通过激进脱敏、速率限制、同意机制约束以及 CLAUDE_MEM_TELEMETRY_ERRORS=0 紧急停止开关来缓解。如果你宁愿不发送任何自由格式内容,请设置该变量。
历史回填¶
遥测比 claude-mem 本身上线得更晚,因此早于遥测的安装所拥有的活动,是实时事件从未见过的。升级后的第一次 worker 启动时,claude-mem 会执行一次一次性的遥测前历史回填——仅包含匿名计数,并与其它所有数据一样经过相同的白名单清理器:
| 事件 | 时间(时间戳) | 携带内容 |
|---|---|---|
historical_activity |
安装处于活动状态的每天各一条,标记在该历史日期上 | 仅包含每日活动计数:观测、会话、摘要、提示、不同项目数量、观测类型分桶(obs_type_*)、会话结果(session_completed_count / session_failed_count)、按平台会话计数(sessions_claude_count 等)、subagent_obs_count、discovery_tokens,以及 backfilled: true。与所有高容量事件一样,不构建画像($process_person_profile: false) |
install_inferred |
一次,标记在安装首次记录的活动日上 | first_active_date(日期字符串,如 2025-10-19)和 backfilled: true |
与一切其它数据一样,这些仅包含计数和封闭集合值——绝不包含标题、提示、文件内容或项目名称。同样的匿名安装 UUID 标识它们,每个属性都会通过白名单清理器。
有几点值得了解:
- 它只运行一次。 成功发送后会写入一个完成标记(claude-mem 数据目录中的
backfill.json),从而防止回填再次运行。在运行成功之前不会写入标记,因此失败的尝试只会在下一次 worker 启动时重试。 - 它与实时遥测遵循完全相同的同意门控 —
DO_NOT_TRACK、CLAUDE_MEM_TELEMETRY=0以及telemetry.json中的enabled: false都会阻止它,并且调试模式会在不发送的情况下打印应有的载荷。 - 在升级后的第一次 worker 启动之前退出选择可完全阻止它。 在你选择退出期间不会发送任何内容,也不会写入标记——不过如果你之后重新选择加入,回填届时将运行。
- 位置是上传时的时间,而非历史时间。 PostHog 在摄入时推导出的粗略位置(见上文)反映的是事件上传地点,而不是这些历史日期所描述的你当时所在的位置。
哪些数据绝不会被收集¶
| 绝不收集 | 备注 |
|---|---|
| 提示词或对话内容 | 即使截断或哈希处理后的版本也不会收集 |
| 文件路径或目录名称 | 已从分析数据中完全剔除,也从错误文本中剔除(主目录 → ~,绝对路径 → 基名)——参见错误追踪 |
| 源代码 | 任何形式的源代码——包括 posthog-node 原本会附加到自动捕获异常上的源代码上下文行(发送前已删除) |
| 项目或仓库名称 | 包括 git 远程仓库和分支名称 |
| 搜索查询 | 仅记录发生了搜索这一事实 |
| IP 地址 | 客户端从不将 IP 附加到事件上;发送方 IP 仅在摄取时临时用于推断粗略位置(国家 / 地区 / 城市),随后即被丢弃——分析项目已配置为绝不存储发送方 IP |
| 硬件或机器标识符 | 即使是哈希处理后的 MAC 地址或主机名也不会收集 |
| 环境变量值 | 绝不 |
| 电子邮件、用户名或任何个人身份信息(PII) | 绝不——电子邮件、令牌、密钥和凭据也会从错误文本中剔除 |
| 技能参数、技能 markdown 或提示词正文 | skill_invoked 仅发送封闭集合中的 skill_id / skill_source / skill_trigger。tool_input.args 以及斜杠提示词的其余部分永远不会离开本机 |
| 第三方技能名称 | 压缩为 skill_id: other + skill_source: third_party。未知的 /foo 斜杠标记不会发出任何事件 |
一个诚实坦白的例外:错误消息。 自错误追踪加入以来,经过脱敏处理的错误消息和堆栈跟踪确实会被收集(作为 $exception 事件)——这是对之前仅收集粗略分类数据的立场的刻意改变,并且它以同意为前提,配有独立的终止开关。原始路径、提示词、项目名称、源代码和模型输出仍然绝不被收集——它们在错误文本离开你的机器之前就已从中剥离。
分析属性在代码层面强制执行:它们经过白名单(只有收集了哪些数据表格中的字段得以保留),而非黑名单。每个白名单字段要么是数字、布尔值,要么是我们定义的封闭集合中的某个值——不存在任何能承载自由格式用户内容的分析字段。错误文本是唯一的自由格式路径,它改而经过单独的「先允许、后脱敏」清洗器处理。
如何选择退出(四种方式)¶
以下任意一种都能让遥测保持关闭——它们按此顺序检查,首个匹配项生效:
DO_NOT_TRACK——通用退出机制。设置DO_NOT_TRACK=1即可强制关闭遥测,覆盖所有其他设置。CLAUDE_MEM_TELEMETRY=0(也接受false/off)——环境变量覆盖。(CLAUDE_MEM_TELEMETRY=1则相反,强制开启。)- 遥测配置文件——在
telemetry.json中设置enabled: false(见下文)。 - CLI 命令:
错误追踪的独立退出¶
错误追踪(携带已脱敏消息/堆栈的 $exception 事件)可以单独禁用,而无需关闭匿名分析:
这是唯一承载自由格式(脱敏)文本的遥测路径,一旦被摄取便是一道单向门,因此它为那些能接受匿名计数器、但不能接受错误文本的运营者提供了独立的终止开关。只要遥测同意处于开启状态,它默认就是开启的;上述四种退出方式中的任何一种也会隐式禁用它(没有同意 ⇒ 没有错误)。
随时查看当前状态——以及四层中是哪一层作出的决定:
调试模式¶
想确切地看到将发送什么?设置:
开启调试模式(且遥测已启用)时,每个本应发送的事件负载都会打印到 stderr,并且不会通过网络发送任何内容。
配置文件位置¶
同意设置与匿名安装 ID 存储在 claude-mem 数据目录内的 telemetry.json 中:
- 默认:
~/.claude-mem/telemetry.json - 如果你已覆盖数据目录,则为
$CLAUDE_MEM_DATA_DIR/telemetry.json
enabled 字段仅在你做出明确选择(安装程序中的提示、telemetry enable 或 telemetry disable)后才会存在。如果文件只有 installId,则表示未记录任何决定,此时适用默认值(开启)。删除该文件即可完全重置——下次使用时将生成全新的安装 ID。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/claude-mem