首页
/ RTK 遥测与隐私机制详解:收集范围、同意机制、保留策略与删除流程

RTK 遥测与隐私机制详解:收集范围、同意机制、保留策略与删除流程

2026-09-06 12:18:34作者:龚格成

RTK 是一个单 Rust 二进制、零依赖的 CLI 代理,用于压缩开发命令输出以降低 LLM token 消耗。为了让维护者知道哪些命令最需要优化、哪些过滤器不够用,RTK 内置了一套默认关闭、显式同意的匿名遥测(Telemetry)系统。本文基于官方文档 docs/guide/resources/telemetry.md 和对应实现 src/core/telemetry.rssrc/core/telemetry_cmd.rs,完整讲清 RTK 收集什么、不收集什么、如何开启或关闭、数据保留多久,以及 GDPR 场景下的删除(erasure)流程如何落地到代码。

遥测的设计目标:为什么需要收集数据

RTK 覆盖多个生态系统的 100+ 命令过滤器。没有遥测时,维护者对以下问题完全没有可见性:

  • 哪些命令使用最频繁、需要最好的过滤器;
  • 哪些过滤器效果不佳、需要改进;
  • 新过滤器应该优先开发哪个生态;
  • RTK 在到达模型之前削减了多少 bash 输出(token 节省量);
  • 用户是持续使用还是尝鲜后流失(churn)。

这些数据直接驱动路线图。官方文档给出的例子是:如果遥测显示 40% 的用户在跑 Python 命令,但过滤器只覆盖了 10% 的 Python 场景,那么下一个投入方向就很明确。

数据收集方为 RTK AI Labs(联系邮箱 contact@rtk-ai.app)。

工作原理:每天一次的“发后即忘”Ping

从源码 src/core/telemetry.rsmaybe_ping() 函数可以看到,遥测的触发遵循严格的“非阻塞、不重试”原则:

  1. 每天一次(23 小时间隔):常量 PING_INTERVAL_SECS = 23 * 3600。选择 23 小时而非 24 小时,是为了避免时钟边界导致的“一天不发”或“一天发两次”。
  2. 后台线程,绝不阻塞 CLI:ping 在独立线程中发出,并设置 2 秒超时req.timeout(Duration::from_secs(2)))。
  3. 标记文件防重复:数据目录下的 .telemetry_last_ping 标记文件(telemetry_marker_path())在发送之前就被写入,23 小时内再次触发直接短路返回。
  4. 失败即丢弃:服务端不可达时 ping 被静默丢弃,没有重试、没有本地队列。

maybe_ping() 中有一系列前置检查,任何一条不满足都直接返回,不发任何网络请求:

  • 编译时未注入遥测端点(RTK_TELEMETRY_URL 环境变量在编译期通过 option_env! 读取),遥测功能本身不存在;
  • 环境变量 RTK_TELEMETRY_DISABLED=1 生效;
  • 配置中 consent_given 不是 Some(true)(GDPR:必须显式同意);
  • 配置中 [telemetry] enabled 为 false;
  • 距上次 ping 不足 23 小时。

收集了什么:完整字段清单

下面是文档声明的全部上报字段,按类别组织。所有字段均为匿名聚合统计,不含任何命令参数。

身份(匿名)

字段 示例 用途
device_hash a3f8c9...(64 位十六进制) 统计独立安装数。对本地随机盐做 SHA-256 得到,不可逆;不含主机名或用户名

实现上,设备盐由 getrandom 生成 32 字节随机数(十六进制化后为 64 位),以私有权限写入 ~/.local/share/rtk/.device_saltsalt_file_path());generate_device_hash() 每次都对盐做 SHA-256。若随机数生成失败,源码回退到“时间戳 + PID”的哈希,保证功能可用。单元测试 test_device_hash_is_stabletest_salt_is_persisted 验证了哈希的稳定性与盐的持久化。

环境

字段 示例 用途
version 0.34.1 跟踪新版本采用率
os macos 确定需要支持和测试的平台
arch aarch64 决定 ARM 与 x86 构建优先级
install_method homebrew 了解分发渠道(homebrew/cargo/script/nix)

install_method 不是猜的:detect_install_method() 对可执行文件路径做 canonicalize 后匹配特征路径,如 /Cellar/rtk//homebrew/ 判定为 homebrew,/.cargo/bin/ 判定为 cargo,/.local/bin/ 判定为脚本安装,/nix/store/ 判定为 nix,其余为 other。测试 test_install_method_unix_paths 覆盖了这些分支。

使用量

