Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wechat-relay

Your personal WeChat account, exposed as a tiny event pipe. Scan QR. Listen forever. Ship payloads anywhere.

CI NuGet MIT dotnet tool

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

Install

npm wrapper

npm install -g @slaveoftime/wechat-relay
wechat-relay

The npm package ships a bundled native binary for:

  • linux-x64
  • win32-x64
  • darwin-arm64

.NET global tool

dotnet tool install -g wechat-relay
wechat-relay

Native binary

Grab a release artifact and run it directly:

  • wechat-relay-{version}-linux-x64.tar.gz
  • wechat-relay-{version}-win-x64.zip
  • wechat-relay-{version}-osx-arm64.tar.gz

Native builds are self-contained. No SDK required.

Boot Sequence

# 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 4210

The 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.

Commands

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
history --tail 10 Shows the latest saved received/sent messages
history --json Outputs saved history as a JSON array
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 4210

Supported audio format hints: pcm, wav, adpcm, feature, speex, amr, silk, mp3, ogg.

Config

Put appsettings.json in your per-user wechat-relay directory:

  • Windows: C:\Users\<you>\wechat-relay\appsettings.json
  • Linux/macOS: ~/wechat-relay/appsettings.json
{
  "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:Command defaults to echo
  • listen --hook overrides Hook:Command without editing config
  • UserId is the default send target
  • ToUsers adds extra IDs for list-send-to
  • History:DirectoryPath is optional; by default, received/sent history JSON files are saved directly in the same per-user wechat-relay directory. Relative custom paths are resolved under that directory.

Hook Mode

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\\wechat-relay\\inbound-media\\20260409\\msg-7447467781622590088-42\\00-image-image.jpg"
    }
  ],
  "context_token": "AARzJWAFAAABAAAA..."
}

Storage lives under your per-user wechat-relay directory, for example C:\Users\<you>\wechat-relay on Windows or ~/wechat-relay on Linux/macOS:

  • appsettings.json stores CLI configuration
  • session-state.json stores login state and cached context tokens
  • *.json and *.sent.json store received and sent message history; unprocessed received history entries are also used for hook crash recovery
  • inbound-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 replays unprocessed received entries from history.

Console Vibe

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]

Build From Source

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=true

Target framework: .NET 10.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages