All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.14.0 - 2026-03-17
Changed
- Bundled model metadata is now synced from the vendored upstream catalog in
codex/codex-rs/core/models.json, and the Elixir model list no longer falls back to extra local-only picker presets when the catalog is present. - SDK default selection still prefers
gpt-5.4, while ChatGPT-auth runtime catalogs continue to prefercodex-auto-balancedwhen that model is advertised remotely. - Example runners and example-specific docs now pin
gpt-5.4-minifor faster live runs, while the library default remainsgpt-5.4. - README and guides were refreshed to document the bundled model catalog source, the current bundled picker-visible snapshot, and the distinction between bundled defaults and example pins.
- Subagent docs and API guides were audited against the vendored Rust runtime and now document the current feature gating (
features.multi_agent,features.enable_fanout), runtime tool surface, inheritance semantics, CSV fan-out behavior, custom-agent precedence/nickname constraints, and current-vs-legacy collaboration item payload shapes more accurately. examples/live_subagent_host_controls.exsnow exercises the fullCodex.Subagentshost-control surface (list/2,children/3,source/1,parent_thread_id/1,child_thread?/1,read/3,await/3), drives the live prompt-mediated multi-agent tool surface (spawn_agent,resume_agent,send_input,wait,close_agent), and uses the configured/default model instead of a stale hardcoded example model.
Fixed
- Subagent/runtime parity was tightened:
collab_agent_spawn_beginnow preserves upstreammodelandreasoning_effortmetadata, subagent source parsing accepts legacysubagent/agent_typealiases, collab tool parsing recognizeswait_agentaliases, andCodex.Subagents.await/3now always pollsthread/readwith turns included so terminal-state detection stays reliable. - Streamed app-server turns now subscribe to the active thread instead of every thread on the shared connection while still allowing global threadless requests through, and the live subagent host-controls example now uses fresh host-control/child-turn connections plus project-scoped
thread/listfilters to avoid real-world discovery timeouts. - App-server collaboration parsing now normalizes both current plural fields and older singular payload shapes (
receiverThreadId,newThreadId,agentStatus) for collab tool-call items,thread/listsource-kind normalization now accepts:mcp/"subagent"aliases consistently, and subagent source parsing now accepts the camelCasememoryConsolidationvariant. - The live subagent example now matches real runtime behavior by resuming a known child before issuing later-turn
send_inputcalls, avoidingagent ... not foundfailures when the earlier child is no longer active in agent control.
0.13.0 - 2026-03-16
Added
Codex.OAuthfor native ChatGPT OAuth login, refresh, status, and logout, including browser-code + PKCE loopback login, device-code fallback, upstream-compatibleauth.jsonpersistence, memory token stores, and app-server external-auth refresh handling.- App-server v2 coverage for filesystem and plugin APIs, isolated managed child-process launch controls (
cwd/process_env), and OAuth-aware child bootstrapping against the effective child environment. - Approval-policy normalization and structured command, file, and permissions approval handling via internal approval-policy, request-permissions, approval-request, and approval-decision modules.
Codex.Subagents,Codex.Protocol.SessionSource,Codex.Protocol.SubAgentSource,Codex.Protocol.CollabAgentState,Codex.Protocol.CollabAgentRef, andCodex.Protocol.CollabAgentStatusEntryfor deterministic host-side subagent discovery, typed source parsing, child-thread inspection, await helpers, and collaboration lifecycle metadata.- New runnable examples and guides for native OAuth, app-server filesystem/plugins/config overrides, and host-side subagent controls, including
guides/09-oauth-and-login.md,guides/10-subagents.md,examples/live_oauth_login.exs, andexamples/live_subagent_host_controls.exs.
Changed
- Auth and config loading now respect child-process environment boundaries, layered
openai_base_url/[model_providers]settings, and shared custom CA bundles (CODEX_CA_CERTIFICATE, thenSSL_CERT_FILE) across CLI subprocesses, direct HTTP, MCP, OAuth, realtime, and voice requests. - App-server transport, events, items, and notification adapters were expanded for current upstream v2 / experimental approval parity, including guardian review lifecycle events,
serverRequest/resolved, richer approval metadata, and typed collaboration/subagent item data. - Approval hooks and thread options now normalize both inline and upstream-tagged granular approval policies, support structured permission grants for app-server review flows, and fail fast on malformed approval configs instead of dropping them silently.
- Model metadata and defaults were refreshed around the current bundled catalog, keeping
gpt-5.4as the SDK default while collaboration-mode presets now prefer server-advertised settings when present. - MCP tool qualification now sanitizes OpenAI-facing tool names while preserving original server/tool identifiers for actual MCP calls, and the README/guides/examples were updated to document the new auth, approvals, config, and subagent behavior.
Fixed
- OAuth browser login now defaults to the upstream-compatible loopback callback port
1455. - Subprocess startup now ensures the shared erlexec worker is running before launching exec/app-server children, avoiding early transport failures.
- App-server connection and shutdown paths now surface initialization/exit errors more reliably and use shared process-exit helpers for cleaner teardown.
- Live approval flows now preserve command/file/request-permissions parity across exec and app-server transports, including
grant_root, available decision metadata, and resolved-request notifications.
0.12.0 - 2026-03-12
Added
- New app-server request event types: MCP elicitation (
mcp_approval_request), permissions approval (permissions_approval_request), dynamic tool calls (dynamic_tool_call_request), and ChatGPT auth-token refresh (chatgpt_token_refresh_request). Codex.Protocol.RequestUserInputstruct withis_otherandis_secretflags for richer question payloads.Codex.Protocol.Opsmodule for protocol-level operation helpers.- App-server transport now filters events by thread correlation, preventing cross-thread race conditions.
- New notification and item adapters for upstream thread lifecycle, hook lifecycle, realtime, fuzzy-file-search, and model-reroute variants.
- Expanded item type coverage in
Codex.Itemsfor newer upstream item variants. - Comprehensive test suites for all new event types, transport filtering, notification/item adapters, and protocol structs.
Changed
Codex.AppServer.thread_compact/2now targets upstreamthread/compact/startinstead of the deprecatedthread/compact.- User-input handling across app-server and exec JSONL now supports
skillandmentionblocks. - Model default selection is now catalog-derived from bundled
priv/models.jsoninstead of hardcoded, defaulting togpt-5.4unless env overrides or fresher ChatGPT catalog data take precedence. - Bundled
priv/models.jsonre-synced with upstream;features.remote_modelsis no longer required for normal catalog/default behavior. - Config layer loading rewritten with real TOML parsing, trust-aware project-layer enablement, cwd
config.tomlproject support, and siblingrequirements.tomlmerging for system config. - App-server
Paramsmodule expanded with builders for all new request families. - App-server
Accountmodule updated for current upstream account fields. - Documentation, guides, and example runners updated to reflect catalog-driven model defaults instead of stale
gpt-5.3-codex/features.remote_modelsassumptions. - Added
tomldependency for config layer TOML parsing.
Fixed
- App-server notifications and items no longer silently drop current upstream variants (thread lifecycle, hook lifecycle, realtime, fuzzy-file-search, model-reroute).
Codex.Eventsparser now correctly handles all current upstream exec JSONL event shapes (~600 new lines of event coverage).- Config defaults test expectations updated to match catalog-derived defaults.
0.11.0 - 2026-03-05
Added
- Added a new
Codex.CLIpassthrough layer plusCodex.CLI.SessionPTY/raw subprocess sessions for command-surface parity with the upstream Codex terminal client, including wrappers for rootcodex,app,app-server,apply,cloud,completion,execpolicy,features,login,logout,mcp,mcp-server,resume,fork, andsandbox. - Added
examples/live_cli_passthrough.exsandexamples/live_cli_session.exsto demonstrate direct CLI passthrough and PTY-backed prompt-mode sessions.
Changed
- Default SDK model is now
gpt-5.4for both API-key and ChatGPT auth flows, and picker/default-marking behavior now keepsgpt-5.4preferred when local presets or current model catalogs are merged. - Bundled model metadata, README/guides, and live example defaults now reflect the current Codex model lineup, including
gpt-5.4,gpt-5.3-codex,gpt-5.3-codex-spark, and the refreshedgpt-5.2-codexdescription. Codex.Thread.Optionsnow mirrors current Codex CLI web-search defaults when callers leave the setting untouched: cached search for normal local runs, and live search for full-access sandbox modes.- Updated README, guides, examples, and generated-doc module groupings to document the new CLI passthrough/session layer and the revised web-search default behavior.
- Realtime
tool_choiceserialization for{:function, name}now emits%{"type" => "function", "name" => name}forsession.updatecompatibility. - Realtime and voice live examples now self-report API skip reasons (
insufficient_quota,realtime_model_unavailable) and exit cleanly instead of misreporting success. - App-server approvals demo now uses a prompt that exercises approvals more reliably and waits briefly for trailing audit messages before summarizing.
- Tool-bridging and rate-limit examples now print explicit runtime notes when transport/rate-limit data is absent so empty output is not mistaken for SDK failure.
Fixed
Codex.Modelsnow accepts current object-shaped remoteupgradepayloads while preserving upgrade reasoning-effort mappings.- Stream queue close semantics now treat
close/2as terminal, preserving already-buffered items while dropping late pushes after closure. - App-server initialize failures now surface through
await_ready/2, avoid sendinginitializedafter init errors, and shut down the transport cleanly. - App-server stderr retention is now capped to the shared transport tail size instead of growing without bound.
- Voice streamed-input STT sessions now complete deterministically on closed input, transcribe through the configured STT model/session config, and no longer leave the multi-turn pipeline hanging forever on already-closed streams.
Codex.Voice.Resultno longer exposes deadtotal_output_textbookkeeping;add_text/2is now side-effect-only.Codex.Realtime.Sessionsend APIs now return{:error, :not_connected}once the websocket is absent instead of silently dropping outbound events.- Realtime now surfaces
response.donefailed status payloads as%Codex.Realtime.Events.ErrorEvent{}(including failures received via raw server events), enabling deterministic skip/error handling in examples. - Realtime handoff demo now uses deterministic function tool choice and correctly skips when realtime model access is unavailable.
- Voice TTS streaming now fails fast on non-success HTTP statuses and stream transport errors instead of silently yielding empty/invalid audio chunks.
- Voice multi-turn example now performs a preflight TTS quota check and skips on quota failures rather than timing out.
- Attachments demo now stages a known-good minimal PNG payload to avoid corruption/decoder drift in downstream tooling.
0.10.1 - 2026-02-11
Changed
AgentRunner.run_streamed/3no longer auto-injects a cancellation token when none is provided; the cancellation token is now purely opt-in.
Fixed
- Renamed internal
ensure_cancellation_token/1tofetch_cancellation_token/1to accurately reflect its read-only semantics.
0.10.0 - 2026-02-11
Added
- CancellationRegistry (
Codex.Execinternal), a supervised cancellation-token registry that owns the backing ETS table and manages token-to-transport mappings safely across processes.
Changed
Codex.Execcancellation token lifecycle now routes through the internalCancellationRegistryinstead of direct multi-process writes to a lazily-created ETS table.
Fixed
- Eliminated intermittent ETS access-rights crashes in thread stream/property flows during cancellation and cleanup paths.
- Added regression coverage for cancellation registry registration, selective unregister behavior, and dead-process pruning.
0.9.0 - 2026-02-11
Added
Codex.Config.Defaultsmodule — single source of truth for every tunable SDK constant (timeouts, buffer sizes, URLs, protocol versions, model names, audio parameters, telemetry IDs, and more). All values are exposed as zero-arity functions; a subset supports runtime override viaApplication.get_env/3.New documentation guides:
guides/07-models-and-reasoning.md— model selection, reasoning-effort levels, automatic coercion, and configuration layersguides/08-configuration-defaults.md— full reference table ofCodex.Config.Defaultstunables with runtime override instructions
Codex.Realtime.Agent.default_model/0— public accessor for the default realtime model name, replacing hardcoded"gpt-4o-realtime-preview"strings.Codex.Test.ModelFixtures— test support module providing canonical model constants (default_model/0,alt_model/0,max_model/0,realtime_model/0,stt_model/0,tts_model/0) so tests stay in sync when defaults change upstream.Codex.ExecThreadStarted metadata enrichment —ThreadStartedevents from the exec transport are now enriched with the effectivemodel,reasoning_effort, andconfig.model_reasoning_effortfrom the activeCodex.Options, filling in values the CLI may omit.Codex.Config.Defaultstest suite (test/codex/config/defaults_test.exs) — 420-line test covering every default value and all runtime-overridable keys.
Changed
Centralized all magic numbers and string literals into
Codex.Config.Defaults— 30+ modules now referenceDefaults.*()instead of inline constants:- Transport timeouts and buffer sizes (
Codex.Exec,Codex.IO.Transport.Erlexec) - MCP protocol constants and timeouts (
Codex.MCP.Client,Codex.MCP.Transport.StreamableHTTP) - App-server timeouts (
Codex.AppServer, Codex.AppServer.Connection, Codex.AppServer.Approvals,Codex.AppServer.Mcp) - OAuth/HTTP timeouts (
Codex.MCP.OAuth) - Retry/backoff parameters (
Codex.Retry, Codex.Thread.Backoff,Codex.RateLimit) - Tool defaults (
Codex.Tools.ShellTool,Codex.Tools.ShellCommandTool,Codex.Tools.FileSearchTool,Codex.Tools.WebSearchTool) - Audio format constants (
Codex.Realtime.Audio) - Voice/TTS/STT defaults (
Codex.Voice.Config.TTSSettings,Codex.Voice.Input,Codex.Voice.Models.OpenAISTT,Codex.Voice.Models.OpenAITTS,Codex.Voice.Models.OpenAIProvider) - URL defaults (
Codex.Config.BaseURL,Codex.Realtime.Config.ModelConfig) - Session/file defaults (
Codex.Sessions,Codex.Files,Codex.Files.Registry) - Stream/run config (Codex.StreamQueue,
Codex.RunResultStreaming,Codex.RunConfig) - Telemetry constants (
Codex.Telemetry) - Config layer stack (Codex.Config.LayerStack)
- Thread options (
Codex.Thread.Options)
- Transport timeouts and buffer sizes (
Refactored
Codex.Modelspresets — model definitions now use shared reasoning-effort templates (@efforts_full,@efforts_mini,@efforts_standard,@efforts_frontier,@efforts_gpt5) and derivemodel/display_namefromidvia compile-timeEnum.map, eliminating ~50 lines of duplication. Shell type map is now derived from presets rather than maintained separately.Codex.Voice.Models.OpenAIProvidernow delegates default model names toOpenAISTT.model_name/0andOpenAITTS.model_name/0instead of duplicating strings.Codex.Realtime.Session.get_model_name/1 now calls
RealtimeAgent.default_model/0instead of hardcoding"gpt-4o-realtime-preview".Examples updated to use
Codex.Models.default_model()andCodex.Realtime.Agent.default_model()instead of hardcoded model strings (conversation_and_resume.exs,live_mcp_and_sessions.exs,live_realtime_voice.exs,live_session_walkthrough.exs).Tests updated to use
Codex.Test.ModelFixturesimports instead of hardcoded model strings acrossexec_test.exs,models_test.exs,options_test.exs,thread_test.exs,agent_test.exs,realtime_integration_test.exs, and all voice model tests.ExDocs now includes a Configuration group listing
Codex.Config.Defaults,Codex.Config.BaseURL,Codex.Config.Overrides, andCodex.Config.OptionNormalizers;Codex.Modelsis added to the Core group.
Fixed
- Realtime sessions no longer emit duplicate
%Codex.Realtime.Events.AgentStartEvent{}on initial connect.AgentStartEventis now emitted onTurnStartedEventonly (whilesession.updateis still sent on connection), and session tests now include regression coverage for the connect-plus-turn sequence.
0.8.0 - 2026-02-10
Added
Realtime handoff execution in
Codex.Realtime.Session:- Handoff tool schema generation — agent
handoffslist is automatically converted totransfer_to_*function tools in thesession.updatepayload handle_handoff_tool_call/3switchesstate.agent, sends newsession.updateconfig, and emits%Events.HandoffEvent{}resolve_handoff_target/4supportsCodex.Handoffstructs (withagent,on_invoke_handoff,input_schema),Codex.Realtime.Agentstructs, and plain mapsget_agent_tools/1merges regular tools and handoff tools;find_tool/2matches%Handoff{tool_name: name}
- Handoff tool schema generation — agent
Codex.IO.Transport behaviour with 10 callbacks (
start/1,start_link/1,send/2,end_input/1,subscribe/2,3,close/1,force_close/1,status/1,stderr/1) providing a unified I/O transport layerCodex.IO.Transport.Erlexec GenServer implementation:
- Task-isolated
safe_call/3viaTaskSupervisor.async_nolinkwith timeout and noproc/death handling - Async
send/end_inputvia IO tasks tracked inpending_callsmap - Tagged subscriber dispatch (
{:codex_io_transport, ref, event}) and legacy dispatch - Queue-based stdout drain with
@max_lines_per_batch 200and:drain_stdoutbackpressure control - Buffer overflow protection with overflow recovery at next newline
- Deferred finalize exit with 25ms delay for late stdout arrival
- Headless timeout auto-shutdown when no subscribers attach
- Bounded stderr buffer with tail-truncation at
max_stderr_buffer_size force_close/1with:exec.stop+:exec.kill(pid, 9)escalation
- Task-isolated
Codex.IO.Buffer — shared line-splitting and JSON-line decoding extracted from triplicated code:
split_lines/1,decode_json_lines/2,decode_complete_lines/1,decode_line/1,iodata_to_binary/1- Replaces identical
split_lines/1copies in Exec, AppServer.Protocol, and MCP.Protocol
Codex.TaskSupport — async task helper with automatic
Codex.TaskSupervisornoproc retry andApplication.ensure_all_startedfallbackasync_nolink/1,2extracted from IO.Transport.Erlexec
Codex.TaskSupervisoradded to application supervision treeVoice TTS
:clientinjection — Added configurable:clientoption toOpenAITTS.new/2for request client injection (testability)
Changed
Codex.Exec migrated to IO.Transport.Erlexec:
- Replaced
start_process/2direct:exec.runwithIO.Transport.Erlexec.start_linkusing tagged subscription ref - Replaced
do_collect/3andnext_stream_chunk/1raw{:stdout, os_pid, chunk}receive with tagged{:codex_io_transport, ref, {:message, line}}events - Replaced direct
:exec.stopinsafe_stop/1with monitor-based shutdown cascade via IO.Transport - Removed
pid,os_pid,bufferfrom internal state; changedstderrfrom list to string; addedtransportandtransport_ref - Deleted
ensure_erlexec_started/0,maybe_put_env/2,iodata_to_binary/1,merge_stderr/1, and remainingsplit_lines
- Replaced
AppServer.Connection migrated to IO.Transport.Erlexec:
- Removed
subprocess_mod,subprocess_opts,subprocess_pid,os_pid,stdout_bufferfrom State; addedtransport_mod,transport, andtransport_ref - Replaced raw erlexec message handlers with tagged transport events
- Deleted
resolve_subprocess_module/1,resolve_subprocess_opts/1,ensure_erlexec_started/1,start_opts/1
- Removed
MCP.Transport.Stdio migrated to IO.Transport.Erlexec (same pattern as Connection)
Transport lifecycle hardening (Codex.Exec):
safe_stop/1now uses monitor-based graceful shutdown escalation:force_close→Process.exit(:shutdown)→Process.exit(:kill)with configurable grace periods (2s / 250ms / 250ms)- Added
flush_transport_messages/1to drain tagged events after shutdown - Simplified
send_prompt/2from with-chain to case-chain - Extracted
decode_event_map/1with function-level rescue (was inlinetry/rescueindecode_line)
Transport module dispatch (Connection, MCP.Transport.Stdio):
- Added
transport_modfield to State structs for dynamic transport dispatch - Added guard clauses to
send_iolist/2andstop_subprocess/1for disconnected transport safety - Connection: refactored
resolve_transport/1intonormalize_transport_option/2andnormalize_transport_value/2clause chain
- Added
IO.Transport.Erlexec
init/1simplified from with-chain to case expressionnormalize_payload/1split: lists tryIO.iodata_to_binaryfirst, falling back toJason.encode!onArgumentError; added map-specific clauseConfig.merge_settingstool serialization refactored intoserialize_tool/1to handle non-struct toolsRewired Exec, AppServer.Protocol, and MCP.Protocol to delegate line-splitting/decoding to
Codex.IO.BufferExample hardening (all realtime examples):
- Added
main/0entry points with:ok/{:skip, reason}/{:error, reason}return pattern insufficient_quotadetection and gracefulSKIPPED:output instead ofSystem.halt(1)safe_close/1with rescue in all session teardown paths- Stats/audit collection replacing raw event printing in
realtime_basic.exs,live_realtime_voice.exs, andlive_app_server_approvals.exs Realtime.send_audio/3calls updated withcommit: trueon final chunk- Voice example (
voice_multi_turn.exs): replacedTask.await(output_task, :infinity)withTask.yield/2+Task.shutdown/2using 60s timeout
- Added
Voice TTS
instructionsfield —maybe_add_instructions/2now putsinstructionsas a top-level request body field instead of nesting underextra_bodyUpdated README, getting-started guide, API guide, examples guide, and realtime-and-voice guide to reflect new handoff patterns
Removed
- Deleted
lib/codex/app_server/subprocess.exandlib/codex/app_server/subprocess/erlexec.ex(superseded by IO.Transport) - Deleted triplicated
split_lines/1,decode_lines,decode_lineprivate functions from Exec, AppServer.Protocol, and MCP.Protocol
Fixed
Config.merge_settingsnow preserves explicit falsy override values (was using||which droppedfalse; changed toif is_nil(override_val))- Voice TTS instructions sent as top-level request body field instead of nested under
extra_body - Stderr test race condition resolved with sleep+ordering adjustment
- Stdio transport test fixed to track correct PIDs (fake vs wrapper)
- Added
Kernel.send/2import guards in test fakes to avoid Transport behavioursend/2conflicts - Updated log assertion to match Buffer module wording
- Buffer decode_line test updated to use sigil syntax
- Added
@moduletag :capture_logto BufferTest - Init failure test fixed to assert specific error tuple
0.7.2 - 2026-02-06
Fixed
- OTLP enablement now honors
CODEX_OTLP_ENABLEvalues like1/0at runtime, including startup banner reporting and telemetry configuration defaults.
Changed
- Bumped project version metadata to
0.7.2inmix.exs,VERSION, README install snippet, and getting-started guide.
0.7.1 - 2026-02-06
Changed
- Bumped
websockexfrom~> 0.4.3to~> 0.5.1(adds telemetry integration) - Bumped
credofrom 1.7.15 to 1.7.16 - Bumped
ex_docfrom 0.40.0 to 0.40.1
0.7.0 - 2026-02-06
Added
Realtime API: Full integration with OpenAI Realtime API for bidirectional voice interactions
Codex.Realtimemodule with agent builder and session orchestrationCodex.Realtime.SessionWebSocket GenServer via WebSockex with reconnection, PubSub event broadcasting, and trapped linked-socket exitsCodex.Realtime.Runnerfor high-level agent session management with automatic tool call handling, handoff execution, and guardrail integrationCodex.Realtime.Agentstruct and builder functions for agent configuration (instructions, tools, handoffs)- Session-level and model-level event types (
Codex.Realtime.Events) for comprehensive event handling - Configuration structs:
RealtimeSessionConfig,RealtimeModelConfig,TurnDetectionConfig,InputAudioTranscription - Core types:
Codex.Realtime.Audio(PCM16/G711),Codex.Realtime.Item,PlaybackTracker - Semantic VAD turn detection with
eagernessparameter (:low,:medium,:high),silence_duration_ms, andprefix_padding_ms - Idempotent
subscribe/unsubscribewith map-based subscriber tracking - Tool calls run outside the session callback path so other session messages stay responsive
Voice Pipeline: Non-realtime STT -> Workflow -> TTS pipeline
Codex.Voice.Pipelinefor single-turn and multi-turn voice flows with asyncTask-based executionCodex.Voice.Resultfor streamed audio output handlingCodex.Voice.Workflowbehaviour,Codex.Voice.SimpleWorkflow(function-based), andCodex.Voice.AgentWorkflow(wrappingCodex.Agent)- Multi-turn conversation history management and optional greeting support
- STT model behaviour (
Codex.Voice.Model.STTModel) with OpenAI implementation (gpt-4o-transcribe) - TTS model behaviour (
Codex.Voice.Model.TTSModel) with OpenAI implementation (gpt-4o-mini-tts) Codex.Voice.Model.ModelProviderbehaviour for model factoriesCodex.Voice.Input.AudioInputfor single audio buffers andStreamedAudioInputfor streamingCodex.Voice.Eventsfor voice stream events (audio, lifecycle, error)Codex.Voice.Configfor pipeline configuration with STT/TTS settings- WAV encoding utilities for audio file handling
Options-level global config overrides (
Codex.Options.config_overrides/config)- Emitted before derived/thread/turn overrides in exec CLI args and app-server config payload
- Four-layer precedence: options-level < derived < thread < turn
- Input aliases
configandconfig_overrideswith nested map auto-flattening
Config override runtime validation (
Overrides.validate_overrides/1)- Validates TOML-compatible types: strings, booleans, integers, floats, arrays, nested maps
- Rejects
nil, tuples, PIDs, functions, and non-finite floats with{:error, {:invalid_config_override_value, path, value}} Propagated through
build_args/config_override_argsvia{:ok, _} | {:error, _}return paths in Exec
:nonepersonality variant acrossConfigTypes,Options,Thread.Options, exec, and app-server- Encode/decode round-trip,
AppServer.Params.personality/1clauses for:none/"none" - Works consistently on both exec CLI and app-server transports
- Encode/decode round-trip,
Nested config override auto-flattening (
Overrides.flatten_config_map/1)- Recursive map-to-dotted-path flattening (e.g.,
%{"model" => %{"personality" => "friendly"}}→[{"model.personality", "friendly"}]) - Auto-detected in
normalize_config_overridesfor both exec and thread options - Deduplicated normalizer shared between
ExecandThread.OptionsviaOverrides.normalize_config_overrides/1
- Recursive map-to-dotted-path flattening (e.g.,
Explicit web search disable tracking —
Thread.Optionstracksweb_search_mode_explicitto distinguish user-set:disabledfrom default:disabled; only emitsweb_search="disabled"override when explicitly setSDK originator environment variable —
CODEX_INTERNAL_ORIGINATOR_OVERRIDE=codex_sdk_elixirset inRuntime.Env.base_overrides/2viaMap.put_new(caller can override inenv)Shared runtime modules extracted from duplicated patterns:
Codex.Runtime.Erlexec— unified erlexec startup across Exec, Connection, Sessions, ShellTool, and MCP StdioCodex.Runtime.Env— subprocess environment construction shared between Exec and AppServer.ConnectionCodex.Runtime.KeyringWarning— deduplicated warn-once logic from Auth and MCP.OAuthCodex.Config.BaseURL—OPENAI_BASE_URLenv fallback with explicit option precedence (option → env → default)Codex.Config.OptionNormalizers— shared reasoning summary, verbosity, and history persistence validation across Options and Thread.Options
Process lifecycle hardening:
- Supervised
MetricsHeirGenServer replacing ad-hoc spawn/register for tool metrics ETS heir - Concurrent stage call coalescing in
Files.Registryviapending_stage_requestsmap - Expired entry collection moved into work queue tasks (non-blocking Registry GenServer)
drain_waiters/2in MCP Stdio transport for subprocess exit- Monitor-based cleanup for
StreamQueuepop waiters andOpenAISTTSessiontranscript waiters on caller DOWN Task.startoverTask.start_linkin StreamableHTTP and RunResultStreaming fallback paths (avoids cascade crashes)async_nolinkvia ephemeralTaskSupervisorinVoice.PipelineStreamQueue-backed queues replacing Agent-backed queues inVoice.ResultandStreamedAudioInput(backpressure + close semantics)StreamQueue.try_pop/1for non-blocking dequeueets.select_deletereplacingets.foldlinApprovals.Registry- Drain pending tool calls in
Realtime.Session.terminate/1
- Supervised
Concurrency and safety improvements:
- Work queue in
Files.Registryfor non-blocking file I/O - WebSocket exits trapped in
Realtime.Session; tool calls run outside callback path - Idempotent subscribe/unsubscribe with map-based subscriber tracking
terminate/1cleanup forStreamableHTTP,Registry, andSTTSessionString.to_existing_atomreplacingString.to_atominConfig.Overrides(atom safety)- Explicit key maps in
ToolOutputto avoid atom interning from untrusted input - ETS heir process for tool metrics table survival across owner restarts
- Atomic tool registration via
insert_newinTools.Registry - Lazy-start
ConnectionSupervisorinAppServer.connect
- Work queue in
Hardcoded local preset for
gpt-5.3-codexas the unified SDK default modelconfig_override,config_override_value, andconfig_override_scalartype specs added toOverrides,Options, andThread.OptionsCodex.Files.list_staged_result/0for explicit{:ok, list} | {:error, reason}responsesMain SDK integration: realtime/voice error types in
Codex.Error, telemetry events for session and pipeline lifecycle, delegation functions in mainCodexmoduleExamples:
live_realtime_voice.exs: Full realtime voice interaction demorealtime_basic.exs: Simple realtime session setuprealtime_tools.exs: Function calling with realtime agentsrealtime_handoffs.exs: Multi-agent handoffs in realtime sessionsvoice_pipeline.exs: Basic STT -> Workflow -> TTS pipelinevoice_multi_turn.exs: Multi-turn streaming conversationsvoice_with_agent.exs: UsingCodex.Agentwith voice pipelineslive_config_overrides.exs: Nested config override auto-flattening (thread and turn level)live_options_config_overrides.exs: Options-level global config overrides, precedence, and validationlive_personality.exs: Updated to exercise all three personality variants including:none
Changed
- Default model updated to
gpt-5.3-codexacross all credential sources (local presets, upgrade metadata, bundledpriv/models.json) - Removed auth-aware default logic (chatgpt vs api key split) and
codex-auto-balancedpreference for chatgpt auth Codex.Files.force_cleanup/0,reset!/0, andmetrics/0return{:error, reason}if the registry is unavailableCodex.Files.Registry.ensure_startedandAppServer.ensure_connection_supervisorrequire application supervision- MCP transport failures normalized to
{:error, reason}tuples - Unified Realtime/Voice API key resolution through
Codex.Authprecedence chain (CODEX_API_KEY→auth.json OPENAI_API_KEY→OPENAI_API_KEY) - Replaced
live_realtime_voice_stub.exsplaceholder with working implementation - Bumped
supertesterto~> 0.5.1
Fixed
String.to_atomreplaced withString.to_existing_atominConfig.Overridesto prevent atom table exhaustion from untrusted input- Explicit key maps in
ToolOutputto avoid atom interning from untrusted config payloads - Web search disable override no longer emitted when defaults are untouched (only when explicitly set via
web_search_mode: :disabledorweb_search_enabled: false) - Removed hardcoded
http_client/0helper fromWebSearchTool
Documentation
- Added Realtime and Voice guide (
guides/06-realtime-and-voice.md) and sections to examples/README.md - Documented four-layer config override precedence (options < derived < thread < turn) in README and guides
- Documented
:nonepersonality variant, SDK originator env, and explicit web search disable behavior - Updated hexdocs module groups to include all Realtime, Voice, and shared runtime modules
0.6.0 - 2026-01-23
Added
- Protocol types for text elements, collaboration modes, request_user_input, elicitation, rate limit snapshots, and config enums
- Event structs for session configuration, user input requests, MCP startup updates, elicitation requests, undo/rollback, review mode, config warnings, and collaboration lifecycle updates
- Thread/turn options: web search modes, personality overrides, collaboration modes, compact prompts, raw reasoning toggle, and per-thread output schemas
- Global options: model personality, auto-compact token limit, review model, hide agent reasoning, tool output token limit, and max agent threads
- Reasoning effort levels
:minimaland:xhigh - App-server APIs for thread fork/read/rollback/loaded list, skills config writes, config requirements, collaboration modes, app listing, and MCP reloads
- App-server params for personality, output schemas, and collaboration modes on thread start/resume and turn start
- Rate limit snapshots parsed from token usage updates and stored on threads
- Live examples covering collaboration modes, personality, web search modes, thread management, and rate limit monitoring
Changed
- Web search config handling now prefers
web_search_modewhile honoring config defaults and feature gating - Account rate limit notifications normalize to rate limit snapshot types
- Output schemas can be configured at the thread level with turn-level overrides
- Restructured and streamlined guides
Fixed
- App-server connections stop spawned subprocesses on initialize-send failures and ignore invalid subscriber filters
- Files/approval registries are supervised, with staged attachments cleared on registry startup to prevent orphans
- Streamable HTTP transport and streaming producers avoid blocking GenServer callbacks by running work in tasks
Deprecated
web_search_enabledonCodex.Thread.Options(useweb_search_modeinstead)
0.5.0 - 2025-12-31
Added
- Typed model options for reasoning summaries/verbosity/context window/supports reasoning summaries
- Provider tuning options (
request_max_retries,stream_max_retries,stream_idle_timeout_ms) - Exec config overrides for model provider/instructions, sandbox policy details, shell env policy, and feature flags
- Opt-in retry/rate-limit handling for exec and app-server transports
- Thread rate limit snapshot storage (
thread.rate_limits+Thread.rate_limits/1) - Exec stream idle timeout handling
- Keyring auth detection with warnings when unsupported
- Forced login enforcement for app-server login flows
- Config layer parsing for dotted core keys and
model_provider - Exec JSONL parsing for account notifications (
account/updated,account/login/completed,account/rateLimits/updated) - App-server protocol parity: thread resume
history/path, skills reload, and fuzzy file search helper - Raw response item structs (ghost snapshots/compaction) plus
rawResponseItem/completedanddeprecationNoticeevents - Session helpers for metadata preservation, apply, and undo workflows
- History persistence options on
Codex.OptionsandCodex.Thread.Options - Legacy app-server v1 conversation helpers (
Codex.AppServer.V1) - Hosted tooling parity:
shell_command,write_stdin, andview_imagetools plus aliases (container.exec,local_shell) - Guardrail parallel execution and tool behavior semantics (
reject_content,raise_exception) - MCP JSON-RPC client with stdio + streamable HTTP transports plus resources/prompts listing
- MCP OAuth credential storage/refresh helpers and MCP config helpers (
Codex.MCP.Config) - Skills and custom prompt helpers (
Codex.Skills,Codex.Prompts) with prompt expansion rules
Changed
- Exec JSONL now uses
--json(alias of--experimental-json) - Exec no longer passes sandbox/approval defaults unless explicitly configured
- Exec transport failures normalize into
Codex.Errorat thread level - Config parsing now validates core config keys (features/history/shell env/auth store)
Codex.MCP.Clientnow speaks MCP JSON-RPC (initialize,tools/list,tools/call)- Shell tool schema now uses argv arrays with
workdir/timeout_ms(legacy string commands remain supported) - ApplyPatch supports
*** Begin Patchgrammar with add/update/delete/move, retaining unified diff fallback - WebSearch schema now supports
actionarguments and honorsfeatures.web_search_requestgating
Documentation
- Updated README, API reference, and transport guides for MCP/skills/prompts parity
0.4.5 - 2025-12-30
Added
- Shell hosted tool with
Codex.Tools.ShellToolfor executing shell commands - Built-in default executor using erlexec for real command execution
- Command timeout support with configurable
:timeout_msoption (default: 60s) - Output truncation with configurable
:max_output_bytesoption (default: 10KB) - Working directory support via
cwdargument or:cwdoption - Approval integration for shell commands via
:approvalcallback - Custom executor support for testing and mocking shell behavior
- MCP tool discovery with
Codex.MCP.Client.list_tools/2andqualify?: trueoption - Tool name qualification with
mcp__<server>__<tool>format matching upstream Rust implementation - Tool name truncation with SHA1 hash suffix for names exceeding 64 characters
qualify_tool_name/2public function for standalone tool name qualificationserver_nameoption forCodex.MCP.Client.handshake/2to enable qualified tool names- Allow/deny list filtering for MCP tools via
:allowand:denyoptions - Tool caching with configurable bypass via
cache?: false - Duplicate qualified name deduplication (skips duplicates like upstream)
- MCP tool invocation with
Codex.MCP.Client.call_tool/4 - ApplyPatch hosted tool with
Codex.Tools.ApplyPatchTool - Unified diff parsing and application for file create/modify/delete operations
- Dry-run support for patch validation without file modification
- Approval integration for file modifications via
:approvalcallback - Exponential backoff retry logic for MCP calls (default 3 retries, 100ms base delay, 5s max)
- Approval integration for MCP tool calls via
:approvalcallback option - Timeout control for MCP tool calls via
:timeout_msoption (default 60s) - Comprehensive retry module
Codex.Retrywith configurable backoff strategies - Support for exponential, linear, constant, and custom backoff strategies
- Jitter support for retry delays to prevent thundering herd
- Customizable retry predicates via
:retry_ifoption on_retrycallbacks for logging and observability- Stream retry support via
Codex.Retry.with_stream_retry/2 Codex.TransportErrornow includesretryable?field for automatic retry classification- Telemetry events for MCP tool invocation:
[:codex, :mcp, :tool_call, :start]- When a tool call begins[:codex, :mcp, :tool_call, :success]- On successful completion[:codex, :mcp, :tool_call, :failure]- On failure after retries exhausted
- Rate limit detection with
Codex.RateLimit.detect/1for automatic rate limit identification - Rate limit handling with configurable backoff via
Codex.RateLimit.with_rate_limit_handling/2 - Retry-After header parsing supporting both map and list header formats
- Rate limit telemetry events (
[:codex, :rate_limit, :rate_limited]) - Configurable rate limit delays via
:rate_limit_default_delay_ms,:rate_limit_max_delay_ms, and:rate_limit_multiplier Codex.Error.rate_limit/2constructor for creating rate limit errors with retry hintsCodex.Error.rate_limit?/1predicate for checking if an error is a rate limit errorCodex.Error.retry_after_ms/1for extracting retry-after hints from errorsretry_after_msfield onCodex.Errorstruct for rate limit retry hints- FileSearch hosted tool with
Codex.Tools.FileSearchToolfor local filesystem search - Glob pattern matching for file discovery (
**/*.ex,*.{ex,exs}, etc.) - Content search with regex support for finding text within files
- Case-sensitive/insensitive search modes via
case_sensitiveoption - Configurable result limits via
max_resultsoption (default: 100) - Renamed
FileSearchTool(vector store) toVectorStoreSearchToolfor clarity - WebSearch hosted tool with
Codex.Tools.WebSearchToolfor performing web searches - Support for Tavily and Serper search providers via
:provideroption - Mock provider for testing without API keys (
:provider => :mock) - HTTP client abstraction with
Codex.HTTPClientfor testability - Custom searcher callback support for backwards compatibility and flexibility
- Configurable max results via
max_resultsargument or:max_resultsoption
Changed
Codex.MCP.Clientstruct now includesserver_namefield for tool qualificationcall_tool/4now uses exponential backoff by defaultcall_tool/4default retries changed from 0 to 3 for improved resilienceCodex.Retry.retryable?/1now recognizesCodex.Errorwith:rate_limitkind as retryableCodex.Events.AccountRateLimitsUpdatednow includes optionalthread_idandturn_idfields
Fixed
Documentation
- Added MCP Tool Discovery section to README with qualification examples
- Updated
Codex.MCP.Clientmodule documentation with tool name qualification details - Added comprehensive
call_tool/4documentation with examples for retries, backoff, approval, and telemetry
0.4.4 - 2025-12-29
Added
- App-server
UserInputlist support forCodex.Thread.run/3andrun_streamed/3(text/image/localImage) - Thread/turn app-server params for model/provider/config/instructions, sandbox_policy, and experimental raw events, with defaults for model + reasoning effort
- Typed app-server notifications for reasoning summaries/deltas, command/file output deltas, terminal interaction, MCP progress, and account updates
- Exec CLI parity flags (
--profile,--oss,--local-provider,--full-auto,--dangerously-bypass-approvals-and-sandbox,--output-last-message,--color) - Generic
-c key=valueconfig overrides, exec review wrapper, and resume --last support - Grant-root approval handling for file changes and
Codex.AppServer.command_write_stdin/4
Changed
- Reasoning items now preserve
summary/contentstructure instead of flattened text - App-server
turn.errorpayloads are surfaced onCodex.Events.TurnCompleted
Fixed
- Streamed turn failures now handle non-text
final_responsepayloads without crashing and includeturn.errordetails when present - Structured
/newinput blocks now reset conversation state for app-server/exec turn runs and streams - Tool guardrail and approval hook exceptions are surfaced as errors instead of crashing the turn
- Progress telemetry metadata now merges even when base metadata is nil
Documentation
- Updated README and API reference for new input types, exec flags, and app-server deltas
0.4.3 - 2025-12-27
Added
- App-server error notifications now expose
additional_detailsand retry metadata - Config layer loader that honors system/user/project
config.tomlsources
Changed
- Remote models gating now respects
/etc/codex/config.tomland.codex/config.tomllayers priv/models.jsonsynced to latest upstream format
Documentation
- Documented config layer precedence for remote model gating in README/examples
0.4.2 - 2025-12-20
Added
- Internal
Constrainedmodule for wrapping configuration values with validation constraints - Internal
ConstraintErrorexception for reporting constraint violations :external_sandboxsandbox mode for containerized/external sandbox environments{:external_sandbox, :enabled | :restricted}tuple variant with explicit network access control- Support for
:adminskill scope (reads from/etc/codex) - pass-through from CLI - Support for
short_descriptionfield in skill metadata - pass-through from CLI
Changed
- Updated bundled
priv/models.jsonto upstream (commits d7ae342ff..987dd7fde) - Model presets updated:
gpt-5.1-codex-max: priority 0 → 1, now upgrades togpt-5.2-codexgpt-5.1-codex-mini: visibility:list→:hide(hidden by default)gpt-5.1-codex: visibility now:hidegpt-5.1: now upgrades togpt-5.2-codex
Fixed
- Normalize signal-based exits to conventional shell exit codes (
128 + signal) when reportingCodex.TransportError
Documentation
- Added
docs/20251220/directory with comprehensive porting plan and validation
Internal
- Synced with upstream codex-rs commits d7ae342ff..987dd7fde (32 commits)
- Added constraint system aligned with upstream
Constrained<T>type
0.4.1 - 2025-12-18
Added
- Auth-aware model defaults (ChatGPT
gpt-5.2-codex, APIgpt-5.1-codex-max) withcodex-auto-balancedpreference when remote models are enabled - Full model registry port with local presets, upgrade metadata, and reasoning effort normalization including
none - Remote model support behind
features.remote_models, with bundledmodels.jsonparsing and cache handling
Changed
- API key handling now prioritizes
CODEX_API_KEYandauth.jsonOPENAI_API_KEY; ChatGPT tokens no longer populateapi_key - Documentation and examples updated for the new defaults, model list, and remote model behavior
0.4.0 - 2025-12-17
Breaking Changes
Codex.AppServer.thread_compact/2now returns{:error, {:unsupported, _}}- the upstreamthread/compactAPI was removed; compaction is now automatic
Changed
Codex.AppServer.Mcp.list_servers/2now usesmcpServerStatus/listmethod with automatic fallback to legacymcpServers/listfor older servers- Added
Codex.AppServer.Mcp.list_server_statuses/2as an alias
Documentation
- Updated app-server transport guide to reflect removed
thread/compactAPI - Added skills feature flag prerequisite documentation
- Added
.codex/sandbox read-only behavior note - Updated config layer schema documentation for
ConfigLayerSourcetagged union
0.3.0 - 2025-12-14
Added
- Multi-transport refactor: exec JSONL remains the default, and a new app-server JSON-RPC (stdio) transport is available via
transport: {:app_server, conn} Codex.AppServerconnection API plus v2 request wrappers (threads, turns, skills, models, config, review, command exec, feedback, account, MCP)- Stateful approval handling for app-server server-initiated requests (
item/*/requestApproval) with both hook-based auto-approval and manualrespond/3 - Typed event/item adapters for core app-server notifications, with lossless passthrough for unknown methods/items
Changed
turn/diff/updatednow surfacesdiffas a unified diff string (app-server v2)
Fixed
- App-server default subprocess selection and iodata sending for stdio writes
0.2.5 - 2025-12-13
Fixed
- Quieted
mix testoutput by default (test log capture + console logger level) while keeping logs available on failures - Fixed an ETS race in tool registry resets that could intermittently fail in async tests
0.2.4 - 2025-12-13
Added
examples/run_all.shdefaults togpt-5.1-codex-minifor consistent runs and reports failures without stopping the whole suite
Fixed
- Exec subprocess env inheritance so
codexcan use CLI-login auth when no env overrides are provided - Structured output example schema compatibility with
codex exec --output-schema, plus clearer example error output - Concurrency example progress output and timeouts to avoid “stuck” runs
0.2.3 - 2025-12-13
Added
- Forwarded Codex CLI execution options via
Codex.Thread.Options: sandbox mode, working directory, additional writable directories, skip-git-repo-check, web search toggle, approval policy, and workspace-write network access turn_opts[:clear_env?]to optionally clear inherited subprocess environment when spawningcodex
Changed
OPENAI_BASE_URLis now set for thecodexsubprocess fromCodex.Options.base_url- Port gap analysis docs updated to reflect the wired Codex CLI surface and erlexec hardening option
0.2.2 - 2025-12-13
Added
auto_previous_response_idrun option viaCodex.RunConfig(forward-compatible; requires backendresponse_idsupport)last_response_idonCodex.Turn.Resultwhen the backend surfaces a response identifier
Changed
- README/docs now distinguish Elixir-side OTLP exporting from codex-rs
[otel]config.toml exporting
Fixed
- Tool metadata is loaded before registration so hosted tools register under their declared names (e.g.
file_search) - Exec CLI arg compatibility: image attachments now use
--image, and unsupported--tool-output/--tool-failureflags are no longer emitted
0.2.1 - 2025-11-29
Added
- App-server event coverage for token usage deltas, turn diffs, and compaction notices, plus explicit thread/turn IDs on item and error notifications
- Streaming example updates to surface live usage and diff events alongside item progress
- Automatic auth fallback to Codex CLI login when API keys are absent; live two-turn walkthrough example
- Regression tests and fixtures for
/newresets, early-exit session non-persistence, and rate-limit/sandbox error normalization - Live usage/compaction streaming example aligned with new model defaults and reasoning effort handling
- Live exec controls example (env injection, cancellation tokens, timeout tuning) plus README/docs updates covering safe-command approval bypass
- Sandbox warning normalization updates (Windows read-only
.gitdetection, world-writable dedup) and runnable examplesandbox_warnings_and_approval_bypass.exs - README/docs refresh covering policy-approved bypass flags and normalized sandbox warning strings
- Added
examples/live_tooling_stream.exsto showcase streamed MCP/shell events and fallback handling whenturn.completedomits a final response - Live telemetry stream example (thread/turn IDs, source metadata, usage deltas, diffs, compaction savings) with README/docs references
- Live telemetry stream defaults tuned for fast runs (minimal reasoning, short prompt)
Changed
- Thread resumption now uses
codex exec … resume <thread_id>(no--thread-idflag) /newclears conversations and early-exit turns do not persist thread IDs, matching upstream CLI- Turn failures normalize rate-limit and sandbox assessment errors into
%Codex.Error{} - Telemetry now propagates source info, thread/turn IDs, OTLP mTLS options, and richer token/diff/compaction signals through emitters and OTEL spans
0.2.0 - 2025-10-20
Added
- Core Codex thread lifecycle with streaming, resumption, and structured output decoding (
Codex.Thread,Codex.Turn.Result,Codex.Events,Codex.Items) - GenServer-backed
Codex.Execprocess supervision, error handling, and tool invocation pipeline - Approval policies, hook behaviour, registry support, and telemetry events for tooling approvals
- File staging registry, attachment helpers, parity fixtures, and harvesting script for Python SDK alignment
- Comprehensive telemetry module with OTLP exporter gating, metrics, and approval instrumentation
- Mix tasks (
mix codex.verify,mix codex.parity), integration tests, and Supertester-powered contract suite - Rich examples and documentation covering approvals, streaming, concurrency, observability, and design dossiers
Changed
- Refreshed
README.mdwith 0.2.0 usage guide, testing workflow, and observability configuration - Expanded HexDocs configuration to include new guides, design notes, and release documentation
- Updated package metadata to ship changelog, examples, and assets with the Hex release
0.1.0 - 2025-10-11
Initial design release.