Cold start scales badly with large ~/.codex state: 419 MB logs DB + 625 MB sessions cause 1–5 min startup on WSL2

Resolved 💬 3 comments Opened Jun 14, 2026 by 0proof1 Closed Jun 24, 2026
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

codex-cli 0.139.0

What subscription do you have?

ChatGPT Plus

Which model were you using?

gpt-5.5

What platform is your computer?

WSL2 Ubuntu on Windows Linux 6.6.114.1-microsoft-standard-WSL2 x86_64 x86_64

What terminal emulator and version are you using (if applicable)?

Windows Terminal with WSL2 Ubuntu, bash shell. No tmux/screen/zellij multiplexer.

Codex doctor report

Not available.

`codex doctor --json` is affected by the same cold-start issue. On this machine, `codex doctor` can take several minutes on a cold page cache, and in earlier attempts it appeared to hang or exceeded practical timeout limits. I included separate `codex doctor` timing measurements in the issue body instead.

What issue are you seeing?

On a cold page cache, full-init Codex commands such as codex exec, codex doctor, and the TUI can block for 1-5 minutes before doing useful work. This makes the CLI appear hung, especially to humans or wrappers using short timeouts.

Auth, network, websocket, and model access appear healthy. The delay appears to come from cold-cache startup I/O over accumulated local state in ~/.codex, especially logs_2.sqlite and sessions/.

Observed timings:

| Command | Warm cache | Cold cache |
|---|---:|---:|
| codex doctor | ~13 s | ~292 s |
| codex exec "say OK" | 4-5 s plus model time | ~57 s |

Accumulated ~/.codex state:

| Item | Size |
|---|---:|
| logs_2.sqlite | 419 MB |
| logs_2.sqlite-wal | 74 MB |
| sessions/ | 625 MB |
| .tmp/plugins/ | 79 MB, 175 plugin.json files |
| history.jsonl | 1.8 MB |
| other sqlite files | small |

What steps can reproduce the bug?

  1. Use Codex long enough for ~/.codex to accumulate large local state. In my case:
  • logs_2.sqlite: 419 MB
  • logs_2.sqlite-wal: 74 MB
  • sessions/: 625 MB
  • .tmp/plugins/: 79 MB / 175 manifests
  1. Drop the page cache:

sync
echo 3 | sudo tee /proc/sys/vm/drop_caches

  1. Run:

codex doctor

or:

codex exec --skip-git-repo-check "say OK"

  1. Observe a long silent startup delay before useful output.

I bisected the cold startup cost by moving one candidate aside, dropping the page cache, timing cold codex doctor, and then restoring the candidate.

| Removed before cold doctor | Cold doctor time | Delta |
|---|---:|---:|
| nothing, full ~/.codex | 291.9 s | -- |
| .tmp/plugins/ only, 79 MB / 175 manifests | 280.1 s | -12 s |
| logs_2.sqlite only, 419 MB | 140.2 s | -152 s |
| both .tmp/plugins/ and logs_2.sqlite | 115.6 s | -176 s |

This strongly suggests that the largest startup cost is associated with accumulated local state, especially the telemetry logs DB and the sessions directory. The plugin catalog contributes, but it is not the primary cause in this environment.

I also tested whether features.plugins=false explains the issue. It does not explain the main cold-start delay.

| Command | Plugins ON | Plugins OFF |
|---|---:|---:|
| warm doctor | 13.42 s | 13.32 s |
| cold doctor | 234.68 s | 240.53 s |
| warm exec | 29.40 s, model-time noisy | 4.44 s |
| cold exec | 56.54 / 59.47 s | 41.46 / 32.34 s |

Interpretation:

  • For doctor, plugins ON/OFF makes almost no difference.
  • The decisive difference is warm vs cold cache.
  • For exec, plugins add some secondary cost, but even with plugins disabled cold exec is still much slower than warm exec.

What is the expected behavior?

Codex should start in a few seconds even when local history, telemetry, sessions, or plugin catalogs have grown large.

