Architecture #
ChatGPT desktop/mobile remote
│
│ SSH login shell launches `codex`
▼
@oh-my-pi/codex-bridge
├─ CLI/daemon/proxy
├─ JSONL or WebSocket transport
├─ Codex request router
├─ thread/turn/item projection store
├─ approval and input request bridge
└─ backend factory
├─ direct OMP SDK session
├─ OMP RPC process
└─ deterministic mock
│
▼
Oh My Pi models, sessions, tools, MCP, extensions
Why it is a workspace package #
A regular OMP extension cannot satisfy the initial contract: ChatGPT launches a command named codex before any OMP session or extension exists. The compatibility executable and app-server must therefore live outside the agent session. Embedding OMP after protocol initialization still preserves OMP as the real agent engine.
State model #
A Codex thread maps to one persisted OMP session. The bridge additionally stores a Codex-facing projection because ChatGPT expects stable thread, turn, and item IDs and may resume after neither the original transport nor the in-memory OMP session survives.
Only one active turn is allowed per thread. Different threads may run concurrently. Server-initiated approvals are scoped to the client connection and are cancelled when that connection or turn ends.
Event mapping #
| OMP/backend event | Codex app-server event/item |
|---|---|
| text delta | agentMessage + item/agentMessage/delta |
| thinking/reasoning delta | reasoning + reasoning delta notifications |
| bash/shell start | commandExecution |
| command output | item/commandExecution/outputDelta |
| edit/write against workspace files | fileChange + item/fileChange/patchUpdated |
| proposed/final diff | turn/diff/updated |
| OMP todo snapshot | turn/plan/updated |
| web search | webSearch |
| image inspection | imageView |
| namespaced MCP tool | mcpToolCall + progress notifications |
| other structured tool | dynamicToolCall attributed to oh-my-pi |
| terminal backend completion | turn/completed |
| abort | interrupted turn/completed |
Approval mapping #
OMP's interactive/ACP bridge is injected into the direct session. Command-like requests become item/commandExecution/requestApproval; edit-like requests become item/fileChange/requestApproval; prompts become item/tool/requestUserInput. The bridge maps accept, acceptForSession, decline, and cancel back to OMP and caches only the explicit session-wide decision.
Goal mapping #
thread/goal/get, thread/goal/set, and thread/goal/clear use the Codex v2 goal object and persist it with the bridge thread. OMP goal_updated events update the same object. Active Desktop-created goals are included as private backend context on later turns, while the visible user message remains unchanged; turn usage and elapsed time update the goal counters and can transition it to budgetLimited.
Transport model #
Stdio uses one JSON object per line. WebSocket carries one JSON object per text frame, while also accepting JSONL within a frame. app-server proxy does not parse protocol messages: it copies the raw HTTP Upgrade and WebSocket bytes between stdin/stdout and the Unix socket.