docs: 重写 README,对齐 Rust 单二进制实现

pull/2/head
jackwener 2026-04-16 15:23:43 +08:00
parent 02f6c4a748
commit 79a653b9c6
1 changed files with 58 additions and 57 deletions

115
README.md
View File

@ -1,6 +1,8 @@
# wx-cli # wx-cli
微信 4.x (macOS) 本地数据 CLI 工具。从运行中的微信进程内存提取加密密钥,后台常驻 daemon 持久缓存解密数据库CLI 毫秒级响应。 微信 4.x (macOS/Linux/Windows) 本地数据 CLI 工具。从运行中的微信进程内存提取加密密钥,后台常驻 daemon 持久缓存解密数据库CLI 毫秒级响应。
单一 Rust 二进制,无运行时依赖。
## 架构 ## 架构
@ -12,99 +14,103 @@ wx (CLI) ──Unix socket──▶ wx-daemon (后台进程)
(mtime 感知) (500ms polling) (mtime 感知) (500ms polling)
``` ```
- **wx-daemon**:后台常驻,持有解密后的 DB 热缓存,首次解密后跨重启复用mtime 不变则不重解密) - **wx-daemon**:后台常驻,持有解密后的 DB 热缓存,mtime 不变则跨重启复用,无需重解密
- **wx (CLI)**:发 JSON 请求到 Unix socket获得响应后格式化输出;首次调用自动启动 daemon - **wx (CLI)**:发 JSON 请求到 Unix socket格式化输出首次调用自动启动 daemon
## 快速开始 ## 快速开始
### 环境要求 ### 环境要求
- macOS (Apple Silicon / Intel) - macOSApple Silicon / Intel或 Linux
- WeChat 4.x (macOS 版,需 ad-hoc 签名,见下文) - WeChat 4.xmacOS 版)
- Python 3.12+ - 首次使用需 `sudo`(内存扫描)
- [uv](https://docs.astral.sh/uv/)Python 包管理)
- Xcode Command Line Tools`xcode-select --install`
### 安装 ### 下载
从 [Releases](https://github.com/jackwener/wx-cli/releases) 下载对应平台的预编译二进制:
| 平台 | 文件名 |
|------|--------|
| macOS Apple Silicon | `wx-macos-arm64` |
| macOS Intel | `wx-macos-x86_64` |
| Linux x86_64 | `wx-linux-x86_64` |
| Windows x86_64 | `wx-windows-x86_64.exe` |
```bash
# macOS arm64 示例
curl -L https://github.com/jackwener/wx-cli/releases/latest/download/wx-macos-arm64 -o wx
chmod +x wx
sudo mv wx /usr/local/bin/
```
### 从源码构建
```bash ```bash
git clone git@github.com:jackwener/wx-cli.git git clone git@github.com:jackwener/wx-cli.git
cd wx-cli cd wx-cli
uv sync cargo build --release
# 二进制位于 target/release/wx
``` ```
### 初始化(首次使用) ### 初始化(首次使用)
微信需要 ad-hoc 签名才能被扫描内存: macOS 上微信需要 ad-hoc 签名才能被扫描内存:
```bash ```bash
sudo codesign --force --deep --sign - /Applications/WeChat.app sudo codesign --force --deep --sign - /Applications/WeChat.app
``` ```
然后打开微信并登录,运行初始化: 打开微信并登录,然后运行初始化:
```bash ```bash
uv run python wx.py init sudo wx init
``` ```
`wx init` 自动完成: `wx init` 自动完成:
1. 检测微信数据目录(`~/Library/Containers/.../xwechat_files/<wxid>/db_storage` 1. 检测微信数据目录(`~/Library/Containers/.../xwechat_files/<wxid>/db_storage`
2. 编译 C 内存扫描器(如未编译) 2. 扫描微信进程内存,提取所有数据库密钥 → `~/.wechat-cli/all_keys.json`
3. `sudo` 扫描微信进程内存,提取所有数据库密钥 → `all_keys.json` 3. 写入 `~/.wechat-cli/config.json`
4. 更新 `config.json`
### 使用 ### 使用
```bash ```bash
# 最近会话 # 最近会话
uv run python wx.py sessions wx sessions
# 聊天记录 # 聊天记录
uv run python wx.py history "张三" wx history "张三"
uv run python wx.py history "AI群" --since 2026-04-01 --until 2026-04-15 wx history "AI群" --since 2026-04-01 --until 2026-04-15
# 搜索消息 # 搜索消息
uv run python wx.py search "Claude" wx search "Claude"
uv run python wx.py search "会议" --in "工作群" --since 2026-01-01 wx search "会议" --in "工作群" --since 2026-01-01
# 联系人 # 联系人
uv run python wx.py contacts wx contacts
uv run python wx.py contacts -q "李" wx contacts -q "李"
# 导出聊天记录 # 导出聊天记录
uv run python wx.py export "张三" --format markdown -o chat.md wx export "张三" --format markdown -o chat.md
uv run python wx.py export "AI群" --since 2026-01-01 --format json -o chat.json wx export "AI群" --since 2026-01-01 --format json -o chat.json
# 实时监听新消息Ctrl+C 退出) # 实时监听新消息Ctrl+C 退出)
uv run python wx.py watch wx watch
uv run python wx.py watch --chat "AI交流群" wx watch --chat "AI交流群"
uv run python wx.py watch --json | jq .content wx watch --json | jq .content
# daemon 管理 # daemon 管理
uv run python wx.py daemon status wx daemon status
uv run python wx.py daemon stop wx daemon stop
uv run python wx.py daemon logs wx daemon logs
uv run python wx.py daemon logs --follow wx daemon logs --follow
``` ```
> **注**daemon 在首次 CLI 调用时自动启动,无需手动运行。 > daemon 在首次 CLI 调用时自动启动,无需手动运行。
### 可选:设置别名
```bash
echo 'alias wx="uv run --directory /path/to/wx-cli python wx.py"' >> ~/.zshrc
source ~/.zshrc
# 之后可以直接用
wx sessions
wx history "张三"
wx watch
```
## 命令参考 ## 命令参考
### `wx init [--force]` ### `wx init [--force]`
首次初始化:检测数据目录、编译扫描器、提取密钥、写入配置。`--force` 强制重新扫描(微信更新后使用)。 首次初始化:检测数据目录、扫描内存、提取密钥、写入配置。`--force` 强制重新扫描(微信更新后使用)。
### `wx sessions [-n N] [--json]` ### `wx sessions [-n N] [--json]`
列出最近 N 个会话(默认 20显示未读数、最后消息摘要。 列出最近 N 个会话(默认 20显示未读数、最后消息摘要。
@ -125,7 +131,7 @@ wx watch
实时监听新消息WAL 变化推送,约 500ms 延迟)。`--json` 输出 JSON lines方便 `jq` 处理。 实时监听新消息WAL 变化推送,约 500ms 延迟)。`--json` 输出 JSON lines方便 `jq` 处理。
### `wx daemon status / stop / logs [-f] [-n N]` ### `wx daemon status / stop / logs [-f] [-n N]`
管理后台 daemon。`logs --follow` 等同 `tail -f` 管理后台 daemon。`logs --follow` 持续追踪新日志
## 原理 ## 原理
@ -136,20 +142,22 @@ wx watch
- **KDF**PBKDF2-HMAC-SHA512256,000 次迭代 - **KDF**PBKDF2-HMAC-SHA512256,000 次迭代
- **页结构**4096 bytes/pagereserve = 80IV 16 + HMAC 64 - **页结构**4096 bytes/pagereserve = 80IV 16 + HMAC 64
WCDB 在进程内存中缓存派生后的 raw key格式为 `x'<64hex_enc_key><32hex_salt>'`C 扫描器(`find_all_keys_macos.c`)通过 macOS Mach VM API 扫描微信进程内存,匹配此模式,再用 HMAC 校验 page 1 确认密钥正确性,输出到 `all_keys.json`。 WCDB 在进程内存中缓存派生后的 raw key格式为 `x'<64hex_enc_key><32hex_salt>'`Rust 扫描器通过 macOS Mach VM API`mach_vm_region` + `mach_vm_read`)或 Linux `/proc/<pid>/mem` 扫描微信进程内存,匹配此模式后输出到 `~/.wechat-cli/all_keys.json`。
### DBCachemtime 感知缓存) ### DBCachemtime 感知缓存)
daemon 首次解密后将结果(及 DB/WAL 的 mtime持久化到 `~/.wechat-cli/cache/_mtimes.json`。重启时若 mtime 未变,直接复用已解密文件,无需重新解密 daemon 首次解密后将结果(及 DB/WAL 的 mtime,精度纳秒)持久化到 `~/.wechat-cli/cache/_mtimes.json`。重启时若 mtime 未变,直接复用已解密文件。
### WAL 监听 ### WAL 监听
微信使用 SQLite WAL 模式WAL 文件固定预分配 4MB不能靠文件大小判断变化daemon 每 500ms 检测 `session.db-wal` 的 mtime有变化时重新解密并广播新消息给所有 `watch` 客户端。 daemon 每 500ms 检测 `session.db-wal` 的 mtime有变化时重新解密并通过 Unix socket 广播新消息给所有 `watch` 客户端。
### 数据文件路径 ### 数据文件路径
``` ```
~/.wechat-cli/ ~/.wechat-cli/
├── config.json # 配置DB 目录、密钥文件路径)
├── all_keys.json # 数据库密钥
├── daemon.sock # Unix socket ├── daemon.sock # Unix socket
├── daemon.pid # PID 文件 ├── daemon.pid # PID 文件
├── daemon.log # daemon 日志 ├── daemon.log # daemon 日志
@ -167,13 +175,6 @@ daemon 首次解密后将结果(及 DB/WAL 的 mtime持久化到 `~/.wechat
| `session/session.db` | 会话列表(最新消息摘要、未读数) | | `session/session.db` | 会话列表(最新消息摘要、未读数) |
| `message/message_*.db` | 聊天记录(按 `Msg_<md5(username)>` 分表) | | `message/message_*.db` | 聊天记录(按 `Msg_<md5(username)>` 分表) |
| `contact/contact.db` | 联系人username、nick_name、remark | | `contact/contact.db` | 联系人username、nick_name、remark |
| `media_*/media_*.db` | 媒体文件索引 |
## 测试
```bash
uv run python -m pytest tests/ -v
```
## 免责声明 ## 免责声明