Skip to content

Codex Architecture Index

Pinned SHA: 4ab44e2c5cc54ed47e47a6729dfd8aa5a3dc2476

Codex is a Rust-based CLI and TUI application. It features a client-server architecture (though often running in the same process) where the TUI orchestrates high-level state and the core engine handles agent logic, tool execution, and sandboxing. The workspace contains 40+ crates under codex-rs/, with the major ones being core, tui, cli, protocol, config, state, exec, hooks, file-search, linux-sandbox, exec-server, shell-command, apply-patch, login, rmcp-client, mcp-server, app-server, app-server-protocol, network-proxy, keyring-store, and ansi-escape.

CratePathPurpose
clicodex-rs/cli/Main binary, clap argument parsing, subcommand dispatch
tuicodex-rs/tui/Interactive ratatui terminal UI, widgets, overlays
corecodex-rs/core/Agent engine, tool dispatch, sandboxing, MCP, skills, context management
protocolcodex-rs/protocol/Shared protocol types: Op submissions, EventMsg events, ResponseItem
configcodex-rs/config/Multi-layer TOML configuration with merge, overrides, requirements
statecodex-rs/state/SQLite state persistence, tracing log DB, session metadata
execcodex-rs/exec/Non-interactive execution engine for CI/scripting
hookscodex-rs/hooks/Event-driven hook system (AfterAgent, AfterToolUse)
file-searchcodex-rs/file-search/Fuzzy file search with nucleo + ignore
linux-sandboxcodex-rs/linux-sandbox/Linux sandboxing: bubblewrap + Landlock + seccomp
exec-servercodex-rs/exec-server/MCP server for privilege escalation and shell interception
shell-commandcodex-rs/shell-command/Tree-sitter bash parsing and command safety checking
apply-patchcodex-rs/apply-patch/Unified diff patch parsing and atomic file application
logincodex-rs/login/Device code auth, PKCE, login server
rmcp-clientcodex-rs/rmcp-client/MCP client (stdio + streamable HTTP transports)
mcp-servercodex-rs/mcp-server/Codex as an MCP server (stdio transport)
app-servercodex-rs/app-server/IDE integration server (stdio/WebSocket)
app-server-protocolcodex-rs/app-server-protocol/Typed JSON-RPC protocol for IDE integration (v1/v2)
network-proxycodex-rs/network-proxy/HTTP + SOCKS5 proxy for network sandboxing
keyring-storecodex-rs/keyring-store/Platform-independent credential storage abstraction
ansi-escapecodex-rs/ansi-escape/ANSI escape to ratatui styled text conversion
windows-sandbox-rscodex-rs/windows-sandbox-rs/Windows sandboxing (restricted token)
execpolicycodex-rs/execpolicy/Execution policy rules engine
secretscodex-rs/secrets/MCP OAuth credential storage (keyring + file fallback)
cloud-taskscodex-rs/cloud-tasks/Codex Cloud task management

1. Bootstrapping and CLI Entry (codex-rs/cli/src/main.rs)

Section titled “1. Bootstrapping and CLI Entry (codex-rs/cli/src/main.rs)”
  1. main() -> arg0_dispatch_or_else() -> cli_main().
  2. cli_main() parses subcommands using clap.
  3. If no subcommand, it calls run_interactive_tui().
  4. run_interactive_tui() performs terminal checks (refuses “dumb” terminals without TTY) and calls codex_tui::run_main().

2. TUI Orchestration (codex-rs/tui/src/lib.rs)

Section titled “2. TUI Orchestration (codex-rs/tui/src/lib.rs)”
  1. run_main():
    • Loads configuration via ConfigBuilder.
    • Initializes AuthManager.
    • Sets up tracing/logging to codex-tui.log.
    • Handles --oss provider selection if needed.
    • Calls run_ratatui_app().
  2. run_ratatui_app():
    • Initializes ratatui terminal.
    • Runs update_prompt::run_update_prompt_if_needed().
    • Runs onboarding::run_onboarding_app() for first-run trust/login.
    • Manages session selection (Resume, Fork, or StartFresh).
    • Resolves CWD, prompting the user if the session history CWD differs from current.
    • Calls App::run().

3. Application Loop and State (codex-rs/tui/src/app.rs)

Section titled “3. Application Loop and State (codex-rs/tui/src/app.rs)”
  1. App::run():
    • Multi-event loop using tokio::select!.
    • app_event_rx: Internal UI events (e.g., NewSession, InsertHistoryCell).
    • active_thread_rx: Events from the agent engine (e.g., SessionConfigured, UserMessage, ShutdownComplete).
    • tui_events: User input (Keys, Pastes, Resizes).
  2. handle_tui_event(): Processes keyboard input, manages Overlay (full-screen views), and triggers draws.
  3. handle_event(): Logic for UI commands (e.g., ForkCurrentSession calls server.fork_thread).
  4. handle_active_thread_event(): Routes agent events to the UI and handles thread lifecycle/failover.
  • transcript_cells: A Vec<Arc<dyn HistoryCell>> in App storing the conversation history.
  • HistoryCell trait: Implemented by UserHistoryCell, AgentMessageCell, SessionInfoCell, etc.
  • project_doc.rs: Hierarchical discovery of AGENTS.md files from git root down to CWD.
  • environment_context.rs: Serializes CWD, Shell, and Network state into XML tags for the LLM.

The core crate is the heart of Codex with around 191 source files implementing the agent loop, tool dispatch, sandboxing, MCP integration, skills, context management, and state persistence.

CODEX SPAWN (codex.rs)
1. Create Session (Arc<Session>)
2. Spawn submission_loop task
3. Return Codex { tx_sub, rx_event, agent_status }
SUBMISSION LOOP (codex.rs:3196)
Async channel receiver for Op enum submissions
while let Ok(sub) = rx_sub.recv().await {
match sub.op {
Op::UserInput { items, .. }
Op::UserTurn { .. }
Op::ExecApproval { .. }
Op::PatchApproval { .. }
Op::Undo, Op::Compact, Op::Review { .. }
Op::Shutdown => break
}
}
handlers::user_input_or_turn -> spawn_task (tasks/mod.rs)
Create Arc<RegularTask> (or ReviewTask, etc.)
Spawn on tokio::spawn with cancellation token
REGULAR TASK: run_turn() (tasks/regular.rs:100)
1. Create TurnContext
2. Initialize ContextManager (token budget)
3. Build prompt (user message + history)
4. Call ModelClientSession.stream() for agent response
5. Stream ResponseEvent::Delta (reasoning/content chunks)
6. For each ResponseItem (text/toolcall), emit events
7. TOOL DISPATCH LOOP
8. Final turn event (TurnComplete or Error)

Codex (codex.rs):

pub struct Codex {
pub tx_sub: Sender<Submission>, // Input: operations
pub rx_event: Receiver<Event>, // Output: protocol events
pub agent_status: watch::Receiver<AgentStatus>,
}

Session (codex.rs):

pub struct Session {
pub conversation_id: ThreadId,
pub services: Arc<SessionServices>,
pub state: Arc<Mutex<SessionState>>,
tx_event: Sender<Event>,
agent_status: watch::Sender<AgentStatus>,
}

SessionServices (state/service.rs):

pub struct SessionServices {
pub auth_manager: Arc<AuthManager>,
pub models_manager: Arc<ModelsManager>,
pub otel_manager: OtelManager,
pub tool_approvals: Arc<Mutex<ApprovalStore>>,
pub mcp_manager: Arc<McpConnectionManager>,
pub agent_control: AgentControl,
pub skills_manager: Arc<SkillsManager>,
pub file_watcher: Arc<FileWatcher>,
}

TurnContext (codex.rs):

pub struct TurnContext {
pub sub_id: String,
pub cwd: PathBuf,
pub approval_policy: AskForApproval,
pub sandbox_policy: SandboxPolicy,
pub windows_sandbox_level: WindowsSandboxLevel,
pub network: Option<NetworkProxy>,
pub shell_environment_policy: ShellEnvironmentPolicy,
pub otel_manager: OtelManager,
}
pub enum TaskKind {
Regular, // Main agent loop
Review, // Code review task
Compact, // Context compaction task
GhostSnapshot, // Git snapshot task
Undo, // Undo task
UserShell, // User shell command
}
// Via SessionTask trait:
// fn kind() -> TaskKind;
// async fn run(self: Arc<Self>, session, ctx, input, cancellation_token) -> Option<String>;
// async fn abort(...);

Tool Dispatch System (codex-rs/core/src/tools/)

Section titled “Tool Dispatch System (codex-rs/core/src/tools/)”
ResponseItem (from model) -> ToolRouter::build_tool_call
Matches: FunctionCall, CustomToolCall, LocalShellCall
Creates ToolCall { tool_name, call_id, payload: ToolPayload }
ToolRouter::dispatch_tool_call (tools/router.rs:143)
Resolve handler from registry
Create ToolInvocation (session, turn, call_id, payload)
Call handler.handle(invocation) -> ToolOutput
ToolOrchestrator::run (tools/orchestrator.rs:102)
Approval check (Skip / NeedsApproval / Forbidden)
If NeedsApproval: emit ExecApprovalRequest, wait for Op::ExecApproval
SandboxManager::select_initial() -> SandboxType
ToolRuntime::run(req, attempt, tool_ctx)
On sandbox denial: retry with SandboxType::None
Handler-specific runtimes (tools/runtimes/)
ShellRuntime: unified_exec/process.rs
ApplyPatchRuntime: apply_patch.rs
Emit ToolOutput -> add to ResponseInputItem[] -> return to model
pub trait ToolHandler: Send + Sync {
fn kind(&self) -> ToolKind; // Function | Freeform
fn matches_kind(&self, payload: &ToolPayload) -> bool;
async fn is_mutating(&self, invocation: &ToolInvocation) -> bool;
async fn handle(&self, invocation: ToolInvocation)
-> Result<ToolOutput, FunctionCallError>;
}
HandlerTypeFilePurpose
ShellHandlerFunctiontools/handlers/shell.rsRaw shell commands
UnifiedExecHandlerFunctiontools/handlers/unified_exec.rsInteractive PTY processes
ApplyPatchHandlerFunction/Freeformtools/handlers/apply_patch.rsFile patching with diff-match-patch
ReadFileHandlerFunctiontools/handlers/read_file.rsFile reading (with token truncation)
ListDirHandlerFunctiontools/handlers/list_dir.rsDirectory listing (recursive option)
GrepFilesHandlerFunctiontools/handlers/grep_files.rsText search in files
JsReplHandlerFunctiontools/handlers/js_repl.rsJavaScript evaluation
McpHandlerFunctiontools/handlers/mcp.rsMCP tool invocation
McpResourceHandlerFunctiontools/handlers/mcp_resource.rsMCP resource reading
MultiAgentHandlerFunctiontools/handlers/multi_agents.rsSpawn sub-agents
PlanHandlerFunctiontools/handlers/plan.rsTask planning
RequestUserInputHandlerFunctiontools/handlers/request_user_input.rsPrompt user for input
SearchToolBm25HandlerFunctiontools/handlers/search_tool_bm25.rsBM25 semantic search
DynamicToolHandlerFunctiontools/handlers/dynamic.rsUser-defined dynamic tools
ViewImageHandlerFunctiontools/handlers/view_image.rsDisplay images
pub enum ToolPayload {
Function { arguments: String }, // JSON-serialized args
Custom { input: String }, // Free-form text
Mcp { server, tool, raw_arguments }, // MCP server tool call
LocalShell { params: ShellToolCallParams },
}
enum ExecApprovalRequirement {
Skip { bypass_sandbox, proposed_execpolicy_amendment },
NeedsApproval { reason, proposed_execpolicy_amendment },
Forbidden { reason },
}
// Approval caching:
// ApprovalStore: HashMap<serialized_key, ReviewDecision>
// with_cached_approval() checks cache first, stores per unique key
enum ReviewDecision {
Approved,
ApprovedForSession,
ApprovedExecpolicyAmendment { amendment },
Denied,
Abort,
}
UnifiedExecProcessManager:
open_process(ExecCommandRequest) -> ProcessHandle
Build CommandSpec -> SandboxManager::select_initial()
Spawn PTY (via execute_exec_env)
Create UnifiedExecProcess { id, handle, buffer }
write_stdin(process_id, input) -> async stream
close_process(process_id) -> output
HeadTailBuffer:
Ring buffer with fixed max size (1 MiB default)
Head pointer: first N bytes (for user context)
Tail pointer: last N bytes (for recent output)
Middle bytes: discarded with "[...truncated...]" marker

