This page documents the CLI entry point architecture in the Codex binary, specifically how the codex executable acts as a multitool dispatcher that routes invocations to different execution modes (TUI, Exec, App Server, etc.) based on command-line arguments and binary name. The dispatch mechanism uses a clap-based parser with subcommand routing and an arg0 dispatch system for specialized binary invocations.
For details on the TUI mode itself, see 4.1. For Exec mode implementation, see 4.2. For App Server protocol handling, see 4.5. This page focuses solely on the routing layer that selects which mode to invoke.
The codex binary uses a single MultitoolCli parser that defines the top-level command structure. When no subcommand is provided, the CLI defaults to interactive TUI mode. The parser structure is defined in codex-rs/cli/src/main.rs55-79
Diagram: MultitoolCli Structure and Field Composition
Sources: codex-rs/cli/src/main.rs55-79 codex-rs/cli/src/main.rs81-146
The #[clap(subcommand_negates_reqs = true)] attribute on MultitoolCli means that when a subcommand is present, top-level interactive arguments are not validated, allowing different argument requirements per mode.
The MultitoolCli struct uses clap's subcommand_negates_reqs = true attribute, which means that when a subcommand is present, the top-level interactive arguments (like --prompt, --model) are ignored. This allows the same binary to have different argument requirements depending on invocation mode.
The following table maps each subcommand to its implementation crate and primary use case:
| Subcommand | Struct | Crate | Purpose |
|---|---|---|---|
| (none) | TuiCli | codex-tui | Interactive terminal UI (default mode) |
exec | ExecCli | codex-exec | Headless, non-interactive execution |
review | ReviewArgs | codex-exec | Code review mode (delegates to exec) |
login | LoginCommand | codex-login | Authenticate with ChatGPT or API key |
logout | LogoutCommand | codex-login | Remove stored credentials |
mcp | McpCli | codex-rmcp-client | Manage external MCP servers |
mcp-server | (unit) | codex-mcp-server | Run Codex as an MCP server (stdio) |
app-server | AppServerCommand | codex-app-server | JSON-RPC 2.0 server for IDE integration |
app | AppCommand | codex-cli | Launch Codex desktop app (macOS only) |
apply | ApplyCommand | codex-chatgpt | Apply agent-generated diffs to working tree |
resume | ResumeCommand | codex-tui | Resume a previous session (TUI picker) |
fork | ForkCommand | codex-tui | Fork a previous session |
sandbox | SandboxArgs | codex-cli | Test sandbox execution directly |
completion | CompletionCommand | codex-cli | Generate shell completion scripts |
features | FeaturesCli | codex-cli | Inspect feature flags |
cloud | CloudTasksCli | codex-cloud-tasks | Browse and apply Codex Cloud tasks |
debug | DebugCommand | codex-cli | Debugging utilities (app-server, etc.) |
execpolicy | ExecpolicyCommand | codex-execpolicy | Execpolicy validation tools (hidden) |
responses-api-proxy | ResponsesApiProxyArgs | codex-responses-api-proxy | Internal responses API proxy (hidden) |
stdio-to-uds | StdioToUdsCommand | codex-stdio-to-uds | Relay stdio to Unix domain socket (hidden) |
Sources: codex-rs/cli/src/main.rs81-146
The main function orchestrates the dispatch logic. The entry point uses #[tokio::main] to provide async runtime support for all modes. The high-level flow:
Diagram: Main Function Dispatch Flow
Sources: codex-rs/cli/src/main.rs510-925 codex-rs/arg0/src/lib.rs
Arg0 dispatch (codex-rs/cli/src/main.rs510-530): arg0_dispatch_or_else() checks the binary name (std::env::args().next()) before parsing CLI args. If it matches a specialized pattern, the appropriate handler runs immediately and exits.
MultitoolCli parsing (codex-rs/cli/src/main.rs599): If not arg0-dispatched, MultitoolCli::parse() uses clap to parse all arguments and flags.
Feature toggle expansion (codex-rs/cli/src/main.rs602-608): The FeatureToggles::to_overrides() method converts --enable FEATURE and --disable FEATURE flags into -c features.FEATURE=true/false format, which are then merged into the main config overrides vector.
Subcommand match (codex-rs/cli/src/main.rs649-925): A large match statement on cli.subcommand routes execution to the appropriate handler function or crate entry point.
The arg0 dispatch mechanism allows the same binary to be invoked under different names to trigger specialized behavior. This is implemented in the codex-arg0 crate via the arg0_dispatch_or_else function in codex-rs/arg0/src/lib.rs1-79
The following table lists recognized arg0 names and their handlers:
| Binary Name Pattern | Handler | Purpose |
|---|---|---|
*-apply-patch | codex_apply_patch::main() | Apply patches from stdin to filesystem |
*-linux-sandbox | codex_linux_sandbox::main() | Run commands under Landlock+seccomp |
The pattern matching is prefix-based: any binary name ending with -apply-patch or -linux-sandbox triggers the respective handler. This allows platform-specific binaries like codex-x86_64-unknown-linux-musl-linux-sandbox to work correctly.
Sources: codex-rs/arg0/src/lib.rs1-79 codex-rs/cli/src/main.rs510-530
The arg0 handlers are terminal: they call std::process::exit() directly and never return control to the main CLI dispatcher. This ensures that when invoked as a specialized binary, the tool behaves exactly like a standalone utility with no CLI parsing overhead.
When no subcommand is provided, the CLI defaults to TUI mode. The TuiCli struct is flattened into MultitoolCli, so all TUI-specific arguments (like --prompt, --model, --resume-picker) are available at the top level:
The dispatch logic for TUI mode is in codex-rs/cli/src/main.rs815-829 When cli.subcommand is None, the code path invokes codex_tui::run_main() with the interactive arguments.
The resume and fork subcommands are specialized TUI invocations rather than separate modes. They set flags (resume_picker, fork_picker, resume_last, fork_last) and then launch TUI:
Sources: codex-rs/cli/src/main.rs830-884
This design keeps the TUI as the single source of truth for interactive session management, avoiding duplication of picker logic.
All modes share the CliConfigOverrides struct from codex-utils-cli, which provides the -c key=value syntax for overriding config.toml values at runtime. This is parsed once in codex-rs/cli/src/main.rs602-608 and forwarded to both TUI and Exec modes.
Example:
The FeatureToggles struct (defined in codex-rs/cli/src/main.rs478-510) provides --enable FEATURE and --disable FEATURE flags as syntactic sugar for -c features.FEATURE=true/false. The struct validates feature names against known features using is_known_feature_key() from codex_core::features before expansion.
Diagram: Feature Toggle Processing Pipeline
Sources: codex-rs/cli/src/main.rs478-510 codex-rs/cli/src/main.rs602-608
The validation step ensures users don't accidentally enable non-existent features, returning an error if an unknown feature name is provided.
The CLI resolves the path to the codex-linux-sandbox binary and passes it to both TUI and Exec modes via ConfigOverrides. This enables sandboxed command execution on Linux platforms. The resolution logic is in codex-rs/cli/src/main.rs531-572
Sources: codex-rs/cli/src/main.rs531-572 codex-rs/cli/src/main.rs820-821
After TUI or Exec mode completes, control returns to the main function, which calls handle_app_exit() to process the exit status. This function (defined in codex-rs/cli/src/main.rs411-429) performs three tasks:
ExitReason::Fatal, print the error and exit with code 1.format_exit_messages().UpdateAction is present (e.g., user requested update from TUI), run the update command (Homebrew, npm, etc.).Diagram: Exit Handling Flow
Sources: codex-rs/cli/src/main.rs379-408 codex-rs/cli/src/main.rs411-429 codex-rs/cli/src/main.rs432-463
The format_exit_messages() function (defined in codex-rs/cli/src/main.rs379-408) builds the token usage display using FinalOutput::from(token_usage) and generates a resume command hint via codex_core::util::resume_command(). Color formatting is applied when terminal color support is detected via supports_color::on(Stream::Stdout).
The update mechanism is part of the TUI's self-update flow (see 4.1 for details). The CLI layer simply executes the command generated by TUI logic.
The CLI entry point layer provides:
codex executable with subcommand-based mode selection-c and feature flags are forwarded to all modesThis architecture allows the same binary to serve as an interactive CLI, headless automation tool, JSON-RPC server, MCP server, and various utility commands, while keeping mode-specific logic cleanly separated in dedicated crates.
Sources: codex-rs/cli/src/main.rs510-925 codex-rs/arg0/src/lib.rs1-79 codex-rs/tui/src/lib.rs129-431 codex-rs/exec/src/lib.rs91-597
Refresh this wiki