# Architecture ```text 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.