Prevent Configuration Pollution: Separate `projects.xxxx.trusted_level` from `config.toml`
What version of the Codex App are you using (From “About Codex” dialog)?
CLI
What subscription do you have?
Plus
What platform is your computer?
Darwin 25.1.0 arm64 arm
What issue are you seeing?
When opening a project for the first time, Codex prompts for user approval. Once granted, the application appends this project-specific metadata directly to ~/.codex/config.toml:
[projects.xxx]
trusted_level='trusted'
This behavior creates friction for users who manage their dotfiles via Git, as config.toml is typically synced across multiple machines. Injecting dynamic trust states and local project paths into the global configuration pollutes version control histories. Furthermore, absolute project paths are machine-specific and should not be tracked in a globally synced configuration file.
What steps can reproduce the bug?
When opening a project for the first time, Codex prompts for user approval. Once granted, the application appends this project-specific metadata directly to ~/.codex/config.toml:
[projects.xxx]
trusted_level='trusted'
What is the expected behavior?
Expected Behavior:
To prevent the pollution of global configuration options, project-related metadata should be decoupled from config.toml. Instead, Codex should store this state in a dedicated file within the ~/.codex directory—such as projects.toml or projects_state.toml—specifically designated for project information:
[projects.xxx]
trusted_level='trusted'
Additional information
_No response_
16 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
at least add glob support please
+1. trust state should be separate from config.toml. mixing repo-specific local state into synced dotfiles is pretty annoying.
I use Codex on multiple dev machines and manage my dotfiles using stow. Codex config makes it really difficult to manage the dotfiles. Every time I use codex in a new repo, changes show up in my config that's not compatible with the config in the other machine. Please separate user config and tooling config (like projects that are auto updated by codex) into separate files.
Here's an example of how I shared my opencode config with multiple machines because machine-specific state is not a part of the user config file.
<img width="896" height="1632" alt="Image" src="https://github.com/user-attachments/assets/1ce7fee5-eadd-494b-b1bc-68146e065ecd" />
Related issue with more engagement: https://github.com/openai/codex/issues/11061
sessions too
+1 — multi-machine dotfiles user (3 Macs, different usernames) hitting exactly this. Leaving concrete evidence in case it helps with prioritization.
Empirical test
codex-cli 0.123.0, macOS 25.4.0. Tried the obvious portable form by hand-editing the shared config:
Running
codexfrom$HOMEstill triggers the trust prompt. Approving it appends[projects."/Users/<username>"]back toconfig.toml— which then waits to be committed to the shared repo on that machine, collide on the next pull from another machine, repeat.Fix appears localized to a few call sites
The helper already exists and is used elsewhere:
AbsolutePathBuf::maybe_expand_home_directory()incodex-rs/utils/absolute-path/src/lib.rsexpands~/during deserialization for otherAbsolutePathBuf-typed fields.What's missing for trust specifically:
project_trust_key()incodex-rs/core/src/config_loader/mod.rsuses rawpath.to_string_lossy()— so[projects."~"]never matches$HOME.set_project_trust_level_inner()incodex-rs/config/src/lib.rswrites absolute paths verbatim when Codex auto-approves a trust prompt, so even with read-side expansion the auto-written entry re-introduces a machine-specific path.The separate-file proposal in this issue would also work. A cheaper alternative that doesn't introduce a new file: apply
maybe_expand_home_directory()to the trust-key read path, and have the auto-write path re-canonicalize$HOMEback to~/on serialization.Related: #11061 covers the broader "share user preferences across machines" scope, where the same asymmetry also affects marketplace
sourcepaths.I am hitting the same underlying problem on NixOS with Home Manager/dotfiles, and I think the scope is slightly broader than trusted project paths.
My desired setup is:
~/.codex/config.tomlas source-controlled user configuration from my dotfiles~/.codexwithout dirtying or fighting that fileIn practice,
config.tomlis currently serving as both declarative config and mutable app state. I tried working around this by regenerating~/.codex/config.tomlfrom a tracked base file plus a harvested local-state fragment, but that approach is brittle because Codex-owned state is not limited to[projects.*]/[tui.*]. On my current install (codex-cli 0.130.0) the mutable block also contains entries like:Those absolute paths clearly should not live in a shared dotfiles config, but if a dotfiles manager replaces
config.toml, Codex can lose state it expects to find there.A dedicated machine-local state file would make this much easier to manage. For example:
~/.codex/config.toml: user-authored/source-controlled config~/.codex/state.tomlor~/.codex/projects.toml: Codex-owned mutable local stateThat would also make it reasonable for users to symlink or Home-Manager-manage
config.tomldirectly, without needing fragile extraction/merge scripts around Codex writes.+1 on the projects trust boundary bleeding over into a configuration file
but this also applies to hooks and their approval state:
Hitting this on codex-cli 0.130.0. The underlying problem is broader than just
[projects.X]—~/.codex/config.tomlis the sink for several distinct kinds of machine-local mutable state today:[projects."<abs path>"]— per-project trust[hooks.state]— hook trust hashes (confirming @thesimonho's earlier comment that this has the same shape)[notice]flags likehide_<...>_migration_promptand[notice.model_migrations]— written when the user dismisses model-migration prompts[tui.model_availability_nux]— counters for new-model intro screensEach of these is keyed by absolute path or per-user UI state, mutates on a routine user action, and lives in the same file as configuration the user actually wants to share or VCS-manage. @colonelpanic8 framed this well above — the goal is to "let Codex keep machine-local mutable state" out of source-controlled config.
A targeted fix that only relocated
[projects.X]would leave the other three lurking. The cleaner principle:config.tomlis read-only-by-Codex aside from explicit user edits, and everything Codex writes back from a UI/CLI action lives in a separate machine-local file (e.g.~/.codex/state.toml). That makes the file VCS-manageable and shareable without per-table workarounds.The split proposed in #15433 (project trust →
~/.codex/trust_level.toml) generalizes naturally if every machine-local concern gets its own file, or all of them land under one~/.codex/state.toml. Happy to test whatever direction this goes.My config.toml being filled with garbage everytime it is opened:
It's like you guys are using config.toml as a dump for everything that requires saving to disk....
Please consider supporting the XDG Base Directory Specification. This makes it so much easier to reason about configuration, state, user data, etc, from a dotfiles and backup perspective.
Just wanted to share my own experience/reasons for wanting this: I'm using Nix on macOS to manage my dotfiles and unfortunately I get an error every time I start Codex due to it trying to write back to the
config.tomlwhich is not writable by design.If you're in Nix then you can patch the codex package while this is being resolved.
I want to restate the use case here because I think the current design misses a very common dotfiles workflow.
Users need a global configuration file for portable preferences. For example: model defaults, reasoning effort, approval policy, sandbox defaults, UI preferences, notification behavior,
feature flags, MCP preferences, etc. These are not project-specific settings. They are user preferences, and users reasonably want to bring them along when moving to a different
machine.
What many people do today is standard dotfiles practice:
config.tomlin a git-tracked dotfiles repo.~/.codex/config.toml.The problem is that Codex also stores non-portable, machine-local mutable state in that same file. Examples include:
Some of this state may not cause a functional problem when copied to another machine, but it still creates a bad user experience. For a git-tracked
config.toml, these changes are meaningless churn. They dirty the dotfiles repo, create diffs that do not represent intentional configuration changes, and add friction every time Codex records local state.The response that
~/.codex/config.tomlis “not designed to be used across machines” does not really answer the issue. If that file is not meant to be portable, then what file is supposed to hold global portable user preferences?Right now the choices seem to be:
.codex/config.toml, which is portable but repetitive and inappropriate for personal preferences.~/.codex/config.toml, which is global but apparently “not designed” to be portable and is constantly rewritten by Codex with machine-local state.That leaves a clear product gap: Codex has project-local config and machine-local config/state, but no clean place for portable global user preferences.
Judging from the number of related issues and comments, this is not an edge case. It is a common frustration among users who manage their development environment with dotfiles, Nix/Home Manager, stow, or any similar setup.
Proposed fix:
Option 1, preferred: keep
~/.codex/config.tomlas the user-authored portable global config, and move Codex-owned mutable local state into a separate file, for example:``
text
``~/.codex/config.toml # user-authored portable preferences
~/.codex/state.toml # Codex-owned machine-local mutable state
Trust state, hook approval state, local runtime paths, marketplace cache paths, notice dismissal state, and similar generated values should live in the state file, not in the portable
config.
Option 2: if OpenAI strongly wants to keep ~/.codex/config.toml as machine-local, then please introduce a new portable global settings file, for example:
But then Codex has to define precedence between settings.toml, config.toml, project config, and CLI overrides. That seems more complicated and more disruptive than Option 1.
I would genuinely like to understand the reasoning behind the current design. Right now it looks like config.toml is being used as both declarative user configuration and an application state dump. Those are different concerns, and combining them makes Codex unnecessarily painful to use with standard dotfiles workflows.
I would also personally be ok with something like
~/.codex/config-shared.tomlbeing introduced with lower precedence to the existing~/.codex/config.toml(so local overrides inconfig.tomlwin). Then I would just update my dotfiles to manageconfig-shared.tomlinstead ofconfig.toml. Might be an easier migration now thatconfig.tomlis so polluted it may as well bestate.toml.