Context Management and Token Budgeting (codex-rs/core/src/context_manager/)

Section titled “Context Management and Token Budgeting (codex-rs/core/src/context_manager/)”
pub struct ContextManager {
messages: Vec<ContentItem>,
token_budget: u32,
reserved_for_model_response: u32,
history_start_index: usize, // Compaction boundary
}
pub struct TotalTokenUsageBreakdown {
pub input_tokens: u32,
pub output_tokens: u32,
pub reasoning_tokens: Option<u32>, // For reasoning models
}

Token Strategies:

  • estimate_response_item_model_visible_bytes() estimates token cost per item
  • formatted_truncate_text() truncates with [... truncated ...] marker
  • should_use_remote_compact_task() decides remote compaction

Inline Compaction (compact.rs): When context exceeds token_budget:

  1. run_inline_auto_compact_task() identifies compactible turns
  2. Summarizes via model call
  3. Replaces original turns with CompactedTurnItem
  4. Updates token budget and continues

Client -> Op::UserInput { items }
submission_loop receives
spawn_task(RegularTask)
run_turn() starts
TurnStartedEvent -> tx_event
ModelClient.stream()
ResponseEvent::Delta -> AgentMessageContentDeltaEvent
-> ReasoningContentDeltaEvent
ResponseItem (toolcall) -> ItemStartedEvent
-> ExecCommand{Begin,End}
-> PatchApply{Begin,End}
-> ItemCompletedEvent
Loop: tool outputs as input items
TurnCompleteEvent -> tx_event
Client <- rx_event.next_event()
CategoryEvents
Turn lifecycleTurnStartedEvent, TurnCompleteEvent, TurnAbortedEvent
Content streamingAgentMessageContentDeltaEvent, ReasoningContentDeltaEvent, ReasoningRawContentDeltaEvent
Tool executionItemStartedEvent, ItemCompletedEvent, ExecCommandBeginEvent, ExecCommandEndEvent
File patchingPatchApplyBeginEvent, PatchApplyEndEvent
ApprovalExecApprovalRequestEvent, PatchApprovalRequestEvent
DiagnosticsErrorEvent, WarningEvent, DeprecationNoticeEvent
StateSessionConfigured, UserMessage, ShutdownComplete
Web searchWebSearchBeginEvent, WebSearchEndEvent
ContextContextCompactedEvent

Defines the shared communication contract between all Codex components.

Submission Queue (Client to Server): Op enum

Section titled “Submission Queue (Client to Server): Op enum”
VariantPurpose
UserTurnPrimary interaction: items, cwd, approval_policy, sandbox_policy, model, reasoning config
UserInputLegacy input variant
ExecApproval / PatchApprovalUser approval responses
ResolveElicitationMCP server request resolution
UserInputAnswer / DynamicToolResponseTool response payloads
InterruptAbort current task
CompactSummarize conversation
Undo / ThreadRollbackUndo operations
ReviewCode review request
ShutdownTerminate session
VariantPurpose
MessageText/image content with optional phase (commentary/final_answer)
ReasoningExtended thinking with summary and encrypted content
LocalShellCallLocal command execution
FunctionCall / FunctionCallOutputTool invocations and results
CustomToolCall / CustomToolCallOutputUser-defined tools
McpToolCallModel Context Protocol calls
WebSearchCallWeb search integration
GhostSnapshotGit commit snapshots
CompactionContext compression metadata
StructPurpose
SubmissionWraps Op with unique ID for request correlation
EventServer event wrapper with timestamp and session context
UserInput enumText, Image, LocalImage, Skill, Mention variants
ShellToolCallParamsCommand params (command, workdir, timeout_ms, sandbox_permissions)
FunctionCallOutputPayloadFlexible output: plain text OR structured content items (text/image)
AskForApproval enumUntrusted, OnFailure, OnRequest (default), Never
SandboxPolicy enumDangerFullAccess, ReadOnly, ExternalSandbox, WorkspaceWrite
ReadOnlyAccess enumRestricted (with readable_roots) or FullAccess
  • Tool defines name, description, input_schema, output_schema
  • Resource provides readable resource metadata (name, uri, size, mime_type)
  • CallToolResult is the MCP tool response: content[], structured_content, is_error flag
  • RequestId is polymorphic: either String or i64

Configuration is loaded from multiple sources and merged with precedence ordering.

Precedence Order (Low to High):

  1. System default config
  2. Project configs (root to cwd, if multiple)
  3. User config (~/.codex/config.toml)
  4. Legacy managed config
  5. MDM-provided config
  6. CLI session flags (-c key=value)

ConfigLayerStack (state.rs):

pub struct ConfigLayerStack {
layers: Vec<ConfigLayerEntry>, // Ordered low-to-high precedence
user_layer_index: Option<usize>, // Tracks single user layer
requirements: ConfigRequirements, // Constraints on merged config
requirements_toml: Option<String>, // Preserves original allow-lists
}
pub struct ConfigLayerEntry {
name: ConfigLayerSource, // Mdm, System, User, Project, SessionFlags
config: TomlValue, // Raw TOML config
raw_toml: Option<String>, // Preserves original TOML text
version: String, // Fingerprint for tracking
disabled_reason: Option<String>, // Why layer is disabled
}

Key Operations:

  • merge_toml_values(base, overlay) does recursive TOML merge; overlay wins
  • build_cli_overrides_layer(overrides) constructs layer from -c key=value args
  • effective_config() merges all non-disabled layers in precedence order
  • origins() maps each config key to its source layer metadata

Configuration Constraints (config_requirements.rs)

Section titled “Configuration Constraints (config_requirements.rs)”
  • SandboxModeRequirement restricts allowed sandbox modes
  • NetworkConstraints enforces network access policy
  • ResidencyRequirement enforces data residency
  • WebSearchModeRequirement controls web search enable/disable
  • McpServerRequirement requires/forbids specific MCP servers
  • System: /etc/codex/config.toml (Linux), ~/Library/Application Support/Codex (macOS)
  • User: ~/.codex/config.toml
  • Project: .codex/config.toml (scanned up directory tree)

