CodeVetter · Repo Unpack · Behavior traces
openai/codex
Three flows dominate. Startup parses CLI args, loads config and auth, builds a Codex session, and either enters the TUI event loop or the exec one-shot loop. A primary turn submits user input, streams a model response, dispatches tool calls under approval and sandbox, and records rollout items until `TurnComplete`. Persistence is continuous during the turn (rollout appends) and finalized on shutdown or resume. App-server clients follow the same core path after a JSON-RPC translation step.
- Process startup: `cli::main` → `arg0_dispatch_or_else` (so sandbox helpers can re-exec under a different argv0) → `MultitoolCli::parse` → match on `Subcommand`. For the default path, `tui_main` loads config, builds `TuiConfig`, and calls `codex_tui::run_main` → `App::run`.
- Exec one-shot: `codex exec` → `exec::run_main` builds a `Codex` with the prompt as the initial `Op::UserTurn`, reads the event channel until `TurnComplete` or `Error`, prints human text or JSONL, and exits non-zero on error. `--output-schema` validates the final message.
- Tool call with approval: model emits a function call → router looks up the handler → if policy is `on-request` and execpolicy does not pre-approve, core emits `ExecApprovalRequest` → TUI modal or exec auto-decision returns `Op::ExecApproval` → sandbox spawn → `ExecCommandEnd` → function output appended → model continues.
- SDK run: `Codex` constructor starts `codex app-server` with `--stdio` → `initialize` JSON-RPC → `startThread` calls `thread/start` → `run` calls `turn/start` and demultiplexes notifications into typed `ThreadEvent`s until `turn/completed`.
- Login flow: `codex login` → login crate starts device-code or localhost callback → tokens written via `AuthManager` to `$CODEX_HOME/auth.json` with mode `chatgpt` or `apikey`. Later `ModelClient` calls `AuthManager::auth()` on each request and refreshes when the access token is near expiry.