字段 示例 用途
commands_24h 142 当日活动量
commands_total 32888 终身使用量,区分轻/重度用户
top_commands ["git", "cargo", "ls"] 最热门工具(仅名称,最多 5 个)
tokens_saved_24h 450000 当日交付价值
tokens_saved_total 96500000 终身交付价值
savings_pct 72.5 总体压缩效率

这些统计全部来自本地 SQLite 跟踪库(src/core/tracking.rs),get_stats() 通过 count_commands_sincetop_commands(5)overall_savings_pcttokens_saved_24htotal_tokens_saved 等查询聚合得到。

质量(过滤器改进)

字段 示例 用途
passthrough_top ["git:15", "npm:8"] bash 输出压缩率为 0% 的前 5 命令——说明缺过滤器
parse_failures_24h 3 过滤器脆弱性——计数高说明过滤器在崩溃
low_savings_commands ["rtk <cmd>:25%"] 平均压缩率低于 30% 的命令——待改进的过滤器(示例为占位符,非实测值)
avg_savings_per_command 68.5 不加权平均(全局值会受高频命令体积偏置)

生态分布

字段 示例 用途
ecosystem_mix {"git": 45, "cargo": 20, "js": 15} 类别百分比——过滤器开发的投入方向

留存(参与度)

字段 示例 用途
first_seen_days 45 安装天数
active_days_30d 22 近 30 天中至少执行过 1 条命令的天数——衡量粘性

经济性

字段 示例 用途
tokens_saved_30d 12000000 30 天 token 节省量,用于趋势分析
estimated_savings_usd_30d 由 token 节省量乘固定内部常数推导的美元估值,非实测成本,不反映任何供应商的定价

源码中该估值按输入 token 价格计算(tokens_saved_30d / 1_000_000.0 * 3.0,注释说明取 Claude Sonnet $3/Mtok 作为内部常数)。注意这与 docs/guide/resources/savings-explained.md 中面向用户展示口径相互独立,遥测上报的只是一个内部趋势指标。

采用度(Adoption)

字段 示例 用途
hook_type claude 安装了哪个 AI agent 的 hook(claude/gemini/codex/cursor/none)
custom_toml_filters 3 用户自建 TOML 过滤器文件数——DSL 采用度

detect_hook_type() 通过检查各 agent 的特征文件是否存在来判断:例如 ~/.claude/hooks/rtk-rewrite.sh(claude)、~/.gemini/hooks/rtk-hook.sh(gemini)、~/.codex/AGENTS.md(codex)、~/.cursor/hooks/rtk-rewrite.json(cursor),还检查项目级 .claude/hooks/rtk-rewrite.sh.github/hooks/rtk-rewrite.json(copilot)。count_custom_toml_filters() 则统计项目本地 .rtk/filters/ 与全局 ~/.config/rtk/filters/ 两个目录下用户 TOML 过滤器文件数量,这些自定义过滤器机制详见 docs/usage/FEATURES.mddocs/guide/getting-started/configuration.md

配置成熟度

字段 示例 用途
has_config_toml true 用户是否定制过 RTK 配置(检查 ~/.config/rtk/config.toml 是否存在)
exclude_commands_count 2 排除改写的命令数——数量高可能表示挫败感
projects_count 5 去重后的项目路径数——多项目 = 重度用户

功能采用

字段 示例 用途
meta_usage {"gain": 5, "discover": 2} 哪些 RTK 内置功能(gain/discover/proxy/verify/learn/init)真的被用到

build_meta_usage() 从跟踪库统计这些元命令的历史执行次数,仅上报非零项。

不收集什么

文档对“不收集”清单的明确承诺包括:

  • 源代码或文件内容;
  • 完整命令行或参数(只有 “git”、“cargo” 这样的工具名);
  • 文件路径或目录结构;
  • 密钥、API key、环境变量值;
  • 仓库名或 URL;
  • 个人身份信息(PII);
  • IP 地址——不写入遥测 ping;仅在服务端删除(erasure)审计日志中临时保存以追责,6 个月后匿名化。

从 payload 构造代码(src/core/telemetry.rssend_ping())可以印证:请求体就是上表这些字段的 JSON 组合,没有任何自由文本通道,参数或路径在结构上就无法进入 payload。

同意机制:默认关闭,显式 Opt-in

遥测要求显式同意(GDPR 第 6、7 条)。同意在 rtk init 时征询,或事后通过 rtk telemetry enable 给出。没有同意,就没有任何数据外发。

rtk telemetry status     # 查看当前同意状态
rtk telemetry enable     # 给出同意(交互式提示)
rtk telemetry disable    # 撤回同意
rtk telemetry forget     # 撤回同意 + 删除本地数据 + 请求服务端擦除

实现细节(src/core/telemetry_cmd.rs):

  • enable 强制要求交互式终端(stdin().is_terminal()),管道模式下直接报错,防止脚本环境误开启;
  • 同意写入配置文件的 [telemetry] 段(consent_givenconsent_dateenabled,结构见 src/core/config.rsTelemetryConfig);
  • status 输出 consent 状态(yes/no/never asked)、enabled 状态、环境变量覆盖提示,以及 device hash 的首尾 8 位(完整 hash 不打印,避免终端日志泄露标识符);
  • 配置默认值由测试 test_telemetry_default_disabled 保证:无配置时遥测关闭、未征询过同意。

环境变量硬开关

export RTK_TELEMETRY_DISABLED=1

该变量无视一切同意状态直接阻断遥测。它是单一事实来源:telemetry_disabled_by_env()src/core/telemetry_cmd.rs)被 maybe_ping()init 的同意提示和 status 命令共同调用,避免多处判断漂移。回归测试 test_telemetry_disabled_by_env_honors_opt_out 明确覆盖了非交互式环境下该变量对同意提示的短路作用(对应 issue #1307:防止 rtk init 在 CI 中挂起),并验证只有精确值 "1" 生效,"0""true""" 等都不触发禁用。

数据保留策略

位置 策略
服务端遥测记录 最长保留 12 个月,到期自动清除
服务端删除审计日志 其中的 IP 地址 6 个月后匿名化(GDPR 视 IP 为个人数据)
客户端本地 SQLite 数据库 ~/.local/share/rtk/history.db,默认保留 90 天,可通过 config.tomltracking.history_days 调整;rtk telemetry forget 会整体删除

90 天默认值对应常量 DEFAULT_HISTORY_DAYS = 90src/core/constants.rs),本地自动清理逻辑在跟踪模块 src/core/tracking.rs 中实现。history_daysTrackingConfig 的配置字段,默认 90,可按需写入 config.toml

GDPR 权利与删除流程

欧盟 GDPR 下,用户可行使以下权利,RTK 将每条权利映射到具体操作:

  • 访问(Access)rtk telemetry status 显示 device hash;遥测 payload 字段上文已完整公开;
  • 更正(Rectification):因数据匿名且聚合,不适用;
  • 删除(Erasure,Art. 17):运行 rtk telemetry forget,删除本地数据并向服务端发删除请求;或携带 device hash 发邮件至 contact@rtk-ai.app 人工删除;
  • 限制处理(Restriction)rtk telemetry disable 立即停止一切采集;
  • 可携带(Portability):本地 ~/.local/share/rtk/history.db 即全部本地数据的导出载体;
  • 反对(Objection)rtk telemetry disableexport RTK_TELEMETRY_DISABLED=1

rtk telemetry forget 的完整执行顺序

run_forget()src/core/telemetry_cmd.rs)按以下顺序执行,顺序本身有讲究——先算 hash,再删盐

  1. save_telemetry_consent(false) 撤回同意;
  2. 若盐文件存在,先 generate_device_hash() 计算完整 device hash(删盐之后就无法再算);
  3. 删除盐文件 .device_salt
  4. 删除 ping 标记文件 .telemetry_last_ping
  5. 删除本地跟踪数据库 history.db(GDPR Art. 17 同样适用于本地数据);
  6. 向服务端端点 {TELEMETRY_URL}/erasure POST {"device_hash": ..., "action": "erasure"}(5 秒超时);
  7. 失败兜底:若服务端不可达,CLI 打印完整 device hash 并提示用户将该 hash 一并发送到 contact@rtk-ai.app 请求人工删除。

数据处理承诺

  • 所有通信走 HTTPS(TLS);
  • 数据仅用于 RTK 产品改进;
  • 不向任何第三方出售或共享数据;
  • 可能发布聚合统计(例如“70% 的 RTK 用户在使用 macOS”)。

小结

RTK 的遥测系统把“默认关闭 + 显式同意 + 可硬禁用 + 可彻底删除”四件事做成了代码级约束:maybe_ping() 的每道检查、RTK_TELEMETRY_DISABLED=1 的单一事实来源、forget 的删盐前算 hash 顺序、以及上报 payload 中不存在自由文本通道的结构设计,共同保证了文档承诺与实现行为一致。对于关心隐私的开发者,最实用的三点是:不执行 rtk telemetry enable 就不会有任何数据外发;CI 或企业环境可全局导出 RTK_TELEMETRY_DISABLED=1;随时可用 rtk telemetry forget 一步完成本地与远端的彻底清除。

登录后查看全文
热门项目推荐
相关项目推荐