by BENZEMA216
README.md
# WeChat Archive for DeepSeek Harness
English | [简体中文](README.zh-CN.md)
A local-first, fail-closed WeChat archive plugin for macOS. It connects four
bounded operations to DeepSeek Harness—diagnose, inspect status, synchronize,
and verify—and includes an Agent Skill plus an optional macOS LaunchAgent for
unattended runs.
Version `0.1.0` can scan every `Msg_*` table in every discovered
`message_N.db` shard from a quiescent, checkpointed Mac WeChat database
snapshot. It stores replayable, verifiable JSONL deltas and preserves locally
available image containers, MP4 files, and voice BLOBs as private,
content-addressed objects.
> **Release status:** the implementation and synthetic safety tests are
> complete, but a real chat synchronization was **not run (`NOT_RUN`)** while
> producing this release. Sync remains disabled by default, and no LaunchAgent
> is installed automatically.
```text
Mac WeChat source
|
v
deterministic Python core ----> private state + JSONL deltas + media objects
| |
+---- stdio MCP ---- DeepSeek Harness +---- replay/hash verification
|
+---- one-shot scheduler ---- optional macOS LaunchAgent
```
## What it provides
| Surface | Operation | Writes archive data? |
| --- | --- | --- |
| MCP | `wechat_doctor` | No—checks the app, source, WAL, secret, and permissions |
| MCP | `wechat_status` | No—reports bounded operational metadata |
| MCP | `wechat_sync` | Yes—requires both server opt-in and `confirm=true` |
| MCP | `wechat_verify` | No—replays message history and verifies hashes and coverage |
| Agent Skill | `wechat-archive` | Guides the model through the required safety workflow |
| Scheduler | `sync` followed by `verify` | Only after a human installs the LaunchAgent |
MCP results expose status, counts, coverage, and integrity information. They do
not expose contact names, account identifiers, message bodies, secrets, or
private database paths.
## Integrity and privacy boundaries
- Tool arguments cannot select an account, filesystem path, SQL statement,
executable, or secret.
- The plugin never captures a key, attaches LLDB, re-signs or replaces WeChat,
terminates the app, or ignores a WAL.
- Sync fails without publishing a new snapshot when WeChat is running, a WAL
contains transactional frames or has a malformed short header, the app lacks
the pinned official signature, the secret is invalid, or the source changes
during acquisition.
- Every encrypted database is independently key-derived and HMAC-verified.
Decrypted staging files are private, checked with SQLite `quick_check`, and
removed after the run.
- Immutable JSONL deltas are fsynced before their index transaction commits.
Verification replays the complete history and hashes every registered media
object, including historical objects.
- Secrets belong in macOS Keychain. They never belong in tool parameters,
command arguments, environment variables, logs, configuration committed to
Git, or release files.
### What `SOURCE_FAITHFUL_V1` means
Images always retain their raw `.dat` bytes. A decoded image variant is written
only when a strong file signature or one unambiguous single-byte XOR transform
validates it. Videos must carry an MP4 `ftyp` signature. Voice BLOBs are
preserved without claiming transcription or playback compatibility.
Emoji extraction, general attachments, media not downloaded to this Mac, and
some private containers remain unresolved. Consequently the public result is
deliberately `media_complete=false`. `SOURCE_FAITHFUL_V1` means that locally
available source bytes were preserved and verified; it does **not** mean a
fully decoded or playable multimodal export.
Likewise, “complete” can describe only one verified, quiescent Mac database
snapshot. It never includes deleted history, cloud-only or phone-only history,
or content that WeChat never stored locally.
## Requirements
- macOS
- Python 3.10 or newer
- Node.js 24 or newer
- pnpm 11
- `uv`
- `libzstd` for decoding zstd-compressed message payloads; without it, the
original compressed bytes remain preserved as base64
- An official WeChat installation and access to your own local account data
Use this project only with data you are authorized to archive. A chat archive
contains other people's private information even when it belongs to your own
account; keep the archive local, access-controlled, and out of Git.
## Install the core and MCP server
From a checked-out copy of this repository:
```sh
cd /path/to/wechat-archive
PROJECT_DIR="$(pwd -P)"
CONFIG_PATH="${HOME}/Library/Application Support/WeChatArchive/config.json"
uv venv
uv pip install -e '.[test]'
pnpm --dir mcp-server install --frozen-lockfile
mkdir -p "$(dirname "$CONFIG_PATH")"
chmod 700 "$(dirname "$CONFIG_PATH")"
cp config.example.json "$CONFIG_PATH"
chmod 600 "$CONFIG_PATH"
```
Edit the private configuration using [config.example.json](config.example.json)
as its schema. Both `source.root` and `archive.root` must be absolute, canonical,
separate paths. The archive root must not be inside the source tree. Production
configuration should use the Keychain provider. The `file` provider exists only
for migration from an existing, user-owned mode-`0600` regular file; symlinks
are rejected.
Key acquisition and application repair are deliberately outside this plugin.
Follow the supervised boundary in [docs/BOOTSTRAP.md](docs/BOOTSTRAP.md) rather
than placing a key in shell history or asking an agent to modify WeChat.
Run the read-only preflight first:
```sh
.venv/bin/wechat-archive --config "$CONFIG_PATH" doctor
```
The command writes exactly one `wechat-archive.command/v1` JSON object to
stdout. Only `READY` permits a separately confirmed sync. See
[Architecture and integrity](docs/ARCHITECTURE.md) for the state model.
## Install into DeepSeek Harness
The installer is a dry-run unless `--install` is present:
```sh
python3 scripts/install_dsh.py
python3 scripts/install_dsh.py --install
```
It manages only one marked block in the Harness profile and one
`~/.dsh/skills/wechat-archive` symlink to this checkout. It does not modify the
DeepSeek Harness source checkout or overwrite an unrelated Skill. Before a live
profile edit it creates one mode-`0600` backup.
Harness exposes these names:
- `mcp__wechat__wechat_doctor`
- `mcp__wechat__wechat_status`
- `mcp__wechat__wechat_sync`
- `mcp__wechat__wechat_verify`
The bundled [safe overlay](dsh/cordis.patch.yml) sets
`WECHAT_ARCHIVE_ALLOW_SYNC=0`. Installation therefore enables read-only
diagnosis and status inspection, not synchronization. After all real-machine
gates pass, an operator must explicitly set the server opt-in to `1`, restart
the MCP process, and still call `wechat_sync` with `confirm=true`.
Removal is also a dry-run by default:
```sh
python3 scripts/uninstall_dsh.py
python3 scripts/uninstall_dsh.py --uninstall
```
## Optional periodic synchronization
Scheduled acquisition calls the deterministic core directly; it does not rely
on a browser tab, a language model, or a running Harness conversation. The
following commands only render and inspect a daily `03:15` LaunchAgent. They do
not install it:
```sh
REVIEW_DIR="${TMPDIR:-/tmp}/wechat-archive-review"
REVIEW_PLIST="${REVIEW_DIR}/local.wechat-archive.sync.plist"
mkdir -p "$REVIEW_DIR"
python3 scripts/render_launchagent.py \
--project-root "$PROJECT_DIR" \
--python "$PROJECT_DIR/.venv/bin/python" \
--config "$CONFIG_PATH" \
--hour 3 --minute 15 \
--sync-timeout-seconds 1800 \
--verify-timeout-seconds 7200 \
--output "$REVIEW_PLIST"
plutil -lint "$REVIEW_PLIST"
python3 scripts/install_launchagent.py --plist "$REVIEW_PLIST"
```
The final command is still a dry-run. Only the following explicit action
installs and bootstraps the job:
```sh
python3 scripts/install_launchagent.py --plist "$REVIEW_PLIST" --install
```
Do not install it until `doctor` reports `READY` and a manually confirmed
`sync` followed by `verify` succeeds. Each scheduled run performs sync first
and full verification second. If WeChat is active or a WAL is not empty, the
run exits safely and may try again at the next scheduled time.
Sync and full verification have separate bounded timeouts: 30 minutes and two
hours by default, configurable up to eight hours. Full verification reads all
historical media objects, so choose its timeout based on archive size.
## Verification and release checks
All repository tests use synthetic fixtures. Do not substitute real chat data.
```sh
.venv/bin/python -m pytest -q
pnpm --dir mcp-server test
python3 scripts/check_manifest.py --scan-content
python3 scripts/build_release.py \
--output "${TMPDIR:-/tmp}/wechat-archive-0.1.0.tar.gz"
```
A successful process exit is not sufficient evidence of a real archive. The
acceptance condition is `SYNCED` or `NO_CHANGE`, immediately followed by
`VERIFIED`, with the expected source coverage. See the complete
[acceptance gates](docs/ACCEPTANCE.md).
## License and third-party work
Project code is released under the [MIT License](LICENSE). Audited or referenced
upstream projects and their licenses are listed in
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). Real chats, databases, keys,
media, logs, local configuration, and historical handoff archives are never
part of the release.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues