The bridge exposes a small HTTP surface and a token-protected WebSocket protocol.
GET /healthz
{ "ok": true, "name": "codex-remote-control", "version": "0.1.0" }GET /v1/sessions
{ "sessions": [] }Clients connect with the bridge token either in the query string or x-bridge-token header:
ws://HOST:PORT/?token=TOKEN
The first server message is a hello payload:
{
"type": "hello",
"ok": true,
"payload": {
"name": "codex-remote-control",
"version": "0.1.0",
"server_time": "2026-05-24T00:00:00.000Z"
}
}Client requests use:
{
"id": "request-id",
"type": "session.list",
"payload": {}
}Successful responses use:
{
"type": "response",
"id": "request-id",
"ok": true,
"payload": {}
}Errors use:
{
"type": "error",
"id": "request-id",
"ok": false,
"error": {
"code": "unknown_message",
"message": "unknown message type: example"
}
}Backend notifications are broadcast as:
{
"type": "event",
"event": "turn/started",
"session_id": "thread-id",
"thread_id": "thread-id",
"turn_id": "turn-id",
"payload": {}
}| Type | Purpose |
|---|---|
ping |
Liveness check |
model.list |
List Codex models |
session.list |
List known sessions and backend threads |
session.start |
Start a Codex thread |
session.resume |
Resume an existing thread |
session.update |
Update local session approval, permission, or sandbox settings |
session.content |
Fetch an authoritative full session snapshot |
session.sync |
Fetch changed turn snapshots since a sequence cursor |
turn.send |
Start a new turn |
turn.steer |
Send additional text to an active turn |
turn.interrupt |
Interrupt a turn |
approval.response |
Resolve a pending approval request |
file.read |
Read a file relative to the session workspace or by absolute path |
session.content returns:
{
"session_id": "SESSION_ID",
"thread_id": "THREAD_ID",
"last_seq": 123,
"session": {},
"entries": [],
"active_turns": [],
"pending_approvals": []
}The Android client treats this as the source of truth for history.
session.sync request:
{
"id": "sync-1",
"type": "session.sync",
"payload": {
"session_id": "SESSION_ID",
"since_seq": 123,
"incremental": true
}
}session.sync response:
{
"session_id": "SESSION_ID",
"thread_id": "THREAD_ID",
"last_seq": 130,
"entries": [],
"active_turns": [],
"pending_approvals": [],
"changed_turn_ids": [],
"needs_full_sync": false,
"fallback_reason": ""
}See Session Incremental Sync for merge rules.
file.read request:
{
"id": "file-1",
"type": "file.read",
"payload": {
"session_id": "SESSION_ID",
"path": "src/index.mjs",
"max_bytes": 65536
}
}The response payload contains:
{
"session_id": "SESSION_ID",
"path": "src/index.mjs",
"resolved_path": "/workspace/src/index.mjs",
"content": "...",
"truncated": false,
"bytes": 1234
}Relative paths are resolved from the session cwd. Absolute paths are read directly.
The bridge forwards Codex method names in the event field. Common events include:
thread/startedturn/starteditem/agentMessage/deltaitem/completeditem/commandExecution/requestApprovalitem/fileChange/requestApprovalitem/permissions/requestApprovalserverRequest/resolvedthread/tokenUsage/updatedturn/completedsession/changed