## Why Resume and fork selection can change the working directory. Folder consent needs to cover the selected destination, and existing tasks in untrusted folders may retain settings and history loaded while trusted. ## What changed - Move startup consent after destination selection and reload local configuration when trust is saved. - Check both selected and saved folders for local daemon resumes, and reread the task after consent to catch working directory changes. - Resolve local trust using project markers, Git roots, and normalized paths, honoring explicit working directory decisions and canonical path precedence. - Offer restricted-folder consent without changing saved trust, with distinct wording for existing tasks that may retain configuration or hooks. Preserve remote checks scoped to explicit `--cd`. ## Testing Extend trust lookup coverage for parent/child decisions, repositories without project configuration, path aliases, and custom project markers. Update restricted-folder snapshots and add an existing-task snapshot. GitOrigin-RevId: caf8c70f1e953c4f7b4ddc89dd29bb1fd8ed62f1
codex-config loader
This module is the canonical place to load and describe Codex configuration layers (user config, CLI/session overrides, cloud-managed config, managed config, and MDM-managed preferences) and to produce:
- An effective merged TOML config.
- Per-key origins metadata (which layer “wins” for a given key).
- Per-layer versions (stable fingerprints) used for optimistic concurrency / conflict detection.
Public surface
Exported from codex_config::loader:
load_config_layers_state(fs, codex_home, cwd_opt, cli_overrides, options, thread_config_loader) -> ConfigLayerStackConfigLayerStackeffective_config() -> toml::Valueorigins() -> HashMap<String, ConfigLayerMetadata>layers_high_to_low() -> impl Iterator<Item = &ConfigLayerEntry>with_user_config(user_config) -> ConfigLayerStack
ConfigLayerEntry(one layer’s{name, config, version, disabled_reason};namecarries source metadata)ConfigLoadOptions(user-facing load behavior such as strict config validation)LoaderOverrides(test/override hooks for managed config sources)merge_toml_values(base, overlay)(public helper used elsewhere)
Layering model
Precedence is top overrides bottom:
LegacyManagedConfigTomlFromMdm(MDM-deliveredmanaged_config.toml, while it is being phased out)LegacyManagedConfigTomlFromFile(managed_config.toml, while it is being phased out)SessionFlags(CLI overrides, applied as dotted-path TOML writes)Projectconfig (.codex/config.toml)Userprofile config, when presentUserconfig (config.toml)EnterpriseManagedcloud-managed config bundle layersSystemconfig (/etc/codex/config.tomlor the Windows system config path)
ConfigLayerStack stores layers in the opposite order internally: lowest
precedence first, highest precedence last, so later layers override earlier
layers when folded. Thread config entries supplied by thread_config_loader are
inserted according to their translated ConfigLayerSource precedence.
Project-root discovery and project trust use the applicable non-project layers, including legacy managed-file and MDM config at their normal precedence. The managed layers remain above project and session layers in the final stack. Executor-local reads use their own system, base-user, and legacy managed sources; they do not include cloud config, selected profiles, or session flags.
Layers with a disabled_reason are still surfaced for UI, but are ignored when
computing the effective config and origins metadata. This is what
ConfigLayerStack::effective_config() implements.
Typical usage
Most callers want the effective config plus metadata:
use codex_config::LoaderOverrides;
use codex_config::NoopThreadConfigLoader;
use codex_config::loader::load_config_layers_state;
use codex_exec_server::LOCAL_FS;
use codex_utils_absolute_path::AbsolutePathBuf;
use toml::Value as TomlValue;
let cli_overrides: Vec<(String, TomlValue)> = Vec::new();
let cwd = AbsolutePathBuf::current_dir()?;
let layers = load_config_layers_state(
LOCAL_FS.as_ref(),
&codex_home,
Some(cwd),
&cli_overrides,
LoaderOverrides::default(),
&NoopThreadConfigLoader,
).await?;
let effective = layers.effective_config();
let origins = layers.origins();
let layers_for_ui = layers.layers_high_to_low().collect::<Vec<_>>();
Internal layout
Implementation is split by concern:
state.rs: public types (ConfigLayerEntry,ConfigLayerStack) + merge/origins convenience methods.layer_io.rs: readingconfig.toml, managed config, and managed preferences inputs.project_discovery.rs: shared managed-config composition for project-root and trust discovery.overrides.rs: CLI dotted-path overrides → TOML “session flags” layer.merge.rs: recursive TOML merge.fingerprint.rs: stable per-layer hashing and per-key origins traversal.macos.rs: managed preferences integration (macOS only).