WeChatBridge
WeChatBridge connects a WeChat bot to agentic coding CLIs (Google's agy / Antigravity, or xAI's Grok Build). From WeChat you can send text, images, files, and voice-as-text to the active CLI, get replies back, and receive certain generated files over the WeChat CDN. Switch backends per user with /backend — no restart.
WeChat (phone) ⇄ iLink bot API ⇄ WeChatBridge ⇄ agy / grok CLI
(this project) (runs tools)
The bridge process stays up and long-polls iLink. For prompts that go to a CLI, it spawns one agy or grok child (-p single-turn) and exits that child when done — the child does not stay resident. Many slash commands (/help, /backend, /persona, …) are handled inside the bridge and never start a CLI. Only artifacts the bridge can detect under the user's allowed session paths are pushed back via CDN.
Features
- Text, image, file, and voice (WeChat server-side transcription only) go to the active backend (
agyorgrok) - Detected CLI artifacts under the per-user allowed tree can be sent back (size-capped); not every file the CLI touches
- Each WeChat user gets an isolated workspace; model / effort / mode are remembered per backend
- Runtime backend switch:
/backend agyor/backend grok(clears the “continue session” flag so the next CLI turn starts without-c/--continue; does not immediately wipe history files on disk) - Slash commands for model, session reset, persona, and more (see below)
- Dangerous-prompt gate: a keyword list of concrete destructive patterns asks for confirmation before run
- Sender whitelist (
WECHATBRIDGE_ALLOWED_SENDERS; empty = allow all) /mcpreturns short usage text;/agentrewrites into a natural-language subagent prompt for the CLI (not a native MCP bridge)- Media over WeChat CDN with AES-128-ECB encrypt/decrypt
- Multi-instance: one codebase, set
WECHATBRIDGE_INSTANCEper process (state / session / QR paths derive from it) - Deploy templates: systemd (Linux), launchd (macOS), Task Scheduler notes (Windows)
Platform Support
- Linux — primary (systemd unit included)
- macOS — supported (launchd plist included)
- Windows — supported (Task Scheduler guide included)
Default data paths expand from ~ (e.g. ~/.local/share/wechatbridge/<instance>/).
CLI Backends
- agy (default) — Google Antigravity CLI
- grok — xAI Grok Build CLI
Per-user switch: /backend agy or /backend grok. Each backend keeps its own model / effort / mode memory and persona file layout. Global default is WECHATBRIDGE_BACKEND.
Prerequisites
- At least one CLI installed and signed in:
- agy on
PATH, or setAGY_BIN_PATH - and/or grok on
PATH, or setGROK_BIN_PATH - Antigravity is Google's terminal agentic coding CLI (successor to Gemini CLI). Grok Build is xAI's counterpart.
- agy on
- A WeChat account with a ClawBot / iLink bot (QR bind on first run)
- Python 3.10+
Install
The recommended way is with pipx (Python >= 3.10 required):
pipx install wechatbridge-cli
After installation, verify:
wechatbridge --version
Install pipx
Debian / Ubuntu:
sudo apt install pipx
Other systems (or to get the latest version):
python3 -m pip install --user pipx && python3 -m pipx ensurepath
Then start a new shell or re-source your shell config so pipx is on PATH.
Developers
If you want to hack on the source:
git clone https://github.com/dorokuma/wechatbridge.git
cd wechatbridge
pip install -e .
Configure
Configuration is loaded from the first location found:
$WECHATBRIDGE_ENV_FILE— explicit path$XDG_CONFIG_HOME/wechatbridge/<instance>.env(defaults to~/.config/wechatbridge/<instance>.env)$XDG_CONFIG_HOME/wechatbridge/.env(defaults to~/.config/wechatbridge/.env).envin the repository root — deprecated (prints a warning on startup)
The instance name defaults to default; override with WECHATBRIDGE_INSTANCE.
Get the example config:
mkdir -p ~/.config/wechatbridge
curl -o ~/.config/wechatbridge/.env https://raw.githubusercontent.com/dorokuma/wechatbridge/main/deploy/wechatbridge.env.example
Then edit ~/.config/wechatbridge/.env with your settings.
Key variables (all have defaults):
| Variable | Default | Purpose |
|---|---|---|
AGY_BIN_PATH |
agy |
path to the agy binary |
GROK_BIN_PATH |
grok |
path to the grok binary |
WECHATBRIDGE_BACKEND |
agy |
global default backend (agy / grok; overridable per user via /backend) |
WECHATBRIDGE_INSTANCE |
default |
instance name; state / session / QR paths derive from it |
WECHATBRIDGE_ALLOWED_SENDERS |
empty | comma-separated WeChat IDs (empty = allow all) |
AGY_TIMEOUT |
600 |
CLI run timeout in seconds (both backends) |
WECHATBRIDGE_MAX_OUTBOUND_BYTES |
104857600 |
max file size sent back to WeChat (100 MB) |
WECHATBRIDGE_MAX_INBOUND_BYTES |
20971520 |
max inbound image/file after download (20 MB) |
WECHATBRIDGE_MAX_CONCURRENT |
4 |
global concurrent handlers; extras get a busy reply |
WECHATBRIDGE_CONFIRM_TOKEN |
y |
reply this token to approve a gated dangerous prompt |
WECHATBRIDGE_ENABLE_MCP |
true |
enable the /mcp help text command |
WECHATBRIDGE_ENABLE_SUBAGENT |
true |
enable the /agent prompt-rewrite command |
WECHATBRIDGE_ADMINS |
empty | comma-separated wxid list; admins receive WeChat notification when a new version is detected |
WECHATBRIDGE_UPDATE_CHECK |
true |
check PyPI for new versions on startup and every 24h; failures are silent |
WECHATBRIDGE_UPDATE_CHECK_INTERVAL |
86400 |
update check interval in seconds |
Full list: deploy/wechatbridge.env.example.
Why the new config location? With pipx the package is installed globally, so a
.envnext to the source no longer makes sense. The XDG base directory layout keeps your config separate and instance-aware.
Run
wechatbridge
On first run the bridge prints a QR code (and saves PNG under the instance data dir). Scan with WeChat to bind, then it long-polls for messages.
Upgrading
pipx upgrade wechatbridge-cli
sudo systemctl restart wechatbridge
Or run the upgrade script (no clone needed — fetch it with curl):
curl -fsSL https://raw.githubusercontent.com/dorokuma/wechatbridge/main/deploy/update.sh | sudo bash
The script upgrades the pipx installation and restarts the service. If the service runs as a dedicated system user (e.g. wechatbridge), running as root automatically runs pipx as that user (override with WECHATBRIDGE_USER=<user>).
Data lives under ~/.local/share/wechatbridge/<instance>/ (sessions, SQLite history, QR codes, login state) and is not touched during upgrade — your bots stay logged in and conversations are preserved.
Before upgrading a major or minor version (e.g. 1.2 → 1.3), check the corresponding section in CHANGELOG.md for breaking changes and migration steps.
Deploy
Linux (systemd)
First, install the bridge under the wechatbridge system user:
sudo -u wechatbridge pipx install wechatbridge-cli
Then deploy the service unit:
sudo cp deploy/wechatbridge.service /etc/systemd/system/
sudo systemctl enable --now wechatbridge
Multi-instance: copy the template deploy/wechatbridge@.service and enable instances:
sudo cp deploy/wechatbridge@.service /etc/systemd/system/
sudo systemctl enable --now wechatbridge@bot2
sudo systemctl enable --now wechatbridge@bot3
Each instance reads its own config file (~/.config/wechatbridge/bot2.env) and keeps state under its own data directory (~/.local/share/wechatbridge/bot2/).
macOS (launchd)
cp deploy/wechatbridge.plist ~/Library/LaunchAgents/com.wechatbridge.plist
# edit WorkingDirectory and ProgramArguments in the plist
launchctl load ~/Library/LaunchAgents/com.wechatbridge.plist
Windows (Task Scheduler)
See deploy/wechatbridge-windows.md.
Slash commands
| Command | Action |
|---|---|
/help |
list supported commands for the active backend |
/backend <agy|grok> |
switch CLI backend for this WeChat user (on real change: drop continue flag; history files may remain until retention cleanup) |
/clear or /new |
drop continue flag so the next CLI turn is a new conversation (does not instantly delete history files) |
/model <name> |
set model (validated against the backend's model list; see /models) |
/models |
list models from the active CLI |
/fast |
set low reasoning effort (on only — not a toggle; no “off” command) |
/planning |
set planning mode (on only — not a toggle) |
/add-dir <path> |
agy: pass --add-dir on later runs if path is allowed. grok: recorded only; not passed to the CLI yet |
/agents |
list agents via the active CLI |
/persona <text> |
set persona (show / clear / reset subcommands) |
/version |
show current version, instance name, and backend; if a newer version is available, show upgrade hint |
/mcp |
short MCP usage hint text (can disable with WECHATBRIDGE_ENABLE_MCP) |
/agent <name> <task> |
craft a "invoke subagent …" prompt and run the CLI (can disable with WECHATBRIDGE_ENABLE_SUBAGENT) |
Other /… commands are either rejected (e.g. /exit), reported as unsupported on WeChat (TUI-only panels), or passed through to the active CLI.
/add-dir only accepts paths under the user's session directory or roots listed in WECHATBRIDGE_ADD_DIR_ROOTS.
Ops & security (what the bridge actually enforces)
- Whitelist first. Empty
WECHATBRIDGE_ALLOWED_SENDERSmeans anyone who can message the bot can use it. - Auto-approve CLIs. agy runs with
--dangerously-skip-permissions; grok with--always-approve(unless planning mode). Treat this as trusted-user tooling, not a multi-tenant sandbox. - Danger gate is keyword-based, not full intent understanding. Defaults target concrete patterns (
rm -rf /, pipe-to-shell,mkfs,format c:, a few heavy Chinese phrases, …). Everyday wording like bare “delete” is not gated. Override list viaWECHATBRIDGE_CONFIRM_KEYWORDS; approve withWECHATBRIDGE_CONFIRM_TOKEN(defaulty), TTLWECHATBRIDGE_PENDING_TTL. - Inbound media is size-capped (default 20 MB), streamed, and CDN hosts are allowlisted. Missing
aes_keyreturns a clear error. - Outbound artifacts only leave the allowed per-user tree (agy: session scratch; grok: under session dir), after
realpathchecks, and only if underWECHATBRIDGE_MAX_OUTBOUND_BYTES. - Concurrency: global cap (
WECHATBRIDGE_MAX_CONCURRENT, default 4); same user is serialized, different users can run in parallel. - Long replies are split into chunks (
WECHATBRIDGE_MESSAGE_CHUNK, default 2000 characters). - Data layout: instance data under
~/.local/share/wechatbridge/<instance>/(override with env). Runtime dirs prefer0700; token/QR files prefer0600(Unix; Windows relies on NTFS ACLs). - Retention: session temps vs dialogue history use separate TTLs (
WECHATBRIDGE_SESSION_RETENTION_DAYS,WECHATBRIDGE_HISTORY_RETENTION_DAYS). Prefs/auth are kept. - Child env is sanitized (strips common secret-style variable names) and points
HOME(andUSERPROFILEon Windows) at the per-user session dir.
Limitations
- Not a standalone agent — requires agy and/or grok.
- Voice is WeChat speech-to-text only; no local ASR; empty transcript → “type instead”.
- No video send/receive; no native WeChat voice-bubble replies (no silk encode).
- One WeChat binding per process; multiple accounts need multiple instances (
WECHATBRIDGE_INSTANCE). - Artifact send-back is best-effort detection under allowed paths, not “every file the CLI created anywhere”.
/mcp//agentdo not implement MCP protocol or spawn process supervisors inside the bridge — they only guide or rephrase for the CLI.- Deploy only for trusted users behind a whitelist when possible.
Contributing
See CONTRIBUTING.md. Semantic Versioning from 1.0.0; record changes in CHANGELOG.md.
License
MIT. See LICENSE.
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 wechatbridge_cli-1.3.3.tar.gz.
File metadata
- Download URL: wechatbridge_cli-1.3.3.tar.gz
- Upload date:
- Size: 65.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abf7c02dcd256c2704695842389a723dfdd0fe4d4d6b9746b62f78373031a9f4
|
|
| MD5 |
ad573fca7a51068113adc1067efff1e6
|
|
| BLAKE2b-256 |
b5cc838f4d60eda4b38338b28236575aa027e1766aaccc99a0b1317c8ef419ac
|
Provenance
The following attestation bundles were made for wechatbridge_cli-1.3.3.tar.gz:
Publisher:
release.yml on dorokuma/wechatbridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wechatbridge_cli-1.3.3.tar.gz -
Subject digest:
abf7c02dcd256c2704695842389a723dfdd0fe4d4d6b9746b62f78373031a9f4 - Sigstore transparency entry: 2256110464
- Sigstore integration time:
-
Permalink:
dorokuma/wechatbridge@12bfc60cd2492b0dab39ac30dd169ae685ad33d1 -
Branch / Tag:
refs/tags/v1.3.3 - Owner: https://github.com/dorokuma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12bfc60cd2492b0dab39ac30dd169ae685ad33d1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wechatbridge_cli-1.3.3-py3-none-any.whl.
File metadata
- Download URL: wechatbridge_cli-1.3.3-py3-none-any.whl
- Upload date:
- Size: 62.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5fe049daa0ac0be5f25e138275447ec83f172419ece150ef5de4fe5cfff692e
|
|
| MD5 |
dc2f384b00572e750d8c42594c7f2211
|
|
| BLAKE2b-256 |
7a601c44426c47adc4bb80a5b21643dfb2aa045dbf0a5dcb785e3e3ebde82bcd
|
Provenance
The following attestation bundles were made for wechatbridge_cli-1.3.3-py3-none-any.whl:
Publisher:
release.yml on dorokuma/wechatbridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wechatbridge_cli-1.3.3-py3-none-any.whl -
Subject digest:
c5fe049daa0ac0be5f25e138275447ec83f172419ece150ef5de4fe5cfff692e - Sigstore transparency entry: 2256110470
- Sigstore integration time:
-
Permalink:
dorokuma/wechatbridge@12bfc60cd2492b0dab39ac30dd169ae685ad33d1 -
Branch / Tag:
refs/tags/v1.3.3 - Owner: https://github.com/dorokuma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@12bfc60cd2492b0dab39ac30dd169ae685ad33d1 -
Trigger Event:
push
-
Statement type: