Your personal WeChat account, exposed as a tiny event pipe. Scan QR. Listen forever. Ship payloads anywhere.
wechat-relay is a minimal CLI that turns a WeChat personal account into a programmable message bridge.
- QR login with local session persistence
- Long-poll listener with crash-safe queue replay
- Hook command execution for every inbound message
- Reply from the CLI with text, image, or audio
- NuGet tool, npm wrapper, and native AOT binaries
npm install -g @slaveoftime/wechat-relay
wechat-relayThe npm package ships a bundled native binary for:
linux-x64win32-x64darwin-arm64
dotnet tool install -g wechat-relay
wechat-relayGrab a release artifact and run it directly:
wechat-relay-{version}-linux-x64.tar.gzwechat-relay-{version}-win-x64.zipwechat-relay-{version}-osx-arm64.tar.gz
Native builds are self-contained. No SDK required.
# 1. Pair the account
wechat-relay login
# 2. Start the stream
wechat-relay listen
# 3. Reply with text
wechat-relay send --text "hello from the terminal"
# 4. Reply with media
wechat-relay send friend@im.wechat --image ./cat.jpg
wechat-relay send friend@im.wechat --audio ./reply.silk --audio-playtime-ms 4210The first time you reply to a user, WeChat expects a context_token from an inbound message.
Translation: run listen, let them message you once, then send works.
| Command | What it does |
|---|---|
login |
Starts QR login, or reuses the stored local session |
login --force |
Clears stored session state and pairs again |
listen |
Long-polls WeChat and fires your hook for each inbound message |
listen --hook "..." |
Overrides Hook:Command for the current run |
list-send-to |
Prints send targets from WeChat:UserId and WeChat:ToUsers |
send [target] --text "..." |
Sends a text message |
send [target] --image ./file.jpg |
Uploads and sends an image |
send [target] --audio ./file.silk |
Uploads and sends audio or voice |
--verbose |
Enables debug logging on any command |
send accepts exactly one payload mode at a time: --text, --image, or --audio.
Audio flags currently supported:
wechat-relay send friend@im.wechat \
--audio ./reply.ogg \
--audio-format ogg \
--audio-sample-rate 16000 \
--audio-bits-per-sample 16 \
--audio-playtime-ms 4210Supported audio format hints: pcm, wav, adpcm, feature, speex, amr, silk, mp3, ogg.
Put appsettings.json next to the executable or run from the project directory.
{
"WeChat": {
"BaseUrl": "https://ilinkai.weixin.qq.com/",
"BotType": "3",
"UserId": "self@im.wechat",
"ToUsers": "friend1@im.wechat,friend2@im.wechat"
},
"Hook": {
"Command": "echo {payload}",
"WorkingDirectory": null
}
}Notes:
Hook:Commanddefaults toecholisten --hookoverridesHook:Commandwithout editing configUserIdis the defaultsendtargetToUsersadds extra IDs forlist-send-to
Every inbound message is queued, persisted, and then passed to your hook command as JSON.
Minimal example:
{
"seq": 42,
"message_id": 7447467781622590088,
"from_user_id": "friend@im.wechat",
"to_user_id": "bot@im.bot",
"create_time_ms": 1775614686361,
"message_type": 1,
"text": "hello",
"summary": "text=\"hello\" [image] [audio 4210ms]",
"items": [
{
"item_type": 1,
"kind": "text",
"text": "hello"
},
{
"item_type": 2,
"kind": "image",
"local_path": "C:\\Users\\you\\AppData\\Roaming\\wechat-relay\\inbound-media\\20260409\\msg-7447467781622590088-42\\00-image-image.jpg"
}
],
"context_token": "AARzJWAFAAABAAAA..."
}Storage lives under your application data directory:
session-state.jsonstores login state and cached context tokenspending-messages.jsonlstores queued hook work for crash recoveryinbound-media/stores downloaded inbound images, audio, files, and video before the hook runs
If the process dies after receipt but before hook execution, the next listen run drains the queue and replays the pending payloads.
Typical listener output:
Listening
Bridge WeChat messages to any webhook
Press Ctrl+C to stop.
[14:23:01] 42 friend@im.wechat type=1 text="hello"
[14:23:15] 43 friend@im.wechat type=1 [image]
[14:23:22] 44 friend@im.wechat type=1 text="see attached" [audio 4210ms]
git clone https://github.com/slaveoftime/wechat-relay.git
cd wechat-relay/WeChatRelay
# local build
dotnet build
# package as a dotnet tool
dotnet pack -c Release
# native AOT
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishAot=true
dotnet publish -c Release -r linux-x64 --self-contained true -p:PublishAot=true
dotnet publish -c Release -r osx-arm64 --self-contained true -p:PublishAot=trueTarget framework: .NET 10.