Codex CLI Starts a Self-Updating Daemon by Default. The config.toml Switch Is Not in the Docs.
Since 0.157.0, an interactive Codex session can leave behind a background server and an hourly updater. The latest release, 0.162.1, still ships it on. The opt-out key is absent from OpenAI's config reference, and the org-wide pin lives in requirements.toml.
Codex CLI 0.157.0, released on 25 September, carried a one-line release note:
automatic background-server startup is now enabled for eligible interactive
sessions. Eleven stable releases later the default has not moved. In the source tagged
for 0.162.1, published on 9 October and the current release, the feature
registry lists daemon_auto_start as a stable feature with
default_enabled: true. An issue asking to make it opt-in, opened the day the
change shipped, is still open and drew a fresh run of comments on 12 October.
A second report, filed today against 0.162.1, says the daemon leaks
environment variables across sessions.
This post is about the codex config.toml line that turns it off, why that line alone does not clean up a machine, and why a team that rolls Codex out through a package manager should treat 0.157.0 as a change in what software it runs, not a CLI update.
What turned on in 0.157.0
The issue's reporter, on 0.157.0 installed with npm under WSL2, describes four
behaviours. Opening an interactive session starts a background app server that
keeps running after every Codex window is closed. The CLI copies its whole
platform package, about 374 MB by their measurement, into a release directory
under ~/.codex/packages/app-server-daemon/ and runs the daemon from that copy,
so the server version is no longer the one the package manager installed. A
detached updater checks for new releases and restarts the server. And the
daemon keeps the proxy variables of whichever session launched it.
The daemon's own README, at the 0.162.1 tag, confirms two of these as design
rather than accident. It says shared clients use the environment inherited
when the daemon started, and that per-client environment isolation is not
provided. It also says eligible managed daemons check for updates five minutes
after start and then hourly, that an update restarts a running daemon so
active or queued work may be interrupted, and that the updater uses saved
network settings, so command-line -c overrides do not reach it. The copy is
in the code too: the daemon's start command prepares a missing install by
copying the running CLI's package into packages/app-server-daemon under the
Codex home, through a confirmation callback that always answers yes.
The startup code shows which sessions are eligible. Auto-start is skipped when
the feature is off, when --no-daemon is passed, for the agents overview, and
for a remote workspace target. Later checks skip it during Bedrock sign-in
setup and for WSL homes on a Windows-mounted drive, the second added in 0.162.0. Everything
else gets the daemon.
The question the issue left open: why stop does not stop it
The reporter found that codex app-server daemon stop stopped the server but
left the pid-update-loop updater alive, and killed it by hand. The source
explains why. The stop lifecycle command in the daemon library stops the
app-server process and nothing else. The updater is a separate loop with no
check on whether the server it updates is still running. Outside of handing
itself off to a new release, it exits on a termination signal, or when it
wakes for its next scheduled check and finds auto-update disabled in
CODEX_HOME/app-server-daemon/settings.json.
So pkill alone is not the durable fix, because the next managed start
launches the updater again. Set updater.autoUpdateEnabled to false in that
settings file and the updater removes itself at its next wake, which on the
default cadence can be up to an hour away. Kill it as well if you need it gone
now.
The opt-out is real and undocumented
The user-level fix is one line in ~/.codex/config.toml, under [features]:
daemon_auto_start = false. The config schema in the repository accepts it,
and a commenter on the issue confirms it works on Windows. But the official
configuration reference, fetched today, contains no entry for
daemon_auto_start at all, while it does document
check_for_update_on_startup, a setting the daemon crate's code never reads.
A reader looking for how to stop Codex from updating itself finds the wrong
switch.
The same reference does document the control that matters for a fleet. A
[features] table in requirements.toml pins runtime feature flags by the
same keys config.toml uses, and the code at 0.162.1 writes each pinned value
over whatever the user configured. On Unix the system file is
/etc/codex/requirements.toml.
One more default rode along. Pull request 49426, shipped in 0.161.0, makes
daemon-launched app servers start with analytics enabled by default, honouring
analytics.enabled = false in config.toml as the opt-out.
The verdict
Our view, which a vendor changelog will not print: for any team that approved Codex through npm, Homebrew, or an internal mirror, 0.157.0 moved the binary that services agent turns outside the approval path. The package you vetted starts a copy of itself, and a background process checks hourly for a release to replace it with. That is the integration gap our piece on why enterprise AI does not ship names first: the model is fine, the audit trail is what breaks. Whether a self-updating server is acceptable is a policy call; making it by default, without a documented switch, removes the call from the people who own that policy.
Adopt 0.162.1 if you need it, but pin the feature first. This advice is wrong
if a release flips default_enabled to false, or if OpenAI documents the key
and stops copying the package when a package manager owns the install, which
is what the open issue asks for.
Checklist for this week
-
On a developer machine that has run Codex 0.157.0 or later, list leftover processes with
pgrep -fl app-server. A match after every Codex window is closed is the daemon or its updater. -
For managed machines, add this to
/etc/codex/requirements.toml:[features] daemon_auto_start = false -
For individual users, put the same two lines in
~/.codex/config.toml. -
On machines where a daemon already runs: set
updater.autoUpdateEnabledto false in~/.codex/app-server-daemon/settings.json, runcodex app-server daemon stop, then end any remaining updater process rather than waiting for its next wake. -
If your proxy or credentials vary per invocation, assume any session started after the first one inherited the first one's environment until the daemon is gone.
-
Add
analytics.enabled = falseto the sameconfig.tomlif your policy requires it for daemon-launched servers.
Sources
- CLI: make daemon_auto_start opt-in - openai/codex issue 48195
- Feature registry at rust-v0.162.1 - openai/codex features/src/lib.rs
- codex-app-server-daemon README at rust-v0.162.1 - openai/codex
- Daemon updater loop at rust-v0.162.1 - openai/codex update_loop.rs
- Daemon lifecycle commands at rust-v0.162.1 - openai/codex app-server-daemon/src/lib.rs
- TUI startup orchestration at rust-v0.162.1 - openai/codex startup_orchestration.rs
- Managed feature pins at rust-v0.162.1 - openai/codex managed_features.rs
- Codex 0.157.0 release notes - openai/codex
- Codex 0.162.1 release notes - openai/codex
- Enable analytics by default for daemon-launched app servers - openai/codex pull request 49426
- Daemon server leaks environment variables across sessions - openai/codex issue 53547
- Configuration reference - Codex, OpenAI Developers
Related reading
- Dev Tools
CodeQL Swift Scanning Has No Supported Setup on Xcode 27. Some Runs Still Pass.
By Petru Popa · Read - Dev Tools
GitHub Secret Scanning Got a New AI Model. Its Documented Blind Spots Predate It.
By Petru Popa · Read - Dev Tools
GitHub Copilot With Ollama: Going Offline Switches Off Content Exclusion
By Petru Popa · Read
Turn this into a plan for your team.
One week, fixed fee: a working session with your team, a prioritized use-case backlog, and an ROI model for the opportunities worth chasing.