An experimental bridge project for sending messages into an existing Codex session and reading the reply back out.
This project is intentionally separate from OpenClaw and IncenseClaw.
- Continue an existing Codex thread by session id
- Expose a small local HTTP API for sending messages into that thread
- Optionally long-poll a Weixin account and relay inbound text to Codex
- Send Codex's final reply back to Weixin
For a "true bridge" MVP, the cleanest entry point on this machine is not the desktop UI itself. It is the Codex CLI's ability to continue an existing session:
codex exec resume <session-id> <prompt>
That gives us a programmatic way to:
- keep using the current thread context
- inject a new message
- capture the assistant's final reply
- Node.js 22+
- A local
codexCLI install - A local Codex desktop/CLI environment with resumable sessions
- Optional: an OpenClaw Weixin login if you want relay mode
- Clone the repo
- Copy
bridge.config.json.exampletobridge.config.json - Fill in your own local values
- Run the CLI or HTTP server
git clone https://github.com/cyberpinkman/codex-wechat-bridge.git
cd codex-wechat-bridge
cp bridge.config.json.example bridge.config.jsonUseful commands:
cd /path/to/codex-wechat-bridge
npm run latest
npm run locate -- --session-id YOUR-CODEX-SESSION-ID
npm run send -- --session-id YOUR-CODEX-SESSION-ID --message "reply with hello only"Structured JSON output:
node ./src/index.mjs send \
--session-id YOUR-CODEX-SESSION-ID \
--message "reply with hello only" \
--jsonStart the local bridge:
cd /path/to/codex-wechat-bridge
npm run serveThen test it:
curl http://127.0.0.1:4318/healthcurl -X POST http://127.0.0.1:4318/bridge/send \
-H 'authorization: Bearer SET-A-LONG-RANDOM-TOKEN' \
-H 'content-type: application/json' \
-d '{"message":"reply with hello only"}'Example config fields:
{
"sessionId": "YOUR-CODEX-SESSION-ID",
"codexHome": "/absolute/path/to/.codex",
"cwd": "/absolute/path/for/codex/workdir",
"host": "127.0.0.1",
"port": 4318,
"http": {
"authToken": "SET-A-LONG-RANDOM-TOKEN",
"allowSessionOverride": false,
"maxBodyBytes": 16384
},
"codex": {
"timeoutMs": 120000,
"maxQueueDepth": 4,
"dangerousBypass": false
},
"weixin": {
"enabled": true,
"accountId": "YOUR-WEIXIN-ACCOUNT-ID",
"syncFile": "/absolute/path/to/codex-wechat-bridge/tmp/weixin-sync.json",
"pollTimeoutMs": 35000,
"stateDir": "/absolute/path/to/.openclaw",
"allowOwner": true,
"allowFrom": []
}
}Field meanings:
sessionId: Codex thread id to resume intocodexHome: local Codex home directory, usually~/.codexcwd: working directory used bycodex exec resumehost: HTTP bind host for this bridgeport: HTTP bind port for this bridgehttp.authToken: required token forPOST /bridge/sendhttp.allowSessionOverride: whenfalse, callers cannot choose a different session idhttp.maxBodyBytes: maximum accepted HTTP request body sizecodex.timeoutMs: max time allowed for onecodex exec resumecallcodex.maxQueueDepth: max queued bridge requests before rejectingcodex.dangerousBypass: whentrue, re-enable--dangerously-bypass-approvals-and-sandboxweixin.enabled: enable the built-in Weixin relay loopweixin.accountId: local Weixin account id created by the plugin login flowweixin.syncFile: local file used by this project to store its own Weixin polling cursorweixin.pollTimeoutMs: long-poll timeout forgetupdatesweixin.stateDir: local OpenClaw state directory, usually~/.openclawweixin.allowOwner: whentrue, only the linked owner account is allowed by defaultweixin.allowFrom: optional extra Weixin user ids allowed to control the relay
Use:
cd /path/to/codex-wechat-bridge
npm run latestOr inspect:
cat ~/.codex/session_index.jsonlAfter logging in with the OpenClaw Weixin plugin, inspect:
cat ~/.openclaw/openclaw-weixin/accounts.jsonThat file contains the account ids you can use as weixin.accountId.
cd /path/to/codex-wechat-bridge
npm run serveHealth check:
curl http://127.0.0.1:4318/healthSend a message into the configured Codex thread:
curl -X POST http://127.0.0.1:4318/bridge/send \
-H 'authorization: Bearer SET-A-LONG-RANDOM-TOKEN' \
-H 'content-type: application/json' \
-d '{"message":"reply with hello only"}'If bridge.config.json contains a weixin.enabled: true section, npm run serve will also:
- load the saved Weixin account token from
<OPENCLAW_STATE_DIR>/openclaw-weixin/accounts/<accountId>.json - long-poll
getupdates - forward inbound text to the configured Codex session
- send the final Codex reply back through
sendmessage
Important:
- Do not let OpenClaw's own Weixin monitor and this bridge consume the same account at the same time.
- For the cleanest test, stop the OpenClaw gateway first, then run this bridge.
- This relay currently focuses on text messages for the MVP.
- By default, only the linked owner account is allowed to control the relay unless you expand
weixin.allowFrom.
- The bridge does not store your Weixin token in the repo.
- Your real
bridge.config.jsonis intentionally ignored by git. - Your local machine paths, account ids, and session ids must be supplied by each user.
- The HTTP bridge expects an auth token for message injection.
- Cross-thread HTTP overrides are disabled by default.
- If you want to preserve the previous "Codex can execute without approvals" behavior on your own machine, set
codex.dangerousBypasstotruein your ignored localbridge.config.json.
- You may see local Codex warnings depending on your machine's install state.
- The bridge currently relies on the local
codex exec resumebehavior and transcript discovery. - The Weixin relay is intentionally minimal and not production-hardened.
- If you need Codex to execute commands without approvals, you must explicitly opt in via
codex.dangerousBypass.
See docs/architecture.md.