# Why `notify` is the remaining compatibility surface from the legacy hook implementation. The newer lifecycle hook engine now owns the active hook system, so we should start steering users away from adding new `notify` configs before removing the old path entirely. This also adds a lightweight watchpoint for the deprecation so we can see how much legacy usage remains before the clean drop. # What - emit a startup deprecation notice when a non-empty `notify` command is configured - emit `codex.notify.configured` when a session starts with legacy `notify` configured - emit `codex.notify.run` when the legacy notify path fires after a completed turn - mark `notify` as deprecated in the config schema and repo docs - remove the orphaned `codex-rs/hooks/src/user_notification.rs` file that is no longer compiled - add regression coverage for the new deprecation notice # Next steps A follow-up PR can remove the legacy notify path entirely once we are ready for the clean drop. Before then, we can watch `codex.notify.configured` and `codex.notify.run` to understand the deprecation impact and remaining active usage. The cleanup PR should then delete the `notify` config field, the `legacy_notify` implementation, the old compatibility dispatch types and callsites that only exist for the legacy path, and the remaining compatibility docs/tests. # Testing - `cargo test -p codex-hooks` - `cargo test -p codex-config` - `cargo test -p codex-core emits_deprecation_notice_for_notify`
5.0 KiB
Configuration
For basic configuration instructions, see this documentation.
For advanced configuration instructions, see this documentation.
For a full configuration reference, see this documentation.
Connecting to MCP servers
Codex can connect to MCP servers configured in ~/.codex/config.toml. See the configuration reference for the latest MCP server options:
MCP tools default to serialized calls. To mark every tool exposed by one server
as eligible for parallel tool calls, set supports_parallel_tool_calls on that
server:
[mcp_servers.docs]
command = "docs-server"
supports_parallel_tool_calls = true
Only enable parallel calls for MCP servers whose tools are safe to run at the same time. If tools read and write shared state, files, databases, or external resources, review those read/write race conditions before enabling this setting.
MCP tool approvals
Codex stores approval defaults and per-tool overrides for custom MCP servers
under mcp_servers in ~/.codex/config.toml. Set
default_tools_approval_mode on the server to apply a default to every tool,
and use per-tool approval_mode entries for exceptions:
[mcp_servers.docs]
command = "docs-server"
default_tools_approval_mode = "approve"
[mcp_servers.docs.tools.search]
approval_mode = "prompt"
Apps (Connectors)
Use $ in the composer to insert a ChatGPT connector; the popover lists accessible
apps. The /apps command lists available and installed apps. Connected apps appear first
and are labeled as connected; others are marked as can be installed.
Codex stores "never show again" choices for tool suggestions in config.toml:
[tool_suggest]
disabled_tools = [
{ type = "plugin", id = "slack@openai-curated" },
{ type = "connector", id = "connector_google_calendar" },
]
Notify
notify is deprecated and will be removed in a future release. Existing configurations still work for compatibility, but new automation should use lifecycle hooks instead.
Codex can run a legacy notification command when the agent finishes a turn. See the configuration reference for the latest notification settings:
When Codex knows which client started the turn, the legacy notify JSON payload also includes a top-level client field. The TUI reports codex-tui, and the app server reports the clientInfo.name value from initialize.
JSON Schema
The generated JSON Schema for config.toml lives at codex-rs/core/config.schema.json.
SQLite State DB
Codex stores the SQLite-backed state DB under sqlite_home (config key) or the
CODEX_SQLITE_HOME environment variable. When unset, WorkspaceWrite sandbox
sessions default to a temp directory; other modes default to CODEX_HOME.
Custom CA Certificates
Codex can trust a custom root CA bundle for outbound HTTPS and secure websocket
connections when enterprise proxies or gateways intercept TLS. This applies to
login flows and to Codex's other external connections, including Codex
components that build reqwest clients or secure websocket clients through the
shared codex-client CA-loading path and remote MCP connections that use it.
Set CODEX_CA_CERTIFICATE to the path of a PEM file containing one or more
certificate blocks to use a Codex-specific CA bundle. If
CODEX_CA_CERTIFICATE is unset, Codex falls back to SSL_CERT_FILE. If
neither variable is set, Codex uses the system root certificates.
CODEX_CA_CERTIFICATE takes precedence over SSL_CERT_FILE. Empty values are
treated as unset.
The PEM file may contain multiple certificates. Codex also tolerates OpenSSL
TRUSTED CERTIFICATE labels and ignores well-formed X509 CRL sections in the
same bundle. If the file is empty, unreadable, or malformed, the affected Codex
HTTP or secure websocket connection reports a user-facing error that points
back to these environment variables.
Notices
Codex stores "do not show again" flags for some UI prompts under the [notice] table.
Plan mode defaults
plan_mode_reasoning_effort lets you set a Plan-mode-specific default reasoning
effort override. When unset, Plan mode uses the built-in Plan preset default
(currently medium). When explicitly set (including none), it overrides the
Plan preset. The string value none means "no reasoning" (an explicit Plan
override), not "inherit the global default". There is currently no separate
config value for "follow the global default in Plan mode".
Realtime start instructions
experimental_realtime_start_instructions lets you replace the built-in
developer message Codex inserts when realtime becomes active. It only affects
the realtime start message in prompt history and does not change websocket
backend prompt settings or the realtime end/inactive message.
Ctrl+C/Ctrl+D quitting uses a ~1 second double-press hint (ctrl + c again to quit).