Windows Codex App 26.409.7971.0 regression: project .codex/config.toml developer_instructions no longer override ~/.codex/config.toml
What version of the Codex App are you using (From “About Codex” dialog)?
Windows Store package on this machine:
OpenAI.Codex_26.409.7971.0_x64__2p2nqsd0c76g0- version:
26.409.7971.0
What subscription do you have?
Not material to the repro.
What platform is your computer?
Microsoft Windows 11 Pro 10.0.26100 x64.
What issue are you seeing?
This appears to be a regression introduced by the Windows desktop update that rolled out on April 16, 2026.
In Codex App on Windows, project-scoped developer_instructions from ./.codex/config.toml no longer override the user-level ~/.codex/config.toml developer_instructions.
This is severe because instruction layering is a core workflow and safety boundary. If repo-local developer_instructions lose precedence, the desktop app can silently apply the wrong developer policy for a repository.
The expected layered behavior is:
- user-global defaults come from
~/.codex/config.toml - project-local overrides come from
./.codex/config.toml - for the same key, the project-local value should win in that repository
In the current Windows Codex App build, the effective behavior appears to be the opposite for developer_instructions: the user-level value continues to dominate.
What steps can reproduce the bug?
- In
~/.codex/config.toml, set an unmistakable global instruction, for example:
developer_instructions = """
Reply with exactly: GLOBAL
"""
- In a trusted project, create
./.codex/config.tomlwith a conflicting project-local instruction, for example:
developer_instructions = """
Reply with exactly: PROJECT
"""
- Confirm the project is trusted.
- From that project root, compare behavior between Codex CLI and Codex App.
- Start a fresh thread in Codex App for that project.
- Ask a trivial prompt that makes the winning instruction obvious.
What is the expected behavior?
For a trusted project, the project-local ./.codex/config.toml developer_instructions should override the user-level ~/.codex/config.toml developer_instructions, matching layered config expectations.
In the example above, the effective instruction in that project should be PROJECT, not GLOBAL.
Actual behavior
On Windows Codex App 26.409.7971.0, the session behaves as if the user-level ~/.codex/config.toml developer_instructions still wins, even in a trusted project with its own ./.codex/config.toml override.
Additional information
This looks related to the broader history of Desktop/App config-layer drift, but it is not the same symptom as older reports.
Related issues:
- #11004 - Codex App:
developer_instructionsfrom config were not attached to app-created threads - #13025 - Desktop ignored project
.codex/config.tomland only loaded~/.codex/config.tomlfor MCP config - #17110 - Desktop did not honor project-scoped
.codex/config.tomlOTel config - #14689 - Codex App / CLI config drift around
config.toml
Why this one is especially severe:
- it affects
developer_instructions, not just MCP or telemetry config - it can invert repository-specific workflow/safety policy
- it is easy to miss because the app still starts and works, but with the wrong instruction layer winning
Current workarounds are not acceptable as a real fix:
- duplicating project rules into
~/.codex/config.toml - moving the most critical rules into
AGENTS.md - abandoning the desktop app for CLI in repos that depend on strict project-local instruction overrides
Please treat this as a regression in Desktop/App config precedence on Windows.
5 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
I'm not able to repro this. I also looked at the code paths that control this behavior, and I don't (or rather, Codex doesn't) see any recent behavioral changes. Can you double check the behavior you're seeing?
I can reproduce a closely related/current form of this on Windows App
26.519.5221.0. I also dug through the local packaged app and the Rust app-server sources, and the code path suggests this is not simply project config failing to load. It looks like the Desktop host is injecting a higher-precedence runtimedeveloper_instructionsoverride.Observed behavior:
./.codex/config.tomlcontains top-leveldeveloper_instructions.codex debug prompt-input "noop"from the same project root does include the project-localdeveloper_instructions, so the config loader/project config path itself appears to work for CLI.Source-level chain I found:
codex-rs/app-server-protocol/src/protocol/v2/thread.rsThreadStartParams { base_instructions: Option<String>, developer_instructions: Option<String>, ... }ConfigOverrides:codex-rs/app-server/src/request_processors/thread_processor.rsbuild_thread_config_overrides(..., developer_instructions, ...) -> ConfigOverrides { developer_instructions, ... }codex-rs/core/src/config/mod.rsdeveloper_instructions.or(cfg.developer_instructions)ConfigOverrides.developer_instructionsisSome(...),cfg.developer_instructionsfrom user/project config files is not used.ThreadStartParams.developer_instructionsdirectly. In the TUI/app-server path, fresh thread params are built from the mergedConfig, butdeveloper_instructionsis left as the defaultNoneforthread/start:codex-rs/tui/src/app_server_session.rsthread_start_params_from_config(...) -> ThreadStartParams { ..., config: config_request_overrides_from_config(config), ..., ..ThreadStartParams::default() }developer_instructionscan win according to the config-layer rules.thread/start:webview/assets/app-server-manager-signals-*.jsfetchFromHost("developer-instructions", { cwd, threadId, threadToolsEnabled, hostId, baseInstructions? })getProjectAwareDeveloperInstructions(...):.vite/build/main-*.jsbaseInstructions,cwd,hostId,threadToolsEnabled,threadId, Desktop settings-store Git prefs, conversation detail mode, and workspace-dependencies feature state../.codex/config.tomldeveloper_instructions..vite/build/workspace-root-drop-handler-*.jsThis explains the CLI/Desktop difference:
developer_instructionsoverride, so config-filedeveloper_instructionscan be used.developerInstructionsis sent, app-server treats it asConfigOverrides.developer_instructions, and the config-file value is short-circuited.Expected fix direction:
developerInstructionswhen it only wants to add app-context instructions, or it should merge the resolved config-layerdeveloper_instructionsinto the generated Desktop app-context before passing it tothread/start..codex/config.tomldeveloper_instructionsshould not be lost just because Desktop needs to add app-specific instructions.This may be why the issue is hard to repro by looking only at the Rust config loader: the loader appears to support project-local
developer_instructions; the loss happens earlier in the Desktop host/webview path that supplies a higher-precedence override.@etraut-openai I (or rather, Codex) performed a source-level analysis above, and it may explain why this is hard to reproduce when looking only at the Rust config-loader path.
The key distinction appears to be that Desktop fresh thread startup injects a host-generated
developerInstructionsvalue. Once it reaches app-server, it becomes a higher-precedenceConfigOverrides.developer_instructionsoverride; CLI/TUI fresh start does not set that top-level field.When you have time, could you please take another look from the Desktop host/webview startup path? I may still be missing context from the app side, but the evidence above seems to point there rather than to the core config loader.
Still reproducible on Windows with the current Codex Desktop build.
Environment:
I added this unmistakable test to the global config:
developer_instructions = """
If the complete user message is exactly:
dev instruction test
reply with exactly:
DEV_INSTRUCTIONS_LOADED
and no other text.
"""
I fully restarted the computer, opened Codex Desktop, created a new task, and sent:
dev instruction test
The main Desktop task ignored the instruction.
Evidence that the config itself is valid and loaded correctly by the underlying runtime:
codex debug prompt-input "dev instruction test"includes both the custom instruction marker andDEV_INSTRUCTIONS_LOADED.DEV_INSTRUCTIONS_LOADEDas the task title.This isolates the failure to the main Desktop task-creation path: the underlying Codex runtime reads
developer_instructions, but the App-created main thread omits or replaces them. The title-generation helper loading them while the main task does not is especially strong evidence of inconsistent instruction construction inside Desktop.Reproduction task/thread ID:
019f6c9a-b54f-7793-a21a-e1302b77d395