wechatbridge-cli 1.3.0__tar.gz → 1.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. wechatbridge_cli-1.3.1/PKG-INFO +287 -0
  2. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/pyproject.toml +1 -0
  3. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/__init__.py +1 -1
  4. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/ilink.py +11 -1
  5. wechatbridge_cli-1.3.1/wechatbridge_cli.egg-info/PKG-INFO +287 -0
  6. wechatbridge_cli-1.3.0/PKG-INFO +0 -29
  7. wechatbridge_cli-1.3.0/wechatbridge_cli.egg-info/PKG-INFO +0 -29
  8. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/LICENSE +0 -0
  9. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/README.md +0 -0
  10. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/setup.cfg +0 -0
  11. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/__main__.py +0 -0
  12. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/agy.py +0 -0
  13. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/config.py +0 -0
  14. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/grok.py +0 -0
  15. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/main.py +0 -0
  16. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/runner_common.py +0 -0
  17. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge/update_check.py +0 -0
  18. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge_cli.egg-info/SOURCES.txt +0 -0
  19. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge_cli.egg-info/dependency_links.txt +0 -0
  20. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge_cli.egg-info/entry_points.txt +0 -0
  21. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge_cli.egg-info/requires.txt +0 -0
  22. {wechatbridge_cli-1.3.0 → wechatbridge_cli-1.3.1}/wechatbridge_cli.egg-info/top_level.txt +0 -0
