openai / openai/codex

Config architecture: separate user-owned settings from generated runtime/plugin/project state

Open
#45,627 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

app config enhancement windows-os
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

~/.codex/config.toml is currently acting as both a user-authored configuration file and a mutable state store for Desktop/CLI/runtime/plugin/project metadata.

For long-term Codex users, this makes the file grow very large and difficult to reason about. In my Windows setup, config.toml has grown to more than 600 lines and contains a mixture of:

  • stable user choices such as model/provider, reasoning settings, feature flags, sandbox policy, and user-defined MCP servers;
  • per-project trust metadata ([projects.*]);
  • plugin enable/disable state;
  • marketplace registrations and revisions;
  • Desktop UI preferences;
  • hook trusted hashes;
  • Desktop-generated node_repl configuration;
  • absolute paths into version/hash-specific Codex runtime directories;
  • browser/computer-use runtime metadata;
  • native-pipe identifiers;
  • generated notify executable paths;
  • runtime-specific hashes and plugin cache paths.

These categories have very different ownership and lifecycles, but they are persisted into the same file.

Why this is a problem

A user generally expects config.toml to be a stable, declarative, user-owned configuration file that can be understood, backed up, diffed, and optionally synced between machines.

Instead, Codex Desktop and related subsystems also write machine-specific and runtime-generated values into the same file. This creates several practical problems:

  1. Configuration pollution

    The file grows continuously as projects, plugin state, hooks, and runtime metadata are added.

  2. Poor debuggability

    A syntax/type/path problem anywhere in the file can prevent Codex from starting, even when the user's actual model/provider configuration is valid.

  3. Runtime state becomes stale

    Version/hash-specific paths, plugin cache paths, native pipe IDs, or Desktop-generated runtime settings can become invalid after updates or restarts.

  4. Ownership is unclear

    It is difficult to tell which sections are safe for the user to edit and which are owned/generated by Codex Desktop.

  5. CLI/Desktop interference becomes possible

    Multiple Codex surfaces can read/write the same file even though they may have different runtime/plugin versions.

  6. Dotfile management is difficult

    Machine-specific project paths, runtime hashes, trusted hook state, and Desktop-generated values do not belong in a portable user config.

Concrete troubleshooting experience

Environment:

  • Windows 11 x64
  • Codex CLI 0.154.0
  • Codex Desktop runtime/browser configuration from the 26.908 build family
  • custom Responses API provider

My full config.toml had grown to hundreds of lines and contained both user configuration and Desktop-generated runtime/plugin state.

codex exec failed very early with:

Error: The system cannot find the path specified. (os error 3)

A minimal isolated CODEX_HOME containing only the model/provider/features configuration worked immediately:

OpenAI Codex v0.154.0
model: gpt-6-astra
provider: <custom provider>
...
API_OK

After cleaning incompatible/problematic entries in the large config, the normal configuration worked again.

The important point is not one specific failing field: the larger design makes this class of failure unnecessarily difficult to diagnose because durable user preferences, generated runtime state, project metadata, and plugin state are all co-located.

Related issues

There are already narrower reports that appear to be symptoms of the same architectural problem:

  • #14601 — separate projects.*.trusted_level from config.toml
  • #26011 — stale MCP/runtime paths after Desktop auto-update
  • #26366 — global CLI and Desktop bundled-plugin reconciliation can fight over the shared config.toml

This issue is intended as a broader configuration/state ownership request rather than a duplicate of any one of those reports.

Suggested design

Please consider separating declarative user configuration from mutable/generated state.

For example:

~/.codex/
├── config.toml                 # user-owned, stable declarative config
├── projects.toml               # project trust / project-local metadata
├── plugins.toml                # plugin + marketplace user selections
├── desktop.toml                # Desktop UI preferences
├── state/                      # Codex-managed mutable state
│   ├── runtime.json            # runtime paths/build/hash/generated data
│   ├── plugin-state.json       # resolved marketplace/plugin runtime state
│   ├── hook-trust.json         # trusted hook hashes
│   └── browser-runtime.json    # ephemeral browser/CUA runtime metadata
└── ...existing SQLite/session state...

The exact file names are not important. The important boundary would be:

User-owned declarative config

Good candidates to keep in config.toml:

model
model_provider
model_reasoning_effort
features
sandbox/approval policy
user-defined MCP servers
custom model providers
explicit user preferences
Codex-managed mutable state

Good candidates to move elsewhere:

project trust history
hook trusted hashes
runtime build/hash paths
node_repl generated environment
native pipe IDs
browser/computer-use runtime paths
Desktop-generated notify paths
marketplace refresh revisions/timestamps
resolved plugin/cache paths
other version-specific generated values

Additional improvements that would help

  1. Add a clear ownership marker/documentation for each config key: user-owned, desktop-managed, or runtime-generated.

  2. Avoid persisting ephemeral values such as native pipe identifiers in the long-lived user config.

  3. Add a supported command such as:

    codex config doctor
    codex config explain
    codex config regenerate-runtime-state
    

    so users can see where effective values come from and safely repair generated state.

  4. Consider a config.d/ or include mechanism for advanced users who want to split model, MCP, plugin, and machine-specific configuration.

  5. Make Desktop-generated state atomic and independently recoverable so a bad runtime entry cannot prevent the entire user configuration from loading.

  6. Keep backward compatibility by continuing to read legacy sections from config.toml, but migrate generated state out over time.

Expected outcome

Ideally, ~/.codex/config.toml should remain small, understandable, and mostly stable over time.

A user should be able to open it and clearly answer:

"What did I configure?"

without having to distinguish their own settings from hundreds of lines of runtime-generated state.

Separating these concerns would improve reliability, upgrade safety, diagnostics, portability, and the overall maintainability of Codex configuration.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the CLI, Desktop, runtime, and plugin reads and writes to ~/.codex/config.toml and the CODEX_HOME layout. Define the ownership boundary, migration and backward-compatibility behavior, then verify that user configuration remains stable while generated state is independently recoverable and diagnosable.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.