Post to WeChat Moments via ADB automation
Project description
wechat-moments
Post to WeChat Moments via ADB automation. Controls an Android phone running WeChat using a deterministic FSM — no LLM required for UI interaction.
Requirements
- Python 3.12+
- Android phone with USB debugging enabled, WeChat installed
Note: ADBKeyboard is required for Chinese text input and will be installed automatically on first use.
Installation
pipx (recommended)
pipx install wechat-moments
uv tool
uv tool install wechat-moments
Homebrew (macOS)
brew tap vangie/formula
brew install wechat-moments
Usage
OpenClaw Integration
To integrate with OpenClaw or other MCP clients:
Local Setup (stdio mode)
If the MCP client and Android phone are on the same machine, use stdio transport (recommended):
Add to your MCP client config (e.g., ~/.mcporter/mcporter.json):
{
"mcpServers": {
"wechat-moments": {
"command": "wx-pyq-mcp"
}
}
}
Remote Setup (SSE mode)
If the Android phone is connected to a different machine:
- On the machine with the phone, start the MCP server:
wx-pyq-mcp --transport sse --host 0.0.0.0 --port 8765
- On the remote machine, configure the MCP client:
{
"mcpServers": {
"wechat-moments": {
"baseUrl": "http://<phone-machine-ip>:8765/sse",
"transport": "sse"
}
}
}
CLI
# Check device connection
wx-pyq status
# Post with text only
wx-pyq post "今天天气真好"
# Post with images (local paths or URLs, max 9)
wx-pyq post "周末出游" -i photo1.jpg -i photo2.jpg
# Post without preview confirmation prompt
wx-pyq post "自动发布" -i photo.jpg --no-preview
# Collect FSM test fixtures (run once with phone connected)
wx-pyq collect-fixtures -o tests/fsm/fixtures/
# Clean up expired staging / archive dirs
wx-pyq cleanup
MCP Server
The MCP server exposes tools for AI agents to post to WeChat Moments.
# Start MCP server (stdio transport, for local use)
wx-pyq-mcp
# Start MCP server with SSE transport (for remote access)
wx-pyq-mcp --transport sse --host 0.0.0.0 --port 8765
Available Tools
| Tool | Description |
|---|---|
prepare_post(text, images) |
Stage assets, generate preview image, return post_id |
submit_post(post_id) |
Execute ADB flow and publish to Moments |
get_device_status() |
Check ADB connection and app installation |
take_screenshot() |
Capture current phone screen for debugging |
Typical Workflow
prepare_post("text", ["image.jpg"])
→ returns { post_id, preview_path, ... }
→ show preview_path to user for confirmation (optional)
submit_post(post_id)
→ returns { status: "success", archive_path: "..." }
Architecture
CLI / MCP Server
│
preview.py ← prepare_post: stage images, generate layout preview
│
submit.py ← execute_submit: lock + FSM + archive + history
│
┌───┴──────────────────────────────────┐
│ UI FSM (poster.py) │ ← concurrent with ↓
│ LAUNCH → DETECT_TAB → NAV_DISCOVER │
│ → OPEN_MOMENTS → [DISCARD_DIALOG] │
│ → SELECT_IMAGES → INPUT_TEXT → DONE │
└──────────────────────────────────────┘
│ Image FSM (images.py, background thread)
│ IDLE → PUSHING → SCANNING → READY → CLEANUP
│
adb.py ← ADB commands (screenshot, tap, dump UI, push files)
cv.py ← tab detection, checkmark counting
ime.py ← ADBKeyboard Chinese text input
Device Profiles
UI coordinates are stored in profiles/<device_serial>.json. Huawei defaults are in profiles/huawei_default.json. Run wx-pyq calibrate to create a profile for a new device.
Data Directory
~/.local/share/wechat-moments/
├── history.jsonl # append-only event log
├── submit.lock # global mutex
├── staging/<post_id>/ # active/pending posts
└── archive/<post_id>/ # completed posts (preview + meta kept 30 days)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wechat_moments-0.1.2.tar.gz.
File metadata
- Download URL: wechat_moments-0.1.2.tar.gz
- Upload date:
- Size: 31.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
942a264cc1bc28779b45aba53e9945eccb422fc7a86465802ab69c958f5a9154
|
|
| MD5 |
178e712563c6a366c5dc04ce8169cd28
|
|
| BLAKE2b-256 |
a43935375526e6055d3040a556b3c81f571b32228b64cad886ee0fb26cbed96d
|
File details
Details for the file wechat_moments-0.1.2-py3-none-any.whl.
File metadata
- Download URL: wechat_moments-0.1.2-py3-none-any.whl
- Upload date:
- Size: 53.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a9c65ca9e95ba0e3e0324fab3b0490297adc808bbd71cd08d08346939f2eccf
|
|
| MD5 |
cac20ab30ad34d71b1ebfbebbe94bb04
|
|
| BLAKE2b-256 |
a72e07952be43b6c5493128f6e1ae6596a9db44710daf01cbb16d51c87a14383
|