Location: ~/.codex/state/state.sqlite

LogEntry (model/log.rs):

pub struct LogEntry {
ts: i64, // Unix timestamp (seconds)
ts_nanos: i64, // Nanosecond precision
level: String, // TRACE, DEBUG, INFO, WARN, ERROR
target: String, // Logger target (crate name)
message: Option<String>,
thread_id: Option<String>,
process_uuid: Option<String>, // pid:uuid format
module_path: Option<String>,
file: Option<String>,
line: Option<i64>,
}

StateRuntime (runtime.rs):

  • Manages SQLite connection and log/metadata operations
  • insert_logs(entries) does batch insert of tracing events
  • delete_logs_before(cutoff_ts) does retention cleanup (90 days)
  • Metadata queries for thread information

LogDbLayer (log_db.rs):

  • Implements tracing_subscriber::Layer for automatic log capture
  • Buffered: MPSC channel (capacity: 512)
  • Batch inserts: batch size 64, flush interval 250ms
  • Automatic cleanup of logs older than 90 days
  • Captures thread_id field from tracing spans

Database Constants:

  • STATE_DB_VERSION = 5
  • LOG_RETENTION_DAYS = 90
  • LOG_BATCH_SIZE = 64
  • LOG_FLUSH_INTERVAL = 250ms
  • LOG_QUEUE_CAPACITY = 512

Session history stored as line-delimited JSON (JSONL) files. Backfill system processes rollouts for extraction:

  • BackfillState tracks JSONL rollout processing state
  • BackfillStatus is in progress / complete / failed
  • Stage1JobClaim, Stage1Output handle job orchestration

Event TypeTriggerData
AfterAgentAgent response completethread_id, turn_id, input_messages[], last_assistant_message
AfterToolUseTool execution doneturn_id, call_id, tool_name, tool_kind, tool_input, executed, success, duration_ms, mutating, sandbox, sandbox_policy, output_preview
pub struct Hooks {
after_agent: Vec<Hook>,
after_tool_use: Vec<Hook>,
}
pub struct HookPayload {
session_id: ThreadId,
cwd: PathBuf,
triggered_at: DateTime<Utc>, // RFC3339 timestamp
hook_event: HookEvent, // Tagged union of event types
}

Execution Model:

  • Hooks run sequentially via async HookFn functions
  • Results: Success, FailedContinue (error, keep going), FailedAbort (error, stop pipeline)
  • Legacy support: legacy_notify_argv converted to AfterAgent hook for backward compatibility
  • Hooks receive JSON payload and can trigger external actions
enum HookToolKind {
Function, // Built-in function calls
Custom, // Custom tool implementations
LocalShell, // Shell command execution
Mcp, // Model Context Protocol tools
}

Non-Interactive Execution (codex-rs/exec/)

Section titled “Non-Interactive Execution (codex-rs/exec/)”

Entry point parses CLI args, initializes config, spawns ThreadManager, and processes events.

Main Loop (main.rs:544-600):

  1. Submit initial operation (UserTurn or Review)
  2. Spawn thread listener tasks for all created threads
  3. Receive events from unbounded MPSC channel
  4. Route to EventProcessor::process_event()
  5. Handle shutdown signals and errors

EventProcessor Trait:

trait EventProcessor {
fn print_config_summary(&mut self, config, prompt, session_configured);
fn process_event(&mut self, event) -> CodexStatus;
fn print_final_output(&mut self);
}
enum CodexStatus {
Running, // Continue processing events
InitiateShutdown, // Gracefully shut down
Shutdown, // Shutdown complete, exit
}

Output Modes:

  • EventProcessorWithJsonOutput emits JSONL (one event per line), for automation
  • EventProcessorWithHumanOutput renders human-readable with ANSI color codes

Approval in Non-Interactive Mode:

  • Default policy: AskForApproval::Never
  • Elicitation requests automatically cancelled
  • --full-auto forces SandboxMode::WorkspaceWrite
  • --dangerously-bypass-approvals-and-sandbox forces full access

PlatformSandbox TypeImplementation
LinuxBubblewrap + Landlock + seccompcodex-rs/linux-sandbox/
macOSSeatbelt (sandbox profiles)core/src/seatbelt.rs
WindowsRestricted token / VM isolationcodex-rs/windows-sandbox-rs/

Two-stage sandboxing: bubblewrap first, then seccomp.

Key files:

  • linux_run_main.rs (458 lines) is the main orchestrator, handles PR_SET_NO_NEW_PRIVS, preflight /proc mount testing, container environment detection
  • bwrap.rs (372 lines) does bubblewrap filesystem setup: read-only-by-default root with writable roots, symlink attack mitigation via /dev/null binding, network namespace isolation
  • landlock.rs (238 lines) installs Landlock filesystem rules (read-only root + writable paths) + seccomp filter
  • vendored_bwrap.rs (71 lines) is an FFI wrapper to C bubblewrap binary (bwrap_main())

Seccomp Filter (blocked syscalls):

  • connect, accept, bind, listen, getpeername, setsockopt
  • ptrace, io_uring_*
  • All sockets blocked except AF_UNIX domain sockets

BwrapNetworkMode:

  • FullAccess has no network restriction
  • Isolated does full network namespace isolation
  • ProxyOnly routes through network proxy

Sandboxing Flow:

  1. Parse SandboxPolicy (read/write access, network access)
  2. If restricting filesystem: wrap with bubblewrap (read-only root + selective writable binds)
  3. Apply PR_SET_NO_NEW_PRIVS if needed
  4. Install seccomp filter (denies network syscalls)
  5. execvp into target command

Sandbox Transform (core/src/sandboxing/mod.rs)

Section titled “Sandbox Transform (core/src/sandboxing/mod.rs)”
CommandSpec {
program, args, cwd, env, sandbox_permissions, justification
}
->
SandboxManager::transform(SandboxTransformRequest {
spec, policy, sandbox: SandboxType, enforce_managed_network,
network, sandbox_policy_cwd, ...
})
->
ExecRequest {
command, cwd, env, network, sandbox: SandboxType,
sandbox_permissions, justification, arg0
}

