RelayHub is a local, extensible message gateway. Channel adapters, routing, plugins, context, Web UI, and IPC are separate so new channels can be added without changing the core.
The included WeChat iLink adapter lives in channels/wechat/. Each account is
bound to the first user ID that sends a message; other users are rejected to
match the WeChat one-user limitation.
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python main.pyCopy config.example.json to config.json, then run python main.py. Open
http://127.0.0.1:8080, scan to add an account, then configure plugins.
Runtime configuration, account tokens, and plugin secrets are ignored by Git;
the *.example.json files are safe templates.
python cli.py ping
python cli.py accounts
python cli.py send <user_id> "hello" --account <account_id>
python cli.py messages --account <account_id>
python cli.py subscribe --account <account_id>Send these commands through a connected channel:
/help List commands and loaded plugins
/help chat Show one plugin's usage and capabilities
/clear Clear conversation context, pending files, and focus mode
/focus chat Send subsequent messages directly to the chat plugin
/exit Leave focus mode
When an image or file arrives, RelayHub downloads it into the local ignored
data/attachments/ directory and confirms receipt. Send a compatible plugin
command next, such as /chat analyze this image or /claude inspect this file.
GET /api/plugins lists plugins, schemas, and masked secrets.
POST /api/plugins/{name}/config accepts schema keys and saves atomically.
Omitting a password field retains its current value. Use
POST /api/plugins/{name}/toggle to enable or disable a plugin.
POST /api/send accepts { "account": "acc_x", "to": "user_id", "text": "...", "context_token": "..." }.
The default Unix socket is /tmp/relayhub.sock and uses newline-delimited
JSON commands: ping, accounts, send, sendfile, messages, and
subscribe.
The /claude plugin uses the Claude Agent SDK to run Claude Code with local
authentication and project permissions. Install claude-agent-sdk, configure
an optional working directory, and send /claude <task>. It does not apply a
system prompt.
Implement a provider adapter in channels/<name>/ that converts provider
events into core.models.InboundMessage and exposes send/reply operations.
Keep credentials, polling, and provider protocol inside that adapter.