Claude Code and Codex. In WeChat Private Chat.
Run local Claude Code or Codex agent sessions from WeChat, with Claude tool approval and file relay; an experimental Gemini Code Assist text backend is also available.
A self-hosted bridge that uses WeChat's iLink bot endpoints. The WeChat transport itself needs no separate tunnel where iLink is available; each AI backend still needs its normal network access and account eligibility.
English | 简体中文
How is this different from cc-weixin / wechat-acp?
This project focuses on session management (
/new/resume/sessions), backend selection (Claude + Codex, with experimental Gemini text compatibility), Claude tool approval, and bidirectional file relay — the same workflow family as telegram-ai-bridge, now using WeChat transport.
Send a message in WeChat and run a Claude Code or Codex turn on the bridge host. Available tools and filesystem access come from the selected SDK/CLI and its local configuration. The workflow requires WeChat/iLink and the selected model provider to be reachable.
你: /new ← Start a fresh session
你: /sessions ← List recent sessions
你: /resume 3 ← Pick up where you left off
你: /backend codex ← Switch backend
你: /model ← Switch models (reply with number)
Bridge session mappings and preferences persist in SQLite. Claude and Codex sessions can be discovered from their local session stores and resumed after restart. The experimental Gemini adapter keeps its conversation history in memory, so that history does not survive a bridge restart. /sessions lists sessions discoverable for the active backend; resume by number with /resume 3.
| Backend | Integration and capability | Status |
|---|---|---|
claude |
Agent SDK + local Claude executable; agent tools, resumable sessions, bridge-mediated tool approval | Recommended |
codex |
Codex SDK/CLI; agent tools and resumable threads, without bridge-mediated approval prompts | Recommended |
gemini |
Google Code Assist API text generation with in-memory history; no local tool execution | Experimental |
Select the backend at startup with --backend. /backend can switch only among adapters explicitly loaded by an advanced multi-adapter deployment.
When the Claude backend asks for permission to run a tool:
🔒 工具审批
工具: Bash
git push origin main
请回复数字:
1. 允许
2. 拒绝
3. 始终允许 "Bash"
4. YOLO(全部允许)
Reply 1, 2, 3, or 4. No buttons needed — just text.
- Send photos/files to Claude or Codex: WeChat media is downloaded, decrypted (AES-128-ECB), stored under local
files/with a sanitized portable filename, and passed to the agent as a local path - Receive files from Claude or Codex: detected local output files and screenshots are sent only when both their lexical and real paths resolve to a regular file under that chat's current working directory. Hidden paths, control characters, common auth/config/credential/key/log/OAuth/secret/session/token names, symlink escapes, oversized files, and inbound
files/uploads are rejected before reading. - Long output: messages over 2000 chars are auto-split into multiple messages, with code fences kept intact
The experimental Gemini text backend cannot read the downloaded local file by itself because it has no local tools.
- Local by default: bridge config, token, SQLite session/task mappings, and decrypted inbound file copies are stored on the bridge host.
- Fail-closed sender authorization: only exact iLink
from_user_idvalues listed inshared.allowedUserIdsare processed. Unknown senders are rejected before media download, approval handling, commands, or model calls. - WeChat transport: messages and context tokens pass through iLink endpoints; media is downloaded from or uploaded to the WeChat CDN.
- Model providers: prompts and any context selected by the agent follow the data handling of the configured Claude, OpenAI, or Google backend. They do not remain exclusively on the bridge host.
- Host access: this bridge is not a sandbox. Claude Code and Codex run with the filesystem and process permissions granted to their local CLI/SDK configuration. Bridge-mediated tool approval currently applies only to Claude.
- Rate limiting: Per-user sliding window
- Idle monitoring: Watchdog timer for hung tasks
- Message batching: FlushGate merges rapid consecutive messages (800ms window)
- Send retry: Exponential backoff with error classification
- File reference protection: Prevents auto-linking of
.md,.go,.pyfilenames
Prerequisites: Bun runtime, WeChat version >= 2026.3.20, and at least one backend CLI: Claude Code, Codex, or Gemini CLI.
git clone https://github.com/AliceLJY/wechat-ai-bridge.git
cd wechat-ai-bridge
npm install # or: bun install
bun run bootstrap --backend claude
# Edit config.json and set shared.allowedUserIds to verified iLink from_user_id values.
bun run check --backend claude
bun run start --backend claudeOn first launch, a QR code appears in your terminal. Scan it with WeChat to authenticate. Token is saved to ~/.wechat-ai-bridge/token.json for subsequent launches.
shared.allowedUserIds is required and starts empty. Use exact, independently verified iLink from_user_id strings—not a display name, WeChat alias, or guessed value. The bridge never auto-claims the first contact. Validation fails while the list is empty; rejected sender IDs are written only to the local process log and are never added automatically. start.js serializes the configured list into the internal WECHAT_ALLOWED_USER_IDS environment variable before loading the bridge.
On POSIX hosts, the bridge enforces mode 0600 on config.json and ~/.wechat-ai-bridge/token.json, and mode 0700 on ~/.wechat-ai-bridge/ and the inbound files/ directory. It refuses symbolic links for these private paths; Windows deployments should also restrict these paths with local ACLs.
All commands are plain text — just type and send:
| Command | Description |
|---|---|
/help |
Show all commands |
/new |
Start a new session |
/cancel |
Abort the running task |
/sessions |
List recent sessions |
/resume <#|id> |
Resume by sequence number or session ID |
/backend [name] |
Switch backend (claude/codex/gemini) |
/model [name] |
Pick a model (reply with number) |
/effort [level] |
Set thinking depth |
/status |
Show backend, model, cwd, session |
| `/dir [path | -]` |
/verbose 0|1|2 |
Change progress verbosity |
WeChat App ←→ iLink Server (ilinkai.weixin.qq.com) ←→ wechat-ai-bridge ←→ AI Backend
│
├── weixin/ (iLink connection)
├── adapters/ (Claude/Codex/Gemini)
├── sessions.js (SQLite persistence)
└── bridge.js (core message loop)
The bridge uses WeChat iLink bot endpoints. Communication is HTTP/JSON with long-polling (getupdates), similar to Telegram's Bot API. Media files use the protocol's AES-128-ECB encryption before CDN upload.
The source code can show which endpoints it calls, but it cannot guarantee platform status, account eligibility, continued availability, or zero enforcement risk. Check the current WeChat terms that apply to your account and deployment.
| Feature | cc-weixin | wechat-acp | This project |
|---|---|---|---|
| AI backends | Claude only | 6 via ACP | Claude + Codex agents; experimental Gemini text backend |
| Session management | None | None | /new /resume /sessions /backend |
| Tool approval | Auto-allow | Auto-allow | Interactive for Claude; no bridge approval prompt for Codex/Gemini |
| Model switching | Hardcoded | Per-preset | /model with numbered selection |
| File relay (in) | Text only | Images+files | Local-path relay for tool-capable Claude/Codex backends |
| File relay (out) | None | None | Auto-detect local paths + encrypted WeChat CDN upload |
| Rate limiting | None | None | Per-user sliding window |
| Idle monitoring | None | None | Watchdog + auto-reset |
| Message batching | None | None | FlushGate (800ms merge) |
| Cross-platform sessions | None | None | Discover local Claude/Codex sessions (CLI + other bridges) |
Comparison entries describe the projects as reviewed on 2026-07-17 and may change upstream.
Configuration
bun run bootstrap --backend claude generates a starter config.json.
{
"shared": {
"cwd": "/Users/you",
"allowedUserIds": ["replace-with-verified-from_user_id"],
"defaultVerboseLevel": 1,
"executor": "direct",
"rateLimitMaxRequests": 10,
"rateLimitWindowMs": 60000,
"idleTimeoutMs": 1800000
},
"backends": {
"claude": {
"enabled": true,
"sessionsDb": "sessions.db",
"model": "claude-sonnet-4-7",
"permissionMode": "default"
}
}
}Project Structure
start.js— CLI entry with QR login flowconfig.js— Config loader and setup wizardbridge.js— Core message loopprogress.js— Typing indicator + processing statussessions.js— SQLite session persistenceweixin/api.js— iLink HTTP clientweixin/auth.js— QR code login + token persistenceweixin/monitor.js— Long-polling message listenerweixin/send.js— Message sending + text chunkingweixin/media.js— CDN upload/download + AES-128-ECBinbound-files.js— Portable filename sanitization + download containmentruntime-paths.js— Cross-platform home-directory resolutionweixin/types.js— iLink protocol constantsadapters/— AI backend integrations (Claude/Codex/Gemini)executor/— Execution modes
iLink Protocol Notes
- Authentication: QR code scan →
bot_token(persisted locally to~/.wechat-ai-bridge/token.json) - Message flow:
getupdateslong-poll (35s hold) → process →sendmessagewithcontext_token - Media: AES-128-ECB encrypted CDN (
novac2c.cdn.weixin.qq.com) - Limitation: 1 WeChat account = 1 bot (1:1 binding)
- No group chat: the current bridge supports private messaging only
- Policy boundary: endpoint availability and account eligibility remain subject to current WeChat terms
The adapter interface is designed for easy extension. To add a new AI backend (e.g. OpenCode, Crush, or any CLI agent):
- Create
adapters/yourbackend.jsexportingcreateAdapter(config):
export function createAdapter(config = {}) {
return {
name: "yourbackend",
async *streamQuery({ prompt, sessionId, model, cwd, abortController }) {
yield { type: "session_init", sessionId: "..." };
yield { type: "text", text: "response chunk" };
yield { type: "result", success: true, text: "final answer" };
},
statusInfo() {
return { backend: "yourbackend", model: "...", session: "..." };
}
};
}- Register it in
adapters/interface.jsand add the name toAVAILABLE_BACKENDSinconfig.js.
Event types: session_init | progress (tool use indicators) | text (streaming chunks) | result (final).
Community interest: OpenCode / Crush support has been requested. OpenCode offers a JS/TS SDK (
@opencode-ai/sdk); Crush provides a Unix socket REST API with SSE streaming. PRs welcome!
Part of the 小试AI open-source AI workflow:
| Project | Description |
|---|---|
| telegram-ai-bridge | Same architecture, Telegram interface |
| tg-bridge-channel | Sister bridge using Claude Agent View background sessions (channel/pool engine) |
| recallnest | MCP memory workbench |
| openclaw-tunnel | Docker ↔ host CLI bridge |
MIT