wx-cli 源码拆解

一条命令背后,是“内存取钥匙 → 按页解密 → mtime/WAL 缓存 → SQLite 查询 → 结构化输出”的完整本地数据管线。

这是什么项目?

wx-cli 是一个 Rust 编写的本地微信数据 CLI,面向微信 4.x 桌面端的本地数据目录。它不把数据上传到服务器,而是通过平台进程内存扫描取得 SQLCipher raw key,再将数据库按需解密到本地缓存,最后通过命令行输出聊天记录、联系人、群成员、朋友圈、公众号文章、收藏、统计和附件等数据。

项目的关键不是“写了一组 SQLite 查询”,而是把一个持续变化、分片、加密、需要高权限初始化的桌面应用数据源包装成一个稳定的 Agent 接口:CLI 是薄客户端,daemon 持有缓存和查询状态,IPC 协议负责把请求与响应解耦。

章节地图

章节主题要回答的问题
01 总览定位与核心数字为什么需要一个常驻 daemon?
02 架构模块骨架与数据流代码如何分层,边界在哪里?
03 启动与配置maininit、路径探测同一个二进制如何切换两种角色?
04 密钥扫描macOS/Linux/Windows scanner如何从候选 key 绑定到具体 DB?
05 SQLCipher 与 WAL按页解密与增量日志为什么不直接全量预解密?
06 daemon 与 IPC生命周期、socket、请求派发如何把昂贵初始化变成透明后台服务?
07 查询层shard、Names、freshness如何跨分片恢复微信数据语义?
08 消息语义类型、压缩、XML、群昵称原始表行如何变成可读消息?
09 附件解密.dat、图片 key、opaque ID如何从查询结果安全地取回二进制?
10 工程化与安全安装、CI、测试、边界项目如何在跨平台和高权限条件下保持可用?

先看一条完整链路

wx init
  ├─ auto_detect_db_dir() 找到 db_storage
  ├─ scanner::scan_keys() 扫 WeChat 内存中的 x'<key><salt>'
  ├─ 将 salt 与所有 .db 的前 16 字节匹配
  └─ 写 ~/.wx-cli/config.json + all_keys.json
 
wx history Alice
  ├─ CLI ensure_daemon()
  ├─ 自身以 WX_DAEMON_MODE=1 脱离终端启动
  ├─ daemon DbCache 按 mtime 解密/复用 message_N.db
  ├─ Unix socket / Windows named pipe 传一行 JSON
  ├─ query::q_history() 找 Msg_<md5(username)> 表并解析
  └─ 输出 YAML/JSON,附 meta.status 判断新鲜度

源码基线

本拆解以工作区中的 wx-cli 0.3.0 源码为准,重点文件包括:src/main.rssrc/config.rssrc/scanner/src/crypto/src/daemon/src/attachment/src/cli/。后续章节中的源码路径均以这些模块为锚点;源项目后续更新可能改变行号和数据库格式。

下一步

01 总览:一个本地微信数据 Agent 适配层 开始,或直接通过章节地图按运行链路阅读。