OMP Codex Bridge — Agent & Developer Reference #
This document covers the internal architecture, protocol mechanics, backend integration paths, and development workflows for @oh-my-pi/codex-bridge.
System Overview #
@oh-my-pi/codex-bridge is an adapter that speaks the Codex CLI and app-server JSON-RPC / WebSocket protocols on the frontend while driving Oh My Pi on the backend.
+---------------------+ +--------------------------------------+
| ChatGPT Desktop | --(SSH/stdio)-->| codex shim (bin/codex.mjs) |
| or Remote Control | --(Unix sock)->| | |
+---------------------+ | v |
| AppServer (src/app-server.mjs) |
| | |
| +--> Backend (src/backend/omp.mjs)|
| | |
+-----------|--------------------------+
v
+-----------------------+
| Oh My Pi (OMP) |
| (SDK / RPC Process) |
+-----------------------+
Backend Modes #
Configured via backend in config.json or OMP_CODEX_BACKEND (auto, sdk, rpc, prime, both, mock):
-
auto(default): Tries direct SDK import first; if unavailable, falls back to theompCLI in RPC mode. -
sdk: Imports the OMP coding-agent module directly in-process. Resolves in order:process.env.OMP_CODEX_OMP_MODULE(explicit path or package name)@oh-my-pi/pi-coding-agent@oh-my-pi/coding-agent@oh-my-pi/agent- Local Bun workspace paths (
packages/coding-agent/src/index.ts)
-
rpc: Spawnsompas a subprocess with JSONL RPC communication (omp --mode rpc-ui). Override binary path withOMP_CODEX_OMP_BINand args withOMP_CODEX_OMP_RPC_ARGS. -
prime: Spawns Prime (prime-agent, Prime 0.8.0 or newer) as a subprocess speaking Prime's own JSONL RPC protocol (--mode rpc). Reached through a dynamic import ofsrc/backend/prime.mjs, soautonever loads it and a machine without Prime installed starts exactly as before. Binary resolution order:primeExecutablepassed programmatically or set undersessionOptionsinconfig.jsonOMP_CODEX_PRIME_BIN~/.local/bin,~/.bun/bin,~/.nix-profile/bin,/opt/homebrew/bin,/usr/local/binprime-agentonPATH
Extra flags come from
OMP_CODEX_PRIME_RPC_ARGS(JSON array) and are appended — unlikeOMP_CODEX_OMP_RPC_ARGS, they never replace the base argument vector, so--resume/--model/--cwdsurvive.Prime publishes its own short model catalog, so the factory declares
modelCatalogPolicy = "all"andmodel/listexempts its rows from the OMP featured-model filter (see below). Rows carry a bareid(gpt-5.6-luna) plus a provider-qualifiedselector(openai-codex/gpt-5.6-luna). Prime's own dialogs (extension_ui_request) map onto the Codex user-input request and are answered withextension_ui_response.Prime enforces no approvals and no sandbox. It has no Codex/OMP command or file approval primitive, so
defaultApprovalPolicyis not applied, no approval round-trip is sent to the client, and shell commands and file writes run with the daemon's own privileges. Use it only where unattended edits are acceptable. -
both: Loads the normal OMPautobackend and Prime together. It advertises a synthetic custom provider throughconfig/read, allowing Desktop/iOS to accept unique model IDs such asgpt-5.6-luna-via-ompandgpt-5.6-luna-via-prime-agent. Display names append(OMP)or(Prime Agent). Selecting the qualified ID chooses the backend for a new thread. Persistedbackend.kindchooses the backend when a thread resumes; an existing thread cannot switch agent families through a later model change. LocalmodelCatalogpolicy controls filtering and ordering without changing the packaged catalogs. -
mock: In-memory deterministic backend for unit tests, offline development, and verification suites.
Model Catalog Visibility #
model/list hides every model outside FEATURED_MODEL_IDS (src/backend/omp.mjs), because OMP's catalog runs to hundreds of rows and the Desktop picker becomes unusable otherwise. A backend whose catalog is already short would lose all of its rows to that filter, so it opts out explicitly:
- Factory-level:
modelCatalogPolicy = "all"on the backend factory (instance or static).createBackendFactorydefaults this forprimewhen the factory does not set it itself. - Row-level:
catalogPassthrough: trueon an individual model row.
Neither is inferred from a provider name or id prefix. A row that sets hidden: true stays hidden regardless of policy.
modelCatalog in bridge config is an optional local policy layer:
include/exclude:*glob patterns over canonical model IDs.excludeProviders: exact provider IDs to remove.backendOrder: backend tags such as["omp", "prime-agent"].order: ordered*glob patterns applied within each backend group.
When include is present, matching rows bypass FEATURED_MODEL_IDS; omitted
policy retains the existing backend-specific visibility and ordering.
Transport Modes #
- JSONL stdio (
codex app-server): Standard entry point invoked by SSH connections from ChatGPT Desktop. - Unix Domain Socket (
codex remote-control start): Listens on~/.omp/codex-bridge/run/app-server.sock(mode0600). - WebSocket Proxy (
codex app-server proxy): Bridges stdio to the running daemon's Unix socket. - Loopback TCP WebSocket: Available for local development. Binding to non-loopback addresses requires
OMP_CODEX_ALLOW_PUBLIC_LISTEN=1.
Environment Variables #
| Variable | Purpose | Default |
|---|---|---|
OMP_CODEX_BACKEND |
auto, sdk, rpc, prime, both, or mock |
auto |
OMP_CODEX_OMP_MODULE |
Explicit OMP SDK module or file URL | autodetected |
OMP_CODEX_OMP_BIN |
Path to omp executable for RPC mode |
autodetected via PATH |
OMP_CODEX_OMP_RPC_ARGS |
JSON array of arguments for OMP RPC process | ["--mode","rpc-ui"] |
OMP_CODEX_PRIME_BIN |
Path to prime-agent executable for prime backend |
autodetected via PATH |
OMP_CODEX_PRIME_RPC_ARGS |
JSON array of extra flags appended to Prime's RPC argv | [] |
OMP_CODEX_CONFIG |
Path to bridge config file | ~/.omp/codex-bridge/config.json |
OMP_CODEX_STATE_FILE |
Persistent state JSON path | ~/.omp/codex-bridge/state.json |
OMP_CODEX_DEFAULT_MODEL |
Default model identifier | gemini-3.7-flash |
OMP_CODEX_MODEL_ALIASES |
JSON string of extra model aliases | {} |
OMP_CODEX_RUNTIME_DIR |
Directory for daemon sockets/pids/logs | ~/.omp/codex-bridge/run |
OMP_CODEX_SOCKET |
Custom Unix domain socket path | <runtime>/app-server.sock |
OMP_CODEX_COMPAT_VERSION |
Version reported by codex --version |
0.145.0 |
OMP_CODEX_DEBUG |
Enable verbose diagnostics to stderr | disabled |
OMP_CODEX_QUIET |
Suppress non-error logs | disabled |
OMP_CODEX_ALLOW_FS_OUTSIDE_WORKSPACE |
Disable workspace boundary checks | disabled (unsafe) |
OMP_CODEX_ALLOW_PUBLIC_LISTEN |
Permit non-loopback TCP listeners | disabled (unsafe) |
State & Persistence #
- State file:
~/.omp/codex-bridge/state.json(atomic writes, mode0600). - Tracks thread IDs, turn history, approval cache ("accept for session"), model overrides, and associated OMP session IDs for resumption.
- Direct filesystem requests (
fs/readFile,fs/writeFile, etc.) are canonicalized and guarded against path traversal outside the active workspace root.
Workspace & Worktree Isolation (Jujutsu & Git) #
The bridge provides automatic VCS workspace isolation for threads and forks:
- Automatic Detection (
src/workspace.mjs):- Checks for a Jujutsu (
jj) repository first viajj root. - If not found, checks for a Git repository via
git rev-parse --show-toplevel. - Falls back to unisolated direct
cwdif outside a repository.
- Checks for a Jujutsu (
- Jujutsu Workspaces (
jj workspace add):- Preferred when
jjis detected. - Creates an independent workspace without index locking, stash conflicts, or branch collision.
- Snapshots all agent mutations automatically in the
jjoperation log. - Automatically forgotten (
jj workspace forget) and cleaned up on thread deletion.
- Preferred when
- Git Worktree Fallback (
git worktree add):- Used in standard Git repositories when
jjis not present. - Creates a detached HEAD worktree and removes it on thread deletion.
- Used in standard Git repositories when
- Configuration:
workspaceIsolationinconfig.jsonorOMP_CODEX_WORKSPACE_ISOLATION:"auto"(default),"jj","git", or"none".- Custom isolation directory via
OMP_CODEX_WORKSPACES_DIR(defaults to~/.omp/codex-bridge/workspaces).
Protocol Tracing & Replay #
To record live protocol exchanges from the real Codex binary or ChatGPT desktop:
CODEX_REAL=/path/to/real/codex node ./scripts/codex-trace-wrapper.mjs app-server
Recorded traces are written to ~/.omp/codex-bridge/traces/ and can be inspected or replayed for debugging.
Verification & Testing #
Run tests and release checks from the repo root:
# Unit and integration test suite (15 tests)
npm test
# Lint/syntax check all JS modules
node ./scripts/check.mjs
# Full isolated release verification (clean-copy + daemon lifecycle)
./scripts/verify-release.sh
# Install or refresh local shim in ~/.local/bin/codex
./scripts/install-local.sh "$HOME/.local"