Exec Server and Privilege Escalation (codex-rs/exec-server/)

Section titled “Exec Server and Privilege Escalation (codex-rs/exec-server/)”

MCP server implementing privilege escalation policy for shell command execution with interception.

TUI calls shell_tool
MCP Server spawns Bash (with escalate socket FD)
Patched Bash attempts exec()
exec() wrapper sends EscalateRequest to MCP server
MCP evaluates policy + heuristics -> decision
Run: child execs directly
Escalate: receive FDs, exec with elevated permissions
Deny: return error to child
struct EscalateRequest {
file: PathBuf,
argv: Vec<String>,
workdir: PathBuf,
env: HashMap<String, String>,
}
enum EscalateAction {
Run,
Escalate,
Deny { reason: Option<String> },
}
  • AsyncSocket is a stream-based socket with length-prefixed frames
  • AsyncDatagramSocket is a datagram socket with FD support
  • Uses SCM_RIGHTS (Unix FD passing) via control messages, max 16 FDs per message
  • Built on socket2 + tokio::io::AsyncFd

Shell Command Safety (codex-rs/shell-command/)

Section titled “Shell Command Safety (codex-rs/shell-command/)”

Tree-sitter based bash parsing and command safety checking.

bash.rs (577 lines) uses tree-sitter to parse bash scripts and extract only safe command patterns:

  • try_parse_shell() parses bash script into tree-sitter Tree
  • try_parse_word_only_commands_sequence() extracts simple commands (no redirections, substitutions, etc.)
  • parse_shell_lc_plain_commands() parses bash -c "cmd1 && cmd2 | cmd3" sequences

Allowed operators: &&, ||, ;, | Rejected constructs: $(), backticks, >, <, (), {}, variable expansions

Safety Strategy:

  1. Build allowed node kinds whitelist
  2. Walk tree depth-first, reject disallowed nodes
  3. Allow only specific punctuation operators
  4. Extract command words from safe patterns only

AST Node Types Used: program, list, pipeline, command, command_name, word, string, raw_string, number, concatenation

  • is_dangerous_command.rs has a heuristic list of dangerous commands (rm, mkfs, dd, etc.)
  • is_safe_command.rs has an allowlist of safe commands
  • windows_dangerous_commands.rs / windows_safe_commands.rs have Windows-specific lists

Uses a custom patch format (*** Begin Patch / *** End Patch) parsed into hunks:

enum Hunk {
AddFile { path: PathBuf, contents: String },
DeleteFile { path: PathBuf },
UpdateFile { path: PathBuf, move_path: Option<PathBuf>,
chunks: Vec<UpdateFileChunk> },
}
struct UpdateFileChunk {
change_context: Option<String>, // line to seek to
old_lines: Vec<String>,
new_lines: Vec<String>,
is_end_of_file: bool,
}
  1. parse_patch() parses patch into hunks
  2. For each UpdateFile hunk: read original file, seek context line per chunk, match old_lines, compute replacement
  3. Apply replacements in reverse order (preserve indices)
  4. Write new file atomically
  5. Create/delete files as needed
  6. unified_diff_from_chunks() generates unified diff output using similar::TextDiff

Two-threaded system using nucleo fuzzy matcher:

struct FileSearchSession { inner: Arc<SessionInner> }
struct FileSearchOptions {
pub limit: NonZero<usize>,
pub exclude: Vec<String>,
pub threads: NonZero<usize>,
pub compute_indices: bool,
pub respect_gitignore: bool,
}
struct FileMatch {
pub score: u32,
pub path: PathBuf,
pub root: PathBuf,
pub indices: Option<Vec<u32>>, // matched character positions
}
trait SessionReporter: Send + Sync {
fn on_update(&self, snapshot: &FileSearchSnapshot);
fn on_complete(&self);
}
create_session()
spawn walker_worker()
Uses ignore::WalkBuilder (.gitignore support)
Injects files into nucleo matcher
spawn matcher_worker()
Consumes signals: QueryUpdated, NucleoNotify, WalkComplete, Shutdown
Debounces results (10ms tick)
Invokes reporter.on_update() for streaming results
Invokes reporter.on_complete() when done
update_query()
Matcher re-parses pattern and emits updates

pub struct RmcpClient { ... }
impl RmcpClient {
pub async fn new_stdio_client(...) -> Self; // Spawn stdio subprocess
pub async fn new_streamable_http_client(...) -> Self; // HTTP transport
pub async fn initialize(...); // MCP handshake
pub async fn list_tools(...) -> Vec<Tool>;
pub async fn list_tools_with_connector_ids(...);
pub async fn list_resources(...) -> Vec<Resource>;
pub async fn list_resource_templates(...) -> Vec<ResourceTemplate>;
pub async fn read_resource(...) -> ReadResourceResult;
pub async fn call_tool(...) -> CallToolResult;
pub async fn send_custom_notification(...);
pub async fn send_custom_request(...);
}

MCP Connection Manager (core/src/mcp_connection_manager.rs)

Section titled “MCP Connection Manager (core/src/mcp_connection_manager.rs)”
pub struct McpConnectionManager {
clients: HashMap<String, Arc<RmcpClient>>, // One per configured server
tools_cache: HashMap<String, Tool>, // Aggregated tools
// Tool names: "<server>__<tool_name>" (double underscore delimiter)
}

MCP Tool Handler (core/src/tools/handlers/mcp.rs)

Section titled “MCP Tool Handler (core/src/tools/handlers/mcp.rs)”
  1. Parse fully-qualified name: "my_server__get_weather" becomes (server: "my_server", tool: "get_weather")
  2. Look up RmcpClient for server
  3. Call client.call_tool(tool_name, args)
  4. Handle elicitation (OAuth, prompts)
  5. Return CallToolResult { content, is_error }

Runs Codex itself as an MCP server via stdio transport. Allows other tools to call Codex as a tool provider.

pub struct StoredOAuthTokens {
pub server_name: String,
pub url: String,
pub client_id: String,
pub token_response: WrappedOAuthTokenResponse,
pub expires_at: Option<u64>,
}
pub enum OAuthCredentialsStoreMode {
Auto, // Keyring when available; otherwise File
File, // ~/.codex/.credentials.json
Keyring, // Keyring only, fail if unavailable
}

Uses OS keyring (macOS Keychain, Windows Credential Manager, Linux DBus Secret Service) with file fallback.


// Core auth flows:
pub use device_code_auth::DeviceCode;
pub use device_code_auth::complete_device_code_login;
pub use device_code_auth::request_device_code;
pub use device_code_auth::run_device_code_login;
pub use server::LoginServer;
pub use server::ServerOptions;
pub use server::run_login_server;
// Re-exported from codex-core:
pub use codex_core::AuthManager;
pub use codex_core::CodexAuth;
pub use codex_core::auth::AuthDotJson;
pub use codex_core::auth::CLIENT_ID;
pub use codex_core::auth::CODEX_API_KEY_ENV_VAR;
pub use codex_core::auth::OPENAI_API_KEY_ENV_VAR;
pub use codex_core::auth::login_with_api_key;
pub use codex_core::auth::logout;
pub use codex_core::auth::save_auth;

Supports device code flow, PKCE, API key via stdin, and a local login server for OAuth callbacks.


pub trait KeyringStore: Debug + Send + Sync {
fn load(&self, service: &str, account: &str)
-> Result<Option<String>, CredentialStoreError>;
fn save(&self, service: &str, account: &str, value: &str)
-> Result<(), CredentialStoreError>;
fn delete(&self, service: &str, account: &str)
-> Result<bool, CredentialStoreError>;
}
pub struct DefaultKeyringStore; // Uses platform-native keyring

Platform Support:

  • Linux: keyring::linux-native-async-persistent (keyutils + async-secret-service)
  • macOS: keyring::apple-native
  • Windows: keyring::windows-native
  • FreeBSD/OpenBSD: keyring::sync-secret-service
  • Fallback: keyring::crypto-rust (software encryption)

HTTP + SOCKS5 proxy for network sandboxing within the sandbox environment.

pub struct NetworkProxyBuilder {
state: Option<Arc<NetworkProxyState>>,
http_addr: Option<SocketAddr>,
socks_addr: Option<SocketAddr>,
admin_addr: Option<SocketAddr>,
managed_by_codex: bool,
policy_decider: Option<Arc<dyn NetworkPolicyDecider>>,
blocked_request_observer: Option<Arc<dyn BlockedRequestObserver>>,
}

Components:

  • HTTP proxy (http_proxy.rs) does transparent HTTP/HTTPS proxying
  • SOCKS5 proxy (socks5.rs) implements SOCKS5 protocol for TCP tunneling
  • Admin server (admin.rs) provides management and metrics endpoint
  • Network policy (network_policy.rs) defines NetworkPolicyDecider trait for allow/deny decisions
  • Per-attempt proxy usernames for tracking (metadata.rs)

Typed protocol for IDE integrations (VSCode extension confirmed).

Transports:

  • stdio:// (default) for subprocess communication
  • ws://IP:PORT for WebSocket networked integrations

Generated bindings:

  • codex app-server generate-ts generates TypeScript bindings
  • codex app-server generate-json-schema generates JSON Schema

App Server Protocol (codex-rs/app-server-protocol/)

Section titled “App Server Protocol (codex-rs/app-server-protocol/)”

Versioned protocol: v1 and v2 modules with shared common types.

Key Types:

pub enum AuthMode {
ApiKey, // OpenAI API key stored by Codex
Chatgpt, // ChatGPT OAuth managed by Codex
ChatgptAuthTokens, // External host-supplied tokens (unstable)
}
// Uses macro-generated ClientRequest enum with tagged JSON-RPC:
// Each variant has params + response types
// Supports experimental feature gating per-method

Protocol generates: TypeScript types via ts-rs, JSON Schema via schemars.


pub struct SkillsManager {
skills_path: PathBuf,
cache: HashMap<PathBuf, SkillMetadata>,
}
// Loading:
pub fn skills_for_config(&self, config: &Config) -> SkillLoadOutcome {
skills: Vec<SkillMetadata>,
errors: Vec<SkillError>,
allowed_skills: HashSet<PathBuf>,
}
// Format: <skills_dir>/<skill_name>/codex.toml
  1. Parse codex.toml: [tool.X] sections become tool definitions, [env] sections define env var requirements
  2. Inject into prompt: tool specs go to ToolsConfig, env vars go to TurnContext.env
  3. Tool mentions (contextual injection): if user asks for “X skill”, inject it. Collected via mentions.rs: collect_explicit_skill_mentions()

Multi-Agent Spawning (codex-rs/core/src/agent/control.rs)

Section titled “Multi-Agent Spawning (codex-rs/core/src/agent/control.rs)”
pub struct AgentControl {
manager: Weak<ThreadManagerState>, // Global agent registry
state: Arc<Guards>, // Spawn depth guards
}
pub async fn spawn_agent(&self, config: Config, items: Vec<UserInput>)
-> CodexResult<ThreadId>
{
1. Check spawn depth limits (MAX_THREAD_SPAWN_DEPTH = 8)
2. Call ThreadManager::spawn_new_thread()
3. Submit initial items via send_input()
4. Return new ThreadId
}

Multi-agent handler (tools/handlers/multi_agents.rs) spawns sub-agents from parent, waits for completion with timeout, returns output to parent.


Converts ANSI escape sequences to ratatui styled text:

pub fn ansi_escape_line(s: &str) -> Line<'static>
pub fn ansi_escape(s: &str) -> Text<'static>

Uses ansi_to_tui crate. Expands tabs to 4 spaces. Handles parsing errors with logging.


WidgetFilePurpose
Appapp.rsMain application loop and event orchestration
ChatWidgetchatwidget/Primary UI for agent conversation display
BottomPanebottom_pane/Input area, command palette, overlays
ExecCellexec_cell/Command execution and output rendering
DiffRenderdiff_render.rsVisual diff display
MarkdownRendermarkdown_render.rsCode block and text rendering
FileSearchfile_search.rsIntegrated fuzzy search UI

Full-screen views managed by handle_tui_event() in App. Overlays replace the main view temporarily (e.g., file search, help, settings).


Feature Flags (codex-rs/core/src/features.rs)

Section titled “Feature Flags (codex-rs/core/src/features.rs)”

50+ feature toggles with stage metadata (alpha/beta/stable). Examples include:

  • ApplyPatchFreeform for freeform patch application
  • Collab for collaborative features
  • JsRepl for JavaScript REPL tool
  • Feature flags controlled via codex features list/enable/disable or -c features.<name>=true/false

pub enum CodexErr {
Fatal(String),
UserCancelled,
InternalAgentDied,
SandboxErr(SandboxErr),
ExecErr(ExecErr),
ApprovalErr(String),
// ... 20+ variants
}
pub type CodexResult<T> = Result<T, CodexErr>;
pub enum FunctionCallError {
RespondToModel(String), // Error to send back to model
Rejected(String), // Tool rejected (user/policy)
}

CategoryCrates
Asynctokio (multi-thread), async-channel, futures
Sandboxinglandlock, seccompiler (Linux), seatbelt (macOS)
TUIratatui, crossterm
Parsingtree-sitter (bash), similar (diffs), askama (templates)
Serializationserde, serde_json, serde_yaml, toml, toml_edit
Networkingreqwest, tokio-tungstenite (WebSocket), http
Securitykeyring, sha1, sha2, base64
Searchnucleo (fuzzy), bm25 (semantic), ignore (walk), regex-lite
File opsnotify (watcher), tempfile, zip
Identityuuid (v4/v5), chrono, time
Utilitieswhich, wildmatch, shlex
Codegents-rs (TypeScript), schemars (JSON Schema)

  1. Event-Driven UI: TUI state updates are almost entirely driven by events (internal or from the engine).
  2. Asynchronous Engine: The agent engine runs in separate tasks/threads, communicating via async_channel bounded/unbounded channels.
  3. Arc<Mutex/RwLock> Pattern: Session is Arc<Session> shared across tasks, state behind Arc<Mutex<SessionState>>, all tool contexts take Arc<Session> and Arc<TurnContext>.
  4. Hierarchical Config: Configuration loaded from multiple layers (system, project, user, CLI) with recursive TOML merge.
  5. Graceful Failover: If an agent thread dies unexpectedly, the TUI attempts to fail back to the primary thread.
  6. Progressive Disclosure (Skills): Skills listed in context, full content only loaded when triggered.
  7. Approval Caching: ApprovalStore (HashMap<serialized_key, ReviewDecision>) with with_cached_approval() checking cache first.
  8. Sandbox Retry: Initial attempt with selected SandboxType; on denial, retry with SandboxType::None using cached approval.
  9. Parallel Tool Execution: ToolCallRuntime with lock guard: read lock (shared) for parallel, write lock (exclusive) for serial.
  10. Task-Based Turns: Each turn is a SessionTask spawned on tokio::spawn with CancellationToken.

PathPurpose
codex-rs/cli/src/main.rsMain entry point and subcommand parsing
codex-rs/tui/src/lib.rsTUI bootstrapper and terminal initialization
codex-rs/tui/src/app.rsMain application loop and event orchestration
codex-rs/tui/src/chatwidget/Primary UI component for chat interface
codex-rs/core/src/codex.rsCodex struct, Session, submission_loop, TurnContext
codex-rs/core/src/codex_thread.rsCodexThread public wrapper around Codex
codex-rs/core/src/tools/router.rsToolRouter dispatches tool calls to handlers
codex-rs/core/src/tools/orchestrator.rsToolOrchestrator: approval, sandbox, run, retry
codex-rs/core/src/tools/handlers/All built-in tool handler implementations
codex-rs/core/src/sandboxing/mod.rsSandbox selection and CommandSpec to ExecRequest transform
codex-rs/core/src/context_manager/history.rsContextManager for token budgeting and compaction
codex-rs/core/src/compact.rsInline context compaction
codex-rs/core/src/mcp_connection_manager.rsMcpConnectionManager for MCP server lifecycle
codex-rs/core/src/skills/manager.rsSkillsManager for TOML skill loading
codex-rs/core/src/agent/control.rsAgentControl for sub-agent spawning (depth limit 8)
codex-rs/core/src/unified_exec/Interactive shell: PTY management + HeadTailBuffer
codex-rs/core/src/project_doc.rsAGENTS.md hierarchical loading
codex-rs/core/src/environment_context.rsLLM context serialization (XML)
codex-rs/core/src/features.rsFeature flags (50+ toggles)
codex-rs/core/src/error.rsCodexErr, CodexResult
codex-rs/protocol/src/protocol.rsOp submissions, EventMsg events
codex-rs/protocol/src/models.rsResponseItem variants
codex-rs/protocol/src/mcp.rsMCP protocol types
codex-rs/config/src/state.rsConfigLayerStack multi-layer config
codex-rs/config/src/merge.rsRecursive TOML merge
codex-rs/state/src/log_db.rsLogDbLayer tracing to SQLite
codex-rs/state/src/runtime.rsStateRuntime SQLite operations
codex-rs/exec/src/main.rsNon-interactive execution entry point
codex-rs/hooks/src/types.rsHookPayload, HookEvent, HookResult
codex-rs/hooks/src/registry.rsHooks registry and dispatch
codex-rs/file-search/src/lib.rsFuzzy file search engine (nucleo)
codex-rs/linux-sandbox/src/linux_run_main.rsLinux sandbox orchestrator
codex-rs/linux-sandbox/src/bwrap.rsBubblewrap filesystem setup
codex-rs/linux-sandbox/src/landlock.rsLandlock + seccomp filtering
codex-rs/exec-server/src/lib.rsExec policy evaluation
codex-rs/exec-server/src/posix/escalate_server.rsPrivilege escalation server
codex-rs/exec-server/src/posix/socket.rsFD-passing socket I/O
codex-rs/shell-command/src/bash.rsTree-sitter bash parsing
codex-rs/apply-patch/src/lib.rsPatch parsing and application
codex-rs/rmcp-client/src/rmcp_client.rsMCP client (stdio + HTTP)
codex-rs/login/src/lib.rsAuth flows (device code, PKCE)
codex-rs/secrets/src/lib.rsMCP OAuth credential storage
codex-rs/keyring-store/src/lib.rsPlatform keyring abstraction
codex-rs/network-proxy/src/lib.rsHTTP+SOCKS5 proxy builder
codex-rs/app-server-protocol/src/protocol/common.rsIDE protocol types (v1/v2)
codex-rs/ansi-escape/src/lib.rsANSI to ratatui conversion

