omp-wechat
OMP/Pi extension: bridge WeChat messages to OMP's AI engine via the iLink Bot API
Package details
Install omp-wechat from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:omp-wechat- Package
omp-wechat- Version
1.4.1- Published
- Jul 25, 2026
- Downloads
- 1,137/mo · 926/wk
- Author
- mentalfl0w
- License
- MIT
- Types
- extension
- Size
- 95.5 KB
- Dependencies
- 1 dependency · 0 peers
Pi manifest JSON
{
"extensions": [
"./dist/index.js"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
OMP-Wechat
Bridge WeChat messages to OMP (Oh My Pi) / Pi — receive WeChat messages, process them with OMP/Pi's AI engine, and reply back automatically.
Uses the Tencent iLink Bot API (the official WeChat personal-account Bot API behind ClawBot) for message transport, and the OMP/Pi SDK as the AI brain.
How It Works
WeChat user → iLink Bot API → [OMP/Pi process] → SDK → AI provider
↑ │
└──── reply ← message_end ─┘
The extension runs inside the OMP/Pi process. The iLink long-poll loop starts at extension load time (not session_start) as a background promise. A singleton port lock ensures only one process runs the poll loop at a time — other OMP/Pi processes standby with a 30s failover timer to take over if the lock holder crashes.
For boot-time persistence, install a launchd/systemd service via /wechat install. The service runs omp --mode rpc (or pi --mode rpc) with a get_state JSON-RPC heartbeat piped to stdin every 5s — without an active RPC client, omp --mode rpc exits on idle stdin, so the heartbeat keeps the process alive. KeepAlive/Restart=always handles crashes and reboots.
- No external
bunrequired — OMP/Pi is a standalone binary with an embedded runtime - Singleton — port lock guarantees one poll loop across all concurrent OMP/Pi processes
- Failover — non-lock-holder processes check every 30s and take over if the lock holder dies
- iLink layer: long-polls
getupdatesfor inbound messages, sends replies viasendmessage - AI engine: one in-memory session per WeChat chat, prompts injected via
session.prompt() - Typing indicator: shows "Typing..." on WeChat while the model is thinking
- Access control: pairing-based — strangers must pair before their messages are delivered
Features
- OMP/Pi extension: installs via
omp plugin link .orpi plugin link ., auto-starts poll loop at extension load time - Slash commands:
/wechat login,/wechat status,/wechat pair,/wechat allow,/wechat revoke,/wechat list,/wechat stop,/wechat install,/wechat uninstall - Singleton: port lock guarantees one poll loop across all concurrent OMP/Pi processes — no duplicate replies
- Failover: 30s timer takes over automatically if the lock holder crashes
- Bidirectional: receive and reply to WeChat text messages
- Image recognition: inbound images are downloaded from WeChat CDN, AES-decrypted, and passed to the vision model
- Per-chat sessions: each WeChat chat gets an independent AI session (concurrent, isolated)
- LRU pool: caps memory usage by evicting least-recently-used sessions (default: 50)
- Typing indicator: native WeChat "Typing..." shown during AI processing
- Access control: pairing / allowlist / disabled modes
- Long text chunking: splits replies >2000 chars at paragraph/line/space boundaries
- Boot service: optional launchd/systemd service for auto-start on boot
Quick Start
Prerequisites
- OMP or Pi installed and authenticated (
omp login/pi login) - WeChat (latest iOS version with ClawBot support)
Install
git clone https://github.com/mentalfl0w/omp-wechat.git OMP-Wechat
cd OMP-Wechat
bun install # build dependency only
bun run build
omp plugin link . # or: pi plugin link .
This links the extension into OMP/Pi. The poll loop starts at extension load time — no session_start required.
Login (scan QR code)
/wechat login
A QR code appears in the terminal. Scan it with WeChat and confirm on your phone. Credentials are saved to ~/.omp-wechat/credentials.json.
Run
No explicit run command needed — the poll loop starts at extension load time. Once running, send a message to the bot on WeChat — it will be processed and the reply sent back.
To check status: /wechat status. To stop: /wechat stop.
Boot-time auto-start (optional)
/wechat install
Installs a launchd (macOS) or systemd (Linux) service that runs the host (omp --mode rpc or pi --mode rpc) at boot. A get_state JSON-RPC heartbeat is piped to stdin every 5s to keep the process alive (without an active RPC client, omp --mode rpc exits on idle stdin). KeepAlive/Restart=always handles crashes and reboots.
Logs: ~/.omp/logs/rpc.log (stderr only; stdout discarded) and ~/.omp/logs/wechat.log (poll loop)
Manage: launchctl start|stop com.omp-wechat (macOS) or sudo systemctl start|stop omp-wechat (Linux)
To remove: /wechat uninstall
Configuration
Configuration is loaded from ~/.omp-wechat/config.yml, falling back to built-in defaults.
# ~/.omp-wechat/config.yml
maxSessions: 50
dmPolicy: pairing
model: "@smol" # default model (role alias or provider/id)
cwd: ~/projects/my-app # working directory for AI sessions
systemPrompt: |
You are an AI assistant chatting via WeChat.
Keep replies concise and in plain text.
| Field | Default | Description |
|---|---|---|
maxSessions |
50 |
Session pool cap (LRU eviction) |
dmPolicy |
pairing |
Access policy: pairing / allowlist / disabled |
model |
OMP default | Default model: role alias (@smol, @slow) or provider/id |
cwd |
process.cwd() |
Working directory for AI sessions — determines which project context (CLAUDE.md, .omp/) the agent loads |
systemPrompt |
Built-in | System prompt for WeChat chat sessions |
Model and tools are managed by OMP/Pi.
createAgentSession()automatically callsdiscoverAuthStorage(), reusing your existingomp login/pi loginOAuth,~/.omp/agent/agent.dbAPI keys, ormodels.ymlconfig. This project never touches API keys.Image recognition requires a vision model role configured in OMP (e.g.
omp model role vision xfyun/xopkimik25). If no vision role is set, inbound images are skipped — only the text placeholder is sent to the AI.
Slash Commands
| Command | Description |
|---|---|
/wechat login |
Scan QR code to log in |
/wechat status |
Show poll loop state, session pool, boot service, authorized users |
/wechat pair <code> |
Approve a pairing request |
/wechat allow <wxid> |
Directly authorize a user |
/wechat revoke <wxid> |
Revoke a user's authorization |
/wechat list |
List authorized users |
/wechat stop |
Stop the poll loop |
/wechat install |
Install boot-time launchd/systemd service |
/wechat uninstall |
Remove boot-time service |
Chat Commands (via WeChat message)
| Command | Description |
|---|---|
/model |
Show current AI model |
/models |
List all available models |
/model provider/id |
Switch model for this chat (e.g. /model anthropic/claude-haiku-4-5) |
/new |
Reset session — clear context and start fresh |
Access Control
| Mode | Behavior |
|---|---|
pairing (default) |
Unknown senders get a pairing code; they must be approved via /wechat pair <code> |
allowlist |
Only users in the allowlist can send messages; others are silently dropped |
disabled |
All inbound messages are dropped |
The logged-in user (who scanned the QR code) is automatically added to the allowlist.
Lifecycle
| Scenario | Behavior |
|---|---|
| Host process starts | Poll loop starts at extension load time (acquires singleton lock) |
| Other host processes | Standby with 30s failover timer, take over if lock holder dies |
| Host process exits | Poll loop stops, lock released, all sessions disposed |
| Host crashes | Failover timer in another process detects dead lock and takes over; or launchd/systemd restarts the host (if /wechat install was run) |
| Machine reboots | Service auto-starts the host (if installed), poll loop resumes |
| No boot service | Poll loop only runs while a host process is active |
Logs: ~/.omp/logs/wechat.log (poll loop) and ~/.omp/logs/rpc.log (boot service stderr)
Project Structure
OMP-Wechat/
├── package.json # omp.extensions / pi.extensions manifest
├── src/
│ ├── index.ts # OMP/Pi extension entry (extension load + /wechat commands)
│ ├── bridge.ts # In-process poll loop + message handling + singleton port lock
│ ├── service.ts # Boot-time launchd/systemd install
│ ├── config.ts # Config loading (config.yml + defaults)
│ ├── ilink/
│ │ ├── types.ts # iLink Bot API type definitions
│ │ ├── client.ts # iLink API client (poll/send/typing)
│ │ └── login.ts # QR code login flow
│ ├── engine/
│ │ ├── session.ts # AI session creation + reply subscription
│ │ └── pool.ts # Session pool (LRU eviction, concurrency)
│ ├── access/
│ │ └── control.ts # Access control (pairing/allowlist/disabled)
│ ├── utils/
│ │ ├── chunk.ts # Long text chunking
│ │ └── logger.ts # stderr + file logger
│ └── types/
│ └── qrcode-terminal.d.ts
├── dist/ # Built output (index.js)
└── README.md
Limitations
- Reply-only: iLink requires
context_tokenfrom an inbound message; you cannot initiate conversations - 1:1 only: iLink Bot API does not support group chats
- Single instance: iLink allows only one bot connection per account
- Media: inbound images are downloaded from WeChat CDN, AES-decrypted, and passed to the vision model (if
modelRoles.visionis configured); voice/video remain as placeholders
Roadmap
- Phase 2a: Inbound image support (CDN download + AES decrypt + vision model)
- Phase 2b: Voice transcription / video support
- Phase 3: Persistent sessions —
SessionManager.continueRecent()per chat, context survives restarts - Phase 4: Per-chat model selection —
/model/modelschat commands for manual switching - Phase 5: Fine-grained permissions (per-user tool restrictions, bash approval via WeChat)
License
MIT