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
+5
View File
@@ -339,6 +339,9 @@ Object.assign(CodemanApp.prototype, {
claudeModeSelect.onchange = () => {
allowedToolsRow.style.display = claudeModeSelect.value === 'allowedTools' ? '' : 'none';
};
// Codex CLI settings
document.getElementById('appSettingsCodexDangerouslyBypassApprovals').checked =
settings.codexDangerouslyBypassApprovals ?? false;
// Claude Permissions settings
document.getElementById('appSettingsAgentTeams').checked = settings.agentTeamsEnabled ?? false;
document.getElementById('appSettingsOpusContext1m').checked = settings.opusContext1mEnabled ?? false;
@@ -1340,6 +1343,8 @@ Object.assign(CodemanApp.prototype, {
// Claude CLI settings
claudeMode: document.getElementById('appSettingsClaudeMode').value,
allowedTools: document.getElementById('appSettingsAllowedTools').value.trim(),
// Codex CLI settings
codexDangerouslyBypassApprovals: document.getElementById('appSettingsCodexDangerouslyBypassApprovals').checked,
// Claude Permissions settings
agentTeamsEnabled: document.getElementById('appSettingsAgentTeams').checked,
opusContext1mEnabled: document.getElementById('appSettingsOpusContext1m').checked,