Captured live from codex --help and all subcommands. The Codex CLI is parsed by clap in codex-rs/cli/src/main.rs.

  • -c, --config <key=value> overrides any ~/.codex/config.toml key at runtime using TOML dotted paths. E.g. -c model="gpt-5.2-codex" or -c 'sandbox_permissions=["disk-full-read-access"]'. Raw string fallback if TOML parse fails.
  • --enable / --disable <FEATURE> toggles feature flags without editing config. Equivalent to -c features.<name>=true/false.
  • -i, --image <FILE>... attaches one or more images to the initial prompt. Multimodal input.
  • -m, --model <MODEL> sets model identifier.
  • --oss is a convenience flag for local OSS provider (LM Studio or Ollama). Verifies server is running before starting.
  • --local-provider lmstudio|ollama disambiguates when using --oss.
  • -p, --profile <CONFIG_PROFILE> selects named config profile from config.toml.
  • -s, --sandbox <SANDBOX_MODE> sets read-only | workspace-write | danger-full-access. Enforced at kernel level (Landlock on Linux, Seatbelt on macOS, restricted token on Windows).
  • -a, --ask-for-approval sets untrusted | on-failure | on-request | never. Controls when human approval gates shell execution.
  • --full-auto is an alias for -a on-request --sandbox workspace-write. Common CI/automation preset.
  • --dangerously-bypass-approvals-and-sandbox disables prompts and sandbox. For externally-sandboxed environments (CI containers).
  • -C, --cd <DIR> sets agent working root. Does not change process CWD; tells the agent where to scope operations.
  • --search enables live web search via the native Responses web_search tool.
  • --add-dir <DIR> adds additional directories writable alongside primary workspace.
  • --no-alt-screen disables alternate screen buffer; runs TUI inline. Required for Zellij and other multiplexers that follow strict xterm spec.
CommandPurpose
codex [PROMPT]Launch interactive TUI. Default. Prompt is optional.
codex exec [PROMPT]Non-interactive agent run (scripting/CI).
codex review [PROMPT]Code review non-interactively.
codex resume [SESSION_ID]Resume previous interactive session (picker or --last).
codex fork [SESSION_ID]Fork previous session (picker or --last).
codex apply <TASK_ID>Apply latest Codex agent diff as git apply to local working tree.
codex loginManage API credentials.
codex logoutRemove stored credentials.
codex mcpMCP server management (experimental).
codex mcp-serverRun Codex itself as an MCP server (stdio transport).
codex app-serverApp server for IDE integrations (experimental).
codex sandboxRun arbitrary commands inside the Codex sandbox (test/debug isolation).
codex completion [SHELL]Shell completion scripts (bash/elvish/fish/powershell/zsh).
codex debugDebugging tools.
codex cloudCodex Cloud task management (experimental).
codex featuresInspect and toggle feature flags.
codex exec [PROMPT] [COMMAND]
--skip-git-repo-check allow running outside a git repo
--ephemeral don't persist session files to disk
--output-schema <FILE> JSON Schema for structured final response
--color always|never|auto colorize output
--json emit events as JSONL (machine-readable)
-o, --output-last-message write last agent message to a file

Subcommands:

  • codex exec resume resumes a previous session non-interactively.
  • codex exec review runs code review non-interactively.

The --json flag emits the same event stream the TUI consumes as JSONL. The --output-schema flag forces structured JSON output from the model via a JSON Schema constraint, revealing that Codex supports structured output mode.

codex review [PROMPT]
--uncommitted review staged + unstaged + untracked changes
--base <BRANCH> review changes against a base branch
--commit <SHA> review changes introduced by a specific commit
--title <TITLE> commit title shown in review summary

Standalone review mode built into the CLI, not a tool call. Three distinct scopes: uncommitted changes, branch diff, or single commit.

Both share the full global options plus:

  • --last skips picker, uses most recent session.
  • --all disables CWD filtering, shows all sessions with CWD column.

Fork semantics: creates a new session branching from a prior session’s state. Distinct from resume (which continues in place).

codex mcp list
codex mcp get
codex mcp add
codex mcp remove
codex mcp login # OAuth for MCP servers
codex mcp logout

Runs Codex itself as an MCP server via stdio transport. Allows other tools to call Codex as a tool provider.

codex app-server (App Server / IDE Integration)

Section titled “codex app-server (App Server / IDE Integration)”
codex app-server
--listen <URL> stdio:// (default) | ws://IP:PORT
--analytics-default-enabled opt-in for first-party integrations (e.g. VSCode extension)

Subcommands:

  • codex app-server generate-ts generates TypeScript bindings for the app server protocol.
  • codex app-server generate-json-schema generates JSON Schema for the app server protocol.

Reveals that Codex exposes a typed protocol for IDE integrations (VSCode extension confirmed by --analytics-default-enabled flag docs).

codex sandbox macos (alias: seatbelt) # macOS Seatbelt
codex sandbox linux (alias: landlock) # Linux Landlock+seccomp
codex sandbox windows # Windows restricted token

Allows running arbitrary commands inside Codex’s own sandbox layer. Useful for verifying isolation behavior.

codex login
--with-api-key read API key from stdin
--device-auth device flow

Subcommand: codex login status shows current login state.

codex cloud exec # submit new cloud task without TUI
codex cloud status # show status of cloud task
codex cloud list # list cloud tasks
codex cloud apply # apply cloud task diff locally
codex cloud diff # show unified diff for a cloud task

codex apply <TASK_ID> at top level also applies cloud diffs as git apply.

codex features list # list all known features with stage + effective state
codex features enable # enable in config.toml
codex features disable # disable in config.toml

Feature flags have a “stage” (alpha/beta/stable) and can be toggled per-user without code changes. Exposes that Codex has a formal feature gate system.