@@ -0,0 +1,287 @@
1
+ Metadata-Version: 2.4
2
+ Name: wechatbridge-cli
3
+ Version: 1.3.1
4
+ Summary: Bridge WeChat messages to agy or Grok Build CLIs — text/image/file/voice in, CLI replies and generated files back.
5
+ Author: WeChatBridge contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dorokuma/wechatbridge
8
+ Project-URL: Repository, https://github.com/dorokuma/wechatbridge
9
+ Project-URL: Issues, https://github.com/dorokuma/wechatbridge/issues
10
+ Project-URL: Changelog, https://github.com/dorokuma/wechatbridge/blob/main/CHANGELOG.md
11
+ Keywords: wechat,bot,bridge,agy,grok
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Natural Language :: Chinese (Simplified)
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Communications :: Chat
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: httpx
27
+ Requires-Dist: qrcode
28
+ Requires-Dist: Pillow
29
+ Requires-Dist: cryptography
30
+ Dynamic: license-file
31
+
32
+ # WeChatBridge
33
+
34
+ [English](README.md) | [简体中文](README.zh-CN.md)
35
+
36
+ ![license](https://img.shields.io/badge/license-MIT-blue.svg)
37
+ ![python](https://img.shields.io/badge/python-3.10+-blue.svg)
38
+
39
+ 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.
40
+
41
+ ```
42
+ WeChat (phone) ⇄ iLink bot API ⇄ WeChatBridge ⇄ agy / grok CLI
43
+ (this project) (runs tools)
44
+ ```
45
+
46
+ 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.
47
+
48
+ ## Features
49
+
50
+ - Text, image, file, and voice (WeChat server-side transcription only) go to the **active** backend (`agy` or `grok`)
51
+ - Detected CLI artifacts under the per-user allowed tree can be sent back (size-capped); not every file the CLI touches
52
+ - Each WeChat user gets an isolated workspace; model / effort / mode are remembered **per backend**
53
+ - Runtime backend switch: `/backend agy` or `/backend grok` (clears the “continue session” flag so the next CLI turn starts without `-c` / `--continue`; does not immediately wipe history files on disk)
54
+ - Slash commands for model, session reset, persona, and more (see below)
55
+ - Dangerous-prompt gate: a **keyword list** of concrete destructive patterns asks for confirmation before run
56
+ - Sender whitelist (`WECHATBRIDGE_ALLOWED_SENDERS`; empty = allow all)
57
+ - `/mcp` returns short usage text; `/agent` rewrites into a natural-language subagent prompt for the CLI (not a native MCP bridge)
58
+ - Media over WeChat CDN with AES-128-ECB encrypt/decrypt
59
+ - Multi-instance: one codebase, set `WECHATBRIDGE_INSTANCE` per process (state / session / QR paths derive from it)
60
+ - Deploy templates: systemd (Linux), launchd (macOS), Task Scheduler notes (Windows)
61
+
62
+ ## Platform Support
63
+
64
+ - **Linux** — primary (systemd unit included)
65
+ - **macOS** — supported (launchd plist included)
66
+ - **Windows** — supported (Task Scheduler guide included)
67
+
68
+ Default data paths expand from `~` (e.g. `~/.local/share/wechatbridge/<instance>/`).
69
+
70
+ ## CLI Backends
71
+
72
+ - **agy** (default) — Google Antigravity CLI
73
+ - **grok** — xAI Grok Build CLI
74
+
75
+ 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`.
76
+
77
+ ## Prerequisites
78
+
79
+ - At least one CLI installed and signed in:
80
+ - **agy** on `PATH`, or set `AGY_BIN_PATH`
81
+ - **and/or grok** on `PATH`, or set `GROK_BIN_PATH`
82
+ - Antigravity is Google's terminal agentic coding CLI (successor to Gemini CLI). Grok Build is xAI's counterpart.
83
+ - A WeChat account with a [ClawBot / iLink](https://ilinkai.weixin.qq.com) bot (QR bind on first run)
84
+ - Python 3.10+
85
+
86
+ ## Install
87
+
88
+ The recommended way is with [pipx](https://pypa.github.io/pipx/) (Python >= 3.10 required):
89
+
90
+ ```bash
91
+ pipx install wechatbridge-cli
92
+ ```
93
+
94
+ After installation, verify:
95
+
96
+ ```bash
97
+ wechatbridge --version
98
+ ```
99
+
100
+ ### Install pipx
101
+
102
+ **Debian / Ubuntu:**
103
+
104
+ ```bash
105
+ sudo apt install pipx
106
+ ```
107
+
108
+ **Other systems (or to get the latest version):**
109
+
110
+ ```bash
111
+ python3 -m pip install --user pipx && python3 -m pipx ensurepath
112
+ ```
113
+
114
+ Then start a new shell or re-source your shell config so `pipx` is on `PATH`.
115
+
116
+ ### Developers
117
+
118
+ If you want to hack on the source:
119
+
120
+ ```bash
121
+ git clone https://github.com/dorokuma/wechatbridge.git
122
+ cd wechatbridge
123
+ pip install -e .
124
+ ```
125
+
126
+ ## Configure
127
+
128
+ Configuration is loaded from the first location found:
129
+
130
+ 1. `$WECHATBRIDGE_ENV_FILE` — explicit path
131
+ 2. `$XDG_CONFIG_HOME/wechatbridge/<instance>.env` (defaults to `~/.config/wechatbridge/<instance>.env`)
132
+ 3. `$XDG_CONFIG_HOME/wechatbridge/.env` (defaults to `~/.config/wechatbridge/.env`)
133
+ 4. `.env` in the repository root — **deprecated** (prints a warning on startup)
134
+
135
+ The instance name defaults to `default`; override with `WECHATBRIDGE_INSTANCE`.
136
+
137
+ Get the example config:
138
+
139
+ ```bash
140
+ mkdir -p ~/.config/wechatbridge
141
+ curl -o ~/.config/wechatbridge/.env https://raw.githubusercontent.com/dorokuma/wechatbridge/main/deploy/wechatbridge.env.example
142
+ ```
143
+
144
+ Then edit `~/.config/wechatbridge/.env` with your settings.
145
+
146
+ Key variables (all have defaults):
147
+
148
+ | Variable | Default | Purpose |
149
+ |---|---|---|
150
+ | `AGY_BIN_PATH` | `agy` | path to the agy binary |
151
+ | `GROK_BIN_PATH` | `grok` | path to the grok binary |
152
+ | `WECHATBRIDGE_BACKEND` | `agy` | global default backend (`agy` / `grok`; overridable per user via `/backend`) |
153
+ | `WECHATBRIDGE_INSTANCE` | `default` | instance name; state / session / QR paths derive from it |
154
+ | `WECHATBRIDGE_ALLOWED_SENDERS` | _empty_ | comma-separated WeChat IDs (empty = allow all) |
155
+ | `AGY_TIMEOUT` | `600` | CLI run timeout in seconds (both backends) |
156
+ | `WECHATBRIDGE_MAX_OUTBOUND_BYTES` | `104857600` | max file size sent back to WeChat (100 MB) |
157
+ | `WECHATBRIDGE_MAX_INBOUND_BYTES` | `20971520` | max inbound image/file after download (20 MB) |
158
+ | `WECHATBRIDGE_MAX_CONCURRENT` | `4` | global concurrent handlers; extras get a busy reply |
159
+ | `WECHATBRIDGE_CONFIRM_TOKEN` | `y` | reply this token to approve a gated dangerous prompt |
160
+ | `WECHATBRIDGE_ENABLE_MCP` | `true` | enable the `/mcp` help text command |
161
+ | `WECHATBRIDGE_ENABLE_SUBAGENT` | `true` | enable the `/agent` prompt-rewrite command |
162
+ | `WECHATBRIDGE_ADMINS` | _empty_ | comma-separated wxid list; admins receive WeChat notification when a new version is detected |
163
+ | `WECHATBRIDGE_UPDATE_CHECK` | `true` | check PyPI for new versions on startup and every 24h; failures are silent |
164
+ | `WECHATBRIDGE_UPDATE_CHECK_INTERVAL` | `86400` | update check interval in seconds |
165
+
166
+ Full list: [`deploy/wechatbridge.env.example`](deploy/wechatbridge.env.example).
167
+
168
+ > **Why the new config location?** With pipx the package is installed globally, so a `.env` next to the source no longer makes sense. The XDG base directory layout keeps your config separate and instance-aware.
169
+
170
+ ## Run
171
+
172
+ ```bash
173
+ wechatbridge
174
+ ```
175
+
176
+ 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.
177
+
178
+ ## Upgrading
179
+
180
+ ```bash
181
+ pipx upgrade wechatbridge-cli
182
+ sudo systemctl restart wechatbridge
183
+ ```
184
+
185
+ Or run the upgrade script (no clone needed — fetch it with curl):
186
+
187
+ ```bash
188
+ curl -fsSL https://raw.githubusercontent.com/dorokuma/wechatbridge/main/deploy/update.sh | sudo bash
189
+ ```
190
+
191
+ 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>`).
192
+
193
+ 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.
194
+
195
+ Before upgrading a **major** or **minor** version (e.g. 1.2 → 1.3), check the corresponding section in [`CHANGELOG.md`](CHANGELOG.md) for breaking changes and migration steps.
196
+
197
+ ## Deploy
198
+
199
+ ### Linux (systemd)
200
+
201
+ First, install the bridge under the `wechatbridge` system user:
202
+
203
+ ```bash
204
+ sudo -u wechatbridge pipx install wechatbridge-cli
205
+ ```
206
+
207
+ Then deploy the service unit:
208
+
209
+ ```bash
210
+ sudo cp deploy/wechatbridge.service /etc/systemd/system/
211
+ sudo systemctl enable --now wechatbridge
212
+ ```
213
+
214
+ **Multi-instance:** copy the template `deploy/wechatbridge@.service` and enable instances:
215
+
216
+ ```bash
217
+ sudo cp deploy/wechatbridge@.service /etc/systemd/system/
218
+ sudo systemctl enable --now wechatbridge@bot2
219
+ sudo systemctl enable --now wechatbridge@bot3
220
+ ```
221
+
222
+ Each instance reads its own config file (`~/.config/wechatbridge/bot2.env`) and keeps state under its own data directory (`~/.local/share/wechatbridge/bot2/`).
223
+
224
+ ### macOS (launchd)
225
+
226
+ ```bash
227
+ cp deploy/wechatbridge.plist ~/Library/LaunchAgents/com.wechatbridge.plist
228
+ # edit WorkingDirectory and ProgramArguments in the plist
229
+ launchctl load ~/Library/LaunchAgents/com.wechatbridge.plist
230
+ ```
231
+
232
+ ### Windows (Task Scheduler)
233
+
234
+ See [`deploy/wechatbridge-windows.md`](deploy/wechatbridge-windows.md).
235
+
236
+ ## Slash commands
237
+
238
+ | Command | Action |
239
+ |---|---|
240
+ | `/help` | list supported commands for the active backend |
241
+ | `/backend <agy\|grok>` | switch CLI backend for this WeChat user (on real change: drop continue flag; history files may remain until retention cleanup) |
242
+ | `/clear` or `/new` | drop continue flag so the next CLI turn is a new conversation (does not instantly delete history files) |
243
+ | `/model <name>` | set model (validated against the backend's model list; see `/models`) |
244
+ | `/models` | list models from the active CLI |
245
+ | `/fast` | set low reasoning effort (**on only** — not a toggle; no “off” command) |
246
+ | `/planning` | set planning mode (**on only** — not a toggle) |
247
+ | `/add-dir <path>` | **agy:** pass `--add-dir` on later runs if path is allowed. **grok:** recorded only; not passed to the CLI yet |
248
+ | `/agents` | list agents via the active CLI |
249
+ | `/persona <text>` | set persona (`show` / `clear` / `reset` subcommands) |
250
+ | `/version` | show current version, instance name, and backend; if a newer version is available, show upgrade hint |
251
+ | `/mcp` | short MCP **usage hint** text (can disable with `WECHATBRIDGE_ENABLE_MCP`) |
252
+ | `/agent <name> <task>` | craft a "invoke subagent …" prompt and run the CLI (can disable with `WECHATBRIDGE_ENABLE_SUBAGENT`) |
253
+
254
+ Other `/…` commands are either rejected (e.g. `/exit`), reported as unsupported on WeChat (TUI-only panels), or passed through to the active CLI.
255
+
256
+ `/add-dir` only accepts paths under the user's session directory or roots listed in `WECHATBRIDGE_ADD_DIR_ROOTS`.
257
+
258
+ ## Ops & security (what the bridge actually enforces)
259
+
260
+ - **Whitelist first.** Empty `WECHATBRIDGE_ALLOWED_SENDERS` means anyone who can message the bot can use it.
261
+ - **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.
262
+ - **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 via `WECHATBRIDGE_CONFIRM_KEYWORDS`; approve with `WECHATBRIDGE_CONFIRM_TOKEN` (default `y`), TTL `WECHATBRIDGE_PENDING_TTL`.
263
+ - **Inbound media** is size-capped (default 20 MB), streamed, and CDN hosts are allowlisted. Missing `aes_key` returns a clear error.
264
+ - **Outbound artifacts** only leave the allowed per-user tree (agy: session scratch; grok: under session dir), after `realpath` checks, and only if under `WECHATBRIDGE_MAX_OUTBOUND_BYTES`.
265
+ - **Concurrency:** global cap (`WECHATBRIDGE_MAX_CONCURRENT`, default 4); same user is serialized, different users can run in parallel.
266
+ - **Long replies** are split into chunks (`WECHATBRIDGE_MESSAGE_CHUNK`, default 2000 characters).
267
+ - **Data layout:** instance data under `~/.local/share/wechatbridge/<instance>/` (override with env). Runtime dirs prefer `0700`; token/QR files prefer `0600` (Unix; Windows relies on NTFS ACLs).
268
+ - **Retention:** session temps vs dialogue history use separate TTLs (`WECHATBRIDGE_SESSION_RETENTION_DAYS`, `WECHATBRIDGE_HISTORY_RETENTION_DAYS`). Prefs/auth are kept.
269
+ - **Child env** is sanitized (strips common secret-style variable names) and points `HOME` (and `USERPROFILE` on Windows) at the per-user session dir.
270
+
271
+ ## Limitations
272
+
273
+ - Not a standalone agent — requires agy and/or grok.
274
+ - Voice is WeChat speech-to-text only; no local ASR; empty transcript → “type instead”.
275
+ - No video send/receive; no native WeChat voice-bubble replies (no silk encode).
276
+ - One WeChat binding per process; multiple accounts need multiple instances (`WECHATBRIDGE_INSTANCE`).
277
+ - Artifact send-back is best-effort detection under allowed paths, not “every file the CLI created anywhere”.
278
+ - `/mcp` / `/agent` do not implement MCP protocol or spawn process supervisors inside the bridge — they only guide or rephrase for the CLI.
279
+ - Deploy only for trusted users behind a whitelist when possible.
280
+
281
+ ## Contributing
282
+
283
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md). Semantic Versioning from 1.0.0; record changes in [`CHANGELOG.md`](CHANGELOG.md).
284
+
285
+ ## License
286
+
287
+ MIT. See [`LICENSE`](LICENSE).
@@ -3,6 +3,7 @@ name = "wechatbridge-cli"
3
3
  dynamic = ["version"]
4
4
  description = "Bridge WeChat messages to agy or Grok Build CLIs — text/image/file/voice in, CLI replies and generated files back."
5
5
  requires-python = ">=3.10"
6
+ readme = "README.md"
6
7
  license = { text = "MIT" }
7
8
  urls = { Homepage = "https://github.com/dorokuma/wechatbridge", Repository = "https://github.com/dorokuma/wechatbridge", Issues = "https://github.com/dorokuma/wechatbridge/issues", Changelog = "https://github.com/dorokuma/wechatbridge/blob/main/CHANGELOG.md" }
8
9
  authors = [
@@ -1,2 +1,2 @@
1
1
  """WeChatBridge — bridge WeChat messages to agy or Grok Build CLIs."""
2
- __version__ = "1.3.0"
2
+ __version__ = "1.3.1"
@@ -39,6 +39,8 @@ def _is_allowed_media_url(url: str) -> bool:
39
39
  return False
40
40
  if host == "weixin.qq.com" or host.endswith(".weixin.qq.com"):
41
41
  return True
42
+ if host == "wechat.com" or host.endswith(".wechat.com"):
43
+ return True
42
44
  if host == "qq.com" or host.endswith(".qq.com"):
43
45
  # WeChat CDN commonly uses *.cdn.weixin.qq.com / *.qq.com
44
46
  if "weixin" in host or "cdn" in host or "novac" in host:
@@ -799,7 +801,15 @@ class ILinkClient:
799
801
 
800
802
  # Build download URL
801
803
  if full_url:
802
- url = full_url
804
+ if _is_allowed_media_url(full_url):
805
+ url = full_url
806
+ elif encrypt_query_param:
807
+ logger.warning(
808
+ "CDN full_url %s 不在白名单内,回退到构造URL", full_url[:120]
809
+ )
810
+ url = f"{config.cdn_base_url}/download?encrypted_query_param={quote(encrypt_query_param)}"
811
+ else:
812
+ raise ValueError(f"拒绝非微信 CDN 下载地址: {full_url[:120]}")
803
813
  else:
804
814
  url = f"{config.cdn_base_url}/download?encrypted_query_param={quote(encrypt_query_param)}"
805
815
 
@@ -0,0 +1,287 @@
1
+ Metadata-Version: 2.4
2
+ Name: wechatbridge-cli
3
+ Version: 1.3.1
4
+ Summary: Bridge WeChat messages to agy or Grok Build CLIs — text/image/file/voice in, CLI replies and generated files back.
5
+ Author: WeChatBridge contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/dorokuma/wechatbridge
8
+ Project-URL: Repository, https://github.com/dorokuma/wechatbridge
9
+ Project-URL: Issues, https://github.com/dorokuma/wechatbridge/issues
10
+ Project-URL: Changelog, https://github.com/dorokuma/wechatbridge/blob/main/CHANGELOG.md
11
+ Keywords: wechat,bot,bridge,agy,grok
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Natural Language :: Chinese (Simplified)
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Communications :: Chat
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: httpx
27
+ Requires-Dist: qrcode
28
+ Requires-Dist: Pillow
29
+ Requires-Dist: cryptography
30
+ Dynamic: license-file
31
+
32
+ # WeChatBridge
33
+
34
+ [English](README.md) | [简体中文](README.zh-CN.md)
35
+
36
+ ![license](https://img.shields.io/badge/license-MIT-blue.svg)
37
+ ![python](https://img.shields.io/badge/python-3.10+-blue.svg)
38
+
39
+ 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.
40
+
41
+ ```
42
+ WeChat (phone) ⇄ iLink bot API ⇄ WeChatBridge ⇄ agy / grok CLI
43
+ (this project) (runs tools)
44
+ ```
45
+
46
+ 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.
47
+
48
+ ## Features
49
+
50
+ - Text, image, file, and voice (WeChat server-side transcription only) go to the **active** backend (`agy` or `grok`)
51
+ - Detected CLI artifacts under the per-user allowed tree can be sent back (size-capped); not every file the CLI touches
52
+ - Each WeChat user gets an isolated workspace; model / effort / mode are remembered **per backend**
53
+ - Runtime backend switch: `/backend agy` or `/backend grok` (clears the “continue session” flag so the next CLI turn starts without `-c` / `--continue`; does not immediately wipe history files on disk)
54
+ - Slash commands for model, session reset, persona, and more (see below)
55
+ - Dangerous-prompt gate: a **keyword list** of concrete destructive patterns asks for confirmation before run
56
+ - Sender whitelist (`WECHATBRIDGE_ALLOWED_SENDERS`; empty = allow all)
57
+ - `/mcp` returns short usage text; `/agent` rewrites into a natural-language subagent prompt for the CLI (not a native MCP bridge)
58
+ - Media over WeChat CDN with AES-128-ECB encrypt/decrypt
59
+ - Multi-instance: one codebase, set `WECHATBRIDGE_INSTANCE` per process (state / session / QR paths derive from it)
60
+ - Deploy templates: systemd (Linux), launchd (macOS), Task Scheduler notes (Windows)
61
+
62
+ ## Platform Support
63
+
64
+ - **Linux** — primary (systemd unit included)
65
+ - **macOS** — supported (launchd plist included)
66
+ - **Windows** — supported (Task Scheduler guide included)
67
+
68
+ Default data paths expand from `~` (e.g. `~/.local/share/wechatbridge/<instance>/`).
69
+
70
+ ## CLI Backends
71
+
72
+ - **agy** (default) — Google Antigravity CLI
73
+ - **grok** — xAI Grok Build CLI
74
+
75
+ 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`.
76
+
77
+ ## Prerequisites
78
+
79
+ - At least one CLI installed and signed in:
80
+ - **agy** on `PATH`, or set `AGY_BIN_PATH`
81
+ - **and/or grok** on `PATH`, or set `GROK_BIN_PATH`
82
+ - Antigravity is Google's terminal agentic coding CLI (successor to Gemini CLI). Grok Build is xAI's counterpart.
83
+ - A WeChat account with a [ClawBot / iLink](https://ilinkai.weixin.qq.com) bot (QR bind on first run)
84
+ - Python 3.10+
85
+
86
+ ## Install
87
+
88
+ The recommended way is with [pipx](https://pypa.github.io/pipx/) (Python >= 3.10 required):
89
+
90
+ ```bash
91
+ pipx install wechatbridge-cli
92
+ ```
93
+
94
+ After installation, verify:
95
+
96
+ ```bash
97
+ wechatbridge --version
98
+ ```
99
+
100
+ ### Install pipx
101
+
102
+ **Debian / Ubuntu:**
103
+
104
+ ```bash
105
+ sudo apt install pipx
106
+ ```
107
+
108
+ **Other systems (or to get the latest version):**
109
+
110
+ ```bash
111
+ python3 -m pip install --user pipx && python3 -m pipx ensurepath
112
+ ```
113
+
114
+ Then start a new shell or re-source your shell config so `pipx` is on `PATH`.
115
+
116
+ ### Developers
117
+
118
+ If you want to hack on the source:
119
+
120
+ ```bash
121
+ git clone https://github.com/dorokuma/wechatbridge.git
122
+ cd wechatbridge
123
+ pip install -e .
124
+ ```
125
+
126
+ ## Configure
127
+
128
+ Configuration is loaded from the first location found:
129
+
130
+ 1. `$WECHATBRIDGE_ENV_FILE` — explicit path
131
+ 2. `$XDG_CONFIG_HOME/wechatbridge/<instance>.env` (defaults to `~/.config/wechatbridge/<instance>.env`)
132
+ 3. `$XDG_CONFIG_HOME/wechatbridge/.env` (defaults to `~/.config/wechatbridge/.env`)
133
+ 4. `.env` in the repository root — **deprecated** (prints a warning on startup)
134
+
135
+ The instance name defaults to `default`; override with `WECHATBRIDGE_INSTANCE`.
136
+
137
+ Get the example config:
138
+
139
+ ```bash
140
+ mkdir -p ~/.config/wechatbridge
141
+ curl -o ~/.config/wechatbridge/.env https://raw.githubusercontent.com/dorokuma/wechatbridge/main/deploy/wechatbridge.env.example
142
+ ```
143
+
144
+ Then edit `~/.config/wechatbridge/.env` with your settings.
145
+
146
+ Key variables (all have defaults):
147
+
148
+ | Variable | Default | Purpose |
149
+ |---|---|---|
150
+ | `AGY_BIN_PATH` | `agy` | path to the agy binary |
151
+ | `GROK_BIN_PATH` | `grok` | path to the grok binary |
152
+ | `WECHATBRIDGE_BACKEND` | `agy` | global default backend (`agy` / `grok`; overridable per user via `/backend`) |
153
+ | `WECHATBRIDGE_INSTANCE` | `default` | instance name; state / session / QR paths derive from it |
154
+ | `WECHATBRIDGE_ALLOWED_SENDERS` | _empty_ | comma-separated WeChat IDs (empty = allow all) |
155
+ | `AGY_TIMEOUT` | `600` | CLI run timeout in seconds (both backends) |
156
+ | `WECHATBRIDGE_MAX_OUTBOUND_BYTES` | `104857600` | max file size sent back to WeChat (100 MB) |
157
+ | `WECHATBRIDGE_MAX_INBOUND_BYTES` | `20971520` | max inbound image/file after download (20 MB) |
158
+ | `WECHATBRIDGE_MAX_CONCURRENT` | `4` | global concurrent handlers; extras get a busy reply |
159
+ | `WECHATBRIDGE_CONFIRM_TOKEN` | `y` | reply this token to approve a gated dangerous prompt |
160
+ | `WECHATBRIDGE_ENABLE_MCP` | `true` | enable the `/mcp` help text command |
161
+ | `WECHATBRIDGE_ENABLE_SUBAGENT` | `true` | enable the `/agent` prompt-rewrite command |
162
+ | `WECHATBRIDGE_ADMINS` | _empty_ | comma-separated wxid list; admins receive WeChat notification when a new version is detected |
163
+ | `WECHATBRIDGE_UPDATE_CHECK` | `true` | check PyPI for new versions on startup and every 24h; failures are silent |
164
+ | `WECHATBRIDGE_UPDATE_CHECK_INTERVAL` | `86400` | update check interval in seconds |
165
+
166
+ Full list: [`deploy/wechatbridge.env.example`](deploy/wechatbridge.env.example).
167
+
168
+ > **Why the new config location?** With pipx the package is installed globally, so a `.env` next to the source no longer makes sense. The XDG base directory layout keeps your config separate and instance-aware.
169
+
170
+ ## Run
171
+
172
+ ```bash
173
+ wechatbridge
174
+ ```
175
+
176
+ 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.
177
+
178
+ ## Upgrading
179
+
180
+ ```bash
181
+ pipx upgrade wechatbridge-cli
182
+ sudo systemctl restart wechatbridge
183
+ ```
184
+
185
+ Or run the upgrade script (no clone needed — fetch it with curl):
186
+
187
+ ```bash
188
+ curl -fsSL https://raw.githubusercontent.com/dorokuma/wechatbridge/main/deploy/update.sh | sudo bash
189
+ ```
190
+
191
+ 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>`).
192
+
193
+ 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.
194
+
195
+ Before upgrading a **major** or **minor** version (e.g. 1.2 → 1.3), check the corresponding section in [`CHANGELOG.md`](CHANGELOG.md) for breaking changes and migration steps.
196
+
197
+ ## Deploy
198
+
199
+ ### Linux (systemd)
200
+
201
+ First, install the bridge under the `wechatbridge` system user:
202
+
203
+ ```bash
204
+ sudo -u wechatbridge pipx install wechatbridge-cli
205
+ ```
206
+
207
+ Then deploy the service unit:
208
+
209
+ ```bash
210
+ sudo cp deploy/wechatbridge.service /etc/systemd/system/
211
+ sudo systemctl enable --now wechatbridge
212
+ ```
213
+
214
+ **Multi-instance:** copy the template `deploy/wechatbridge@.service` and enable instances:
215
+
216
+ ```bash
217
+ sudo cp deploy/wechatbridge@.service /etc/systemd/system/
218
+ sudo systemctl enable --now wechatbridge@bot2
219
+ sudo systemctl enable --now wechatbridge@bot3
220
+ ```
221
+
222
+ Each instance reads its own config file (`~/.config/wechatbridge/bot2.env`) and keeps state under its own data directory (`~/.local/share/wechatbridge/bot2/`).
223
+
224
+ ### macOS (launchd)
225
+
226
+ ```bash
227
+ cp deploy/wechatbridge.plist ~/Library/LaunchAgents/com.wechatbridge.plist
228
+ # edit WorkingDirectory and ProgramArguments in the plist
229
+ launchctl load ~/Library/LaunchAgents/com.wechatbridge.plist
230
+ ```
231
+
232
+ ### Windows (Task Scheduler)
233
+
234
+ See [`deploy/wechatbridge-windows.md`](deploy/wechatbridge-windows.md).
235
+
236
+ ## Slash commands
237
+
238
+ | Command | Action |
239
+ |---|---|
240
+ | `/help` | list supported commands for the active backend |
241
+ | `/backend <agy\|grok>` | switch CLI backend for this WeChat user (on real change: drop continue flag; history files may remain until retention cleanup) |
242
+ | `/clear` or `/new` | drop continue flag so the next CLI turn is a new conversation (does not instantly delete history files) |
243
+ | `/model <name>` | set model (validated against the backend's model list; see `/models`) |
244
+ | `/models` | list models from the active CLI |
245
+ | `/fast` | set low reasoning effort (**on only** — not a toggle; no “off” command) |
246
+ | `/planning` | set planning mode (**on only** — not a toggle) |
247
+ | `/add-dir <path>` | **agy:** pass `--add-dir` on later runs if path is allowed. **grok:** recorded only; not passed to the CLI yet |
248
+ | `/agents` | list agents via the active CLI |
249
+ | `/persona <text>` | set persona (`show` / `clear` / `reset` subcommands) |
250
+ | `/version` | show current version, instance name, and backend; if a newer version is available, show upgrade hint |
251
+ | `/mcp` | short MCP **usage hint** text (can disable with `WECHATBRIDGE_ENABLE_MCP`) |
252
+ | `/agent <name> <task>` | craft a "invoke subagent …" prompt and run the CLI (can disable with `WECHATBRIDGE_ENABLE_SUBAGENT`) |
253
+
254
+ Other `/…` commands are either rejected (e.g. `/exit`), reported as unsupported on WeChat (TUI-only panels), or passed through to the active CLI.
255
+
256
+ `/add-dir` only accepts paths under the user's session directory or roots listed in `WECHATBRIDGE_ADD_DIR_ROOTS`.
257
+
258
+ ## Ops & security (what the bridge actually enforces)
259
+
260
+ - **Whitelist first.** Empty `WECHATBRIDGE_ALLOWED_SENDERS` means anyone who can message the bot can use it.
261
+ - **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.
262
+ - **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 via `WECHATBRIDGE_CONFIRM_KEYWORDS`; approve with `WECHATBRIDGE_CONFIRM_TOKEN` (default `y`), TTL `WECHATBRIDGE_PENDING_TTL`.
263
+ - **Inbound media** is size-capped (default 20 MB), streamed, and CDN hosts are allowlisted. Missing `aes_key` returns a clear error.
264
+ - **Outbound artifacts** only leave the allowed per-user tree (agy: session scratch; grok: under session dir), after `realpath` checks, and only if under `WECHATBRIDGE_MAX_OUTBOUND_BYTES`.
265
+ - **Concurrency:** global cap (`WECHATBRIDGE_MAX_CONCURRENT`, default 4); same user is serialized, different users can run in parallel.
266
+ - **Long replies** are split into chunks (`WECHATBRIDGE_MESSAGE_CHUNK`, default 2000 characters).
267
+ - **Data layout:** instance data under `~/.local/share/wechatbridge/<instance>/` (override with env). Runtime dirs prefer `0700`; token/QR files prefer `0600` (Unix; Windows relies on NTFS ACLs).
268
+ - **Retention:** session temps vs dialogue history use separate TTLs (`WECHATBRIDGE_SESSION_RETENTION_DAYS`, `WECHATBRIDGE_HISTORY_RETENTION_DAYS`). Prefs/auth are kept.
269
+ - **Child env** is sanitized (strips common secret-style variable names) and points `HOME` (and `USERPROFILE` on Windows) at the per-user session dir.
270
+
271
+ ## Limitations
272
+
273
+ - Not a standalone agent — requires agy and/or grok.
274
+ - Voice is WeChat speech-to-text only; no local ASR; empty transcript → “type instead”.
275
+ - No video send/receive; no native WeChat voice-bubble replies (no silk encode).
276
+ - One WeChat binding per process; multiple accounts need multiple instances (`WECHATBRIDGE_INSTANCE`).
277
+ - Artifact send-back is best-effort detection under allowed paths, not “every file the CLI created anywhere”.
278
+ - `/mcp` / `/agent` do not implement MCP protocol or spawn process supervisors inside the bridge — they only guide or rephrase for the CLI.
279
+ - Deploy only for trusted users behind a whitelist when possible.
280
+
281
+ ## Contributing
282
+
283
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md). Semantic Versioning from 1.0.0; record changes in [`CHANGELOG.md`](CHANGELOG.md).
284
+
285
+ ## License
286
+
287
+ MIT. See [`LICENSE`](LICENSE).
@@ -1,29 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: wechatbridge-cli
3
- Version: 1.3.0
4
- Summary: Bridge WeChat messages to agy or Grok Build CLIs — text/image/file/voice in, CLI replies and generated files back.
5
- Author: WeChatBridge contributors
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/dorokuma/wechatbridge
8
- Project-URL: Repository, https://github.com/dorokuma/wechatbridge
9
- Project-URL: Issues, https://github.com/dorokuma/wechatbridge/issues
10
- Project-URL: Changelog, https://github.com/dorokuma/wechatbridge/blob/main/CHANGELOG.md
11
- Keywords: wechat,bot,bridge,agy,grok
12
- Classifier: Development Status :: 4 - Beta
13
- Classifier: Environment :: Console
14
- Classifier: Intended Audience :: Developers
15
- Classifier: License :: OSI Approved :: MIT License
16
- Classifier: Natural Language :: Chinese (Simplified)
17
- Classifier: Operating System :: POSIX :: Linux
18
- Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.10
20
- Classifier: Programming Language :: Python :: 3.11
21
- Classifier: Programming Language :: Python :: 3.12
22
- Classifier: Topic :: Communications :: Chat
23
- Requires-Python: >=3.10
24
- License-File: LICENSE
25
- Requires-Dist: httpx
26
- Requires-Dist: qrcode
27
- Requires-Dist: Pillow
28
- Requires-Dist: cryptography
29
- Dynamic: license-file
@@ -1,29 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: wechatbridge-cli
3
- Version: 1.3.0
4
- Summary: Bridge WeChat messages to agy or Grok Build CLIs — text/image/file/voice in, CLI replies and generated files back.
5
- Author: WeChatBridge contributors
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/dorokuma/wechatbridge
8
- Project-URL: Repository, https://github.com/dorokuma/wechatbridge
9
- Project-URL: Issues, https://github.com/dorokuma/wechatbridge/issues
10
- Project-URL: Changelog, https://github.com/dorokuma/wechatbridge/blob/main/CHANGELOG.md
11
- Keywords: wechat,bot,bridge,agy,grok
12
- Classifier: Development Status :: 4 - Beta
13
- Classifier: Environment :: Console
14
- Classifier: Intended Audience :: Developers
15
- Classifier: License :: OSI Approved :: MIT License
16
- Classifier: Natural Language :: Chinese (Simplified)
17
- Classifier: Operating System :: POSIX :: Linux
18
- Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.10
20
- Classifier: Programming Language :: Python :: 3.11
21
- Classifier: Programming Language :: Python :: 3.12
22
- Classifier: Topic :: Communications :: Chat
23
- Requires-Python: >=3.10
24
- License-File: LICENSE
25
- Requires-Dist: httpx
26
- Requires-Dist: qrcode
27
- Requires-Dist: Pillow
28
- Requires-Dist: cryptography
29
- Dynamic: license-file