feat(codex): add Codex (OpenAI CLI) run-mode foundation

Add Codex as a first-class session mode alongside Claude/Shell/OpenCode.

- codex-cli-resolver: locate the `codex` binary and augment PATH (mirrors the
  OpenCode resolver)
- SessionMode 'codex' + CodexConfig (model, resumeSessionId, dangerouslyBypass,
  renderMode); persisted in SessionState and threaded through CreateSession/
  RespawnPane options
- schema validation: CodexConfigSchema, CODEX_ env-var prefix allowlist, mode
  enums on create/quick-start, codexDangerouslyBypassApprovals setting
- tmux launch: buildCodexCommand, setenv for OPENAI_API_KEY/CODEX_* (keeps
  secrets out of ps), truecolor COLORTERM, codex PATH resolution
- session + routes: availability check (clear install hint), config passthrough,
  tmux-required guard; Codex skips Claude-only parsers (Ralph/respawn/token)
- run-mode UI: "Run CX" selector option + dedicated Codex CLI settings tab with
  the bypass-approvals toggle; GET /api/codex/status

Scope: foundation only. Codex terminal redraw handling and xterm snapshot/replay
are intentionally excluded and tracked separately.

Verification: tsc --noEmit, eslint, prettier --check, check:frontend-syntax all
clean; full test:ci suite green (2712 passed, 0 failed); server boot smoke OK.

Co-Authored-By: Saqeb Akhter <saqeb.akhter@gmail.com>
This commit is contained in:
Aamer Akhter
2026-06-10 09:34:52 -04:00
co-authored by Saqeb Akhter
parent e1f611b8fb
commit 70378315da
13 changed files with 487 additions and 23 deletions
+16
View File
@@ -384,6 +384,9 @@
<button class="run-mode-option" data-mode="opencode" onclick="app.setRunMode('opencode')">
<span class="run-mode-dot opencode"></span>OpenCode
</button>
<button class="run-mode-option" data-mode="codex" onclick="app.setRunMode('codex')">
<span class="run-mode-dot codex"></span>Codex
</button>
<div class="run-mode-sep"></div>
<div class="run-mode-header">Recent Sessions</div>
<div class="run-mode-history" id="runModeHistory"></div>
@@ -895,6 +898,7 @@
<div class="modal-tabs">
<button class="modal-tab-btn active" data-tab="settings-display">Display</button>
<button class="modal-tab-btn" data-tab="settings-claude">Claude CLI</button>
<button class="modal-tab-btn" data-tab="settings-codex">Codex CLI</button>
<button class="modal-tab-btn" data-tab="settings-models">Models</button>
<button class="modal-tab-btn" data-tab="settings-paths">Paths</button>
<button class="modal-tab-btn" data-tab="settings-notifications">Notifications</button>
@@ -1174,6 +1178,18 @@
<span class="form-hint">Process priority (-20 to 19, higher = lower priority, default: 10)</span>
</div>
</div>
<!-- Codex CLI Tab -->
<div class="modal-tab-content hidden" id="settings-codex">
<div class="form-section-header">Codex CLI</div>
<div class="form-row form-row-switch">
<label>Bypass Approvals and Sandbox</label>
<label class="switch">
<input type="checkbox" id="appSettingsCodexDangerouslyBypassApprovals">
<span class="slider"></span>
</label>
<span class="form-hint">Start new Codex sessions with --dangerously-bypass-approvals-and-sandbox</span>
</div>
</div>
<!-- Models Tab -->
<div class="modal-tab-content hidden" id="settings-models">
<div class="form-row">