Large append-only or historical state should not block CLI startup unless the user explicitly opens that state.

If startup must do expensive local-state work, the CLI should print early progress such as "loading local state", "loading sessions", or "loading plugin catalog", so a slow cold start is not mistaken for a hang.

Additional information

Ruled out:

  • Not the binary: codex --version returns immediately.
  • Not auth/network/websocket/model: codex doctor reports healthy connectivity.
  • Not a /mnt/c DrvFs/9p mount: ~/.codex is on native WSL2 ext4.
  • Not config size: copying the real config.toml into a clean CODEX_HOME remains fast.
  • Not primarily the plugin catalog: removing it only saves about 12 s on cold doctor; disabling plugins has almost no effect on doctor.

Secondary observations:

  1. codex doctor appears to ignore features.plugins=false.

With plugins disabled, doctor timing is effectively unchanged. Physically moving the plugin catalog directory does change timing, which suggests doctor may still scan plugin-related state even when the feature is disabled.

  1. Plugin and skill manifests appear to be parsed multiple times per process.

In one RUST_LOG=info codex exec run, the same manifest warning for one plugin was logged 6 times, and a set of skill icon warnings was logged 24 times.

Example repeated warnings:

codex_core_plugins::manifest: ignoring interface.defaultPrompt[0]: prompt must be at most 128 characters
path=.../.tmp/plugins/plugins/ngs-analysis/.codex-plugin/plugin.json

codex_core_skills::loader: ignoring interface.icon_small/icon_large: icon path with '..'

One internal startup phase also logged approximately:

duration_ms=14502

Suggested fixes:

  1. Avoid loading or scanning large accumulated state on the startup hot path.
  2. Open telemetry logs lazily or asynchronously.
  3. Load session history only when a specific session is opened.
  4. Add retention, rotation, or vacuuming for logs_2.sqlite, WAL files, and sessions/.
  5. Cache parsed plugin and skill manifests by mtime/hash.
  6. Ensure each manifest is parsed and validated at most once per process.
  7. Make codex doctor honor features.plugins=false.
  8. Print early startup progress so long cold starts are not mistaken for a hang.

Local mitigation:

Using a clean CODEX_HOME with only auth/config avoids the delay, which further supports that the problem is accumulated local state rather than auth, network, or the binary itself.

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #27741
  • #28109
  • #26775

Powered by Codex Action

0proof1 · 2 months ago

This may be related to the broader local-state / logs / sessions performance cluster, but I do not think it is an exact duplicate.

My understanding of the difference is:

  • #27741 is about a Codex Desktop app-server launch failure on /mnt/c, with a multi-GB logs_2.sqlite causing a SQLite pool timeout during startup.
  • #28109 is about Windows Desktop mouse/input freezes and Desktop session-history responsiveness.
  • #26775 is CLI-related, but it appears to reproduce even with a clean CODEX_HOME, whereas in this report a clean CODEX_HOME is fast.

This issue is narrower: direct Codex CLI cold-start latency on native WSL2 ext4. The affected commands are codex doctor, codex exec, and the TUI. The slowdown appears only with accumulated local state under ~/.codex, and I tried to separate the cost by moving individual state components aside.

The strongest distinction is that removing logs_2.sqlite reduced cold doctor time by about 152 s, while removing the plugin catalog only reduced it by about 12 s. That makes this look less like a general plugin/model latency issue and more like a local-state startup path issue.

If maintainers prefer to consolidate this into an existing tracking issue for local-state startup performance, I am happy to close it.
Thank you for consideration.

Necmttn · 2 months ago

Cold start needs a metadata-first path that does not open every large history payload.

Commands like doctor, exec, and TUI launch can read a compact session/log manifest first, then lazily hydrate only the active session. Diagnostics should report manifest rows, changed files scanned, bytes parsed, and time spent in logs DB versus session JSONL.

That makes WSL cold-cache cost measurable.

---

_Generated with ax._