A relay server that enables communication between Claude Code and Codex
Claude ↔ Codex MCP Relay (with logs + web UI)
This runs a single Python MCP server that both Claude Code and Codex (VS Code chat / CLI) can connect to.
It provides:
- MCP tools:
post_message,fetch_messages,list_channels - Rotating log files (tool usage + channel message archive)
- A tiny web UI that renders conversations, highlights fenced code blocks, and can post messages
1) Setup
Requirements
- Python 3.10+
pip
Install
python -m venv .venv
source .venv/bin/activate # (Windows: .venv\Scripts\activate)
pip install -r requirements.txt
2) Run the server
python claude_codex.py
This reads host/port from config.json (or env vars, or defaults to 127.0.0.1:8010).
Alternatively, specify host/port directly:
uvicorn claude_codex:app --host 127.0.0.1 --port 8010
Open:
- Web UI: http://127.0.0.1:8010/
- MCP endpoint: http://127.0.0.1:8010/mcp
Logs:
log/claude_codex.log(rotated, defaults: 25MB × 10 backups)log/channel_messages.log(rotated, defaults: 25MB × 10 backups)
3) Configuration
Configuration is loaded from config.json (if present), then environment variables, then defaults.
Option A: config.json (recommended)
Create a config.json in the project root:
{
"host": "127.0.0.1",
"port": 8010,
"log_path": "log/claude_codex.log",
"log_max_mb": 25,
"log_backup_count": 10,
"channel_log_path": "log/channel_messages.log",
"channel_log_max_mb": 25,
"channel_log_backup_count": 10,
"channels": ["proj-x", "codex", "claude"],
"allowed_hosts": []
}
Option B: Environment variables
| Variable | Default | Meaning |
|---|---|---|
CLAUDE_CODEX_HOST |
127.0.0.1 |
Server host |
CLAUDE_CODEX_PORT |
8010 |
Server port |
CLAUDE_CODEX_LOG_PATH |
log/claude_codex.log |
Log file path |
CLAUDE_CODEX_LOG_MAX_MB |
25 |
Rotate after N MB |
CLAUDE_CODEX_LOG_BACKUP_COUNT |
10 |
Keep N backups |
CLAUDE_CODEX_CHANNEL_LOG_PATH |
log/channel_messages.log |
Channel message archive log path |
CLAUDE_CODEX_CHANNEL_LOG_MAX_MB |
25 |
Rotate channel log after N MB |
CLAUDE_CODEX_CHANNEL_LOG_BACKUP_COUNT |
10 |
Keep N channel log backups |
CLAUDE_CODEX_CHANNELS |
proj-x,codex,claude |
Seed list of channels |
CLAUDE_CODEX_ALLOWED_HOSTS |
(empty) | Extra hosts for MCP DNS-rebinding protection (comma-separated) |
Legacy compatibility: log_max_bytes / channel_log_max_bytes (and env ..._MAX_BYTES) are still accepted.
Example:
CLAUDE_CODEX_LOG_PATH=/tmp/relay.log uvicorn claude_codex:app --host 127.0.0.1 --port 8010
LAN / remote access
By default the MCP endpoint only accepts requests with Host: localhost or Host: 127.0.0.1 (DNS-rebinding protection). To allow connections from other machines on the network, add their IPs to allowed_hosts:
config.json:
{
"host": "0.0.0.0",
"allowed_hosts": ["192.168.2.3"]
}
Or via env vars:
CLAUDE_CODEX_HOST=0.0.0.0 CLAUDE_CODEX_ALLOWED_HOSTS=192.168.2.3 python claude_codex.py
Port wildcards are added automatically — 192.168.2.3 becomes 192.168.2.3:*. You can also specify an explicit host:port pattern like 192.168.2.3:8010.
4) Configure Claude Code + Codex
See:
docs/claude.mddocs/codex.md
5) Suggested workflow
Use a shared channel like proj-x so both agents read/write the same thread.
Claude makes changes, then posts a review packet:
- summary
- unified diff (in a ```diff fenced block)
- questions/focus
Codex fetches, reviews, then posts feedback:
- verdict
- major/minor issues
- tests to add/run
Claude applies fixes and posts an updated packet.
6) Polling script
scripts/review-poll.sh is a lightweight bash poller that watches a channel for new messages. It uses curl and jq to hit the /api/messages endpoint and prints one-line summaries of any new messages since the last poll.
Required env vars:
| Variable | Purpose |
|---|---|
BASE_URL |
Server URL, e.g. http://127.0.0.1:8010 |
LASTFILE |
Path to a file that persists the last-seen message ID |
Optional env vars:
| Variable | Default | Purpose |
|---|---|---|
TARGET |
propiese |
Channel to poll |
INTERVAL |
20 |
Seconds between polls |
WATCH_SENDER |
claude |
Only show messages from this sender (ignores own messages) |
Example:
BASE_URL=http://127.0.0.1:8010 LASTFILE=/tmp/last_id TARGET=proj-x INTERVAL=10 bash scripts/review-poll.sh
7) Auto-polling: making Codex check for messages
Codex won't poll on its own — it only acts when prompted. Options A–C below require a human in the loop to relay messages to Codex. Only Option D is fully automated.
Option A: Codex custom instructions (requires human)
Add to .github/copilot-instructions.md or your VS Code Copilot instructions:
After completing any task, call the fetch_messages MCP tool on the "proj-x" chann
Tools (3)
post_messagePosts a message to a specified channel.fetch_messagesFetches messages from a specified channel.list_channelsLists all available messaging channels.Environment Variables
CLAUDE_CODEX_HOSTServer hostCLAUDE_CODEX_PORTServer portCLAUDE_CODEX_CHANNELSSeed list of channelsConfiguration
{"host": "127.0.0.1", "port": 8010, "channels": ["proj-x", "codex", "claude"]}