Windows Desktop WSL mode should split persistent CODEX_HOME from native WSL runtime cache

Open 💬 5 comments Opened Jun 8, 2026 by pussikill

What version of the Codex App are you using (From “About Codex” dialog)?

OpenAI.Codex 26.602.4764.0
Package: OpenAI.Codex_26.602.4764.0_x64__2p2nqsd0c76g0

What subscription do you have?

Pro

What platform is your computer?

Microsoft Windows NT 10.0.26100.0 x64
WSL2 Ubuntu, app-server launched from Codex Desktop WSL mode.

What issue are you seeing?

This is a focused proposal/bug report for the Windows Desktop + WSL runtime-cache behavior.

Several open issues describe overlapping symptoms around Windows Desktop WSL mode: config/home ambiguity, very slow plugin/skill discovery, stale arg0 temp paths, WSL UNC sandbox ACL failures, and heavy /mnt/c filesystem scans.

Related issues:
#22759, #13762, #18506, #24101, #24268, #25317, #25745, #25747, #26149, #26766, #25715, #16970, #26904.

The underlying problem appears to be that Desktop WSL mode currently overloads CODEX_HOME for both:

  1. persistent Desktop/user state: auth, config, sessions, sqlite/log state;
  2. runtime-heavy WSL data: plugin cache, marketplace temp dirs, bundled/system skills cache, arg0 temp helpers.

For Desktop users, moving the entire CODEX_HOME to native WSL would be risky because it can split auth/config/session state and may force re-authentication. But keeping all runtime-heavy data under /mnt/c/Users/.../.codex makes plugin/skill discovery very slow in WSL because the Linux app-server walks thousands of files through drvfs.

A more stable behavior would be:

  • keep persistent Desktop state under the Windows-backed CODEX_HOME;
  • move runtime-heavy WSL cache/temp data to native WSL storage, e.g. ~/.codex/runtime/wsl/<distro>;
  • expose/warn about the distinction so users understand whether auth/config is shared with Desktop or native to WSL;
  • provide an explicit opt-in for users who want fully native WSL CODEX_HOME.

I have a working branch implementing this approach for review/reference:

https://github.com/openai/codex/compare/main...pussikill:codex/wsl-desktop-runtime-cache

Note: I understand external PRs are by invitation only per docs/contributing.md. I am opening this issue to share analysis, reproduction data, and a concrete implementation direction for maintainers to evaluate.

What steps can reproduce the bug?

  1. Use Codex Desktop on Windows with WSL mode enabled.
  2. Ensure Desktop launches the Linux app-server through WSL while keeping:
  • CODEX_HOME=/mnt/c/Users/<user>/.codex
  • HOME=/home/<wsl-user>
  • CODEX_SQLITE_HOME=/home/<wsl-user>/.codex/sqlite
  1. Use plugins/skills so plugin and skill discovery touches the runtime plugin cache.
  2. Trigger app-server RPCs:
  • initialize
  • config/read
  • plugin/list
  • skills/list
  • skills/list with forceReload=true
  1. Compare the current store bundle behavior with a build that keeps Desktop persistent state on Windows but routes WSL runtime cache to native WSL storage.

For local validation, I used a benchmark harness that launches the app-server over stdio and measures these RPCs.

Clean isolated benchmark command:

python3 bench-wsl-desktop-app-server.py --isolated --clean --iterations 10

Hot isolated benchmark command:

python3 bench-wsl-desktop-app-server.py --isolated --iterations 8

Real non-isolated sanity check:

python3 -u bench-wsl-desktop-app-server.py --iterations 1 --verbose --request-timeout 120

What is the expected behavior?

Windows Desktop WSL mode should preserve Desktop auth/config/session state without forcing users to sign in again, but should not store or repeatedly scan heavy WSL runtime caches through /mnt/c.

Expected split:

  • persistent state/auth/config/sessions: Windows-backed Desktop CODEX_HOME;
  • WSL runtime plugin/skill/temp cache: native WSL filesystem;
  • clear warning or UI copy explaining the distinction;
  • explicit opt-in for users who want native WSL CODEX_HOME instead.

Additional information

Isolated multi-run benchmarks showed the improvement without touching the real user profile.

Cold median, 10 runs:

  • initialize: 414.3ms -> 286.3ms
  • skills/list: 690.8ms -> 99.0ms
  • skills/list:forceReload: 714.9ms -> 101.0ms

Warm median, 10 runs:

  • initialize: 427.3ms -> 233.4ms
  • skills/list: 711.7ms -> 94.9ms
  • skills/list:forceReload: 718.4ms -> 94.8ms

Hot-path isolated median, 8 runs:

  • initialize: 400.6ms -> 216.2ms
  • skills/list: 630.2ms -> 95.3ms
  • skills/list:forceReload: 669.0ms -> 95.0ms

I also ran a non-isolated sanity check on the real local environment. I checked the filesystem footprint carefully to avoid comparing unrelated state.

The whole Windows CODEX_HOME size is not the right primary metric because it also contains persistent auth/session/config/log state. The comparable footprint is the plugin temp runtime tree used by plugin/skill discovery.

Comparable plugin temp tree:

  • store path: /mnt/c/Users/xdev/.codex/.tmp/plugins
  • 4,909 files
  • 2,564 dirs
  • 59,447,140 bytes
  • patched path: /home/xdev/.codex/runtime/wsl/Ubuntu/.tmp/plugins
  • 4,908 files
  • 2,562 dirs
  • 58,713,015 bytes

The remaining differences are mostly git metadata/refs, so this is effectively the same runtime plugin tree served from different filesystems.

The RPC result size was also the same:

  • config/read: 3 layers
  • plugin/list: 2 marketplaces
  • skills/list: 1 skill

Non-isolated single-run timing on the real local environment:

  • initialize: store 547.8ms -> patched 219.9ms
  • plugin/list: store 1125.0ms -> patched 479.4ms
  • skills/list: store 28816.7ms -> patched 374.0ms
  • skills/list:forceReload: store 19196.9ms -> patched 602.2ms

This suggests the bottleneck is not different returned data or a smaller cache. The returned data is the same and the comparable runtime tree is nearly identical. The difference is that the current store bundle walks that tree through /mnt/c, while the patched build serves the heavy runtime plugin/skill cache from native WSL storage.

Implementation direction in the branch:

  • add a WSL-aware runtime cache home derived from CODEX_HOME;
  • keep persistent Desktop state/auth/config in Windows CODEX_HOME;
  • route plugin/marketplace/system-skill runtime cache/temp paths to native WSL runtime cache;
  • keep user skills persistent;
  • add WSL-aware arg0 temp namespacing and .pid guard;
  • skip unsupported Windows ACL refresh for WSL UNC paths;
  • add an explicit warning and opt-in env for native WSL CODEX_HOME.

Validation already run locally:

just fmt
TMPDIR=/home/xdev/tmp/codex-clean-test-tmp cargo test -p codex-utils-home-dir -p codex-core-plugins -p codex-core-skills -p codex-arg0 -p codex-windows-sandbox --lib
TMPDIR=/home/xdev/tmp/codex-clean-test-tmp cargo test -p codex-app-server desktop_wsl_windows_codex_home_warning --lib
TMPDIR=/home/xdev/tmp/codex-clean-test-tmp cargo test -p codex-app-server config_read_returns_effective_and_layers --test all
TMPDIR=/home/xdev/tmp/codex-clean-test-tmp cargo test -p codex-app-server skills_list_loads_remote_installed_plugin_skills_from_cache --test all
cargo +1.95.0-x86_64-unknown-linux-gnu test --target x86_64-pc-windows-gnu -p codex-utils-home-dir -p codex-arg0 -p codex-windows-sandbox --lib

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