Codex Desktop (Windows): code-mode host spawns ~271 unreaped node/node_repl helpers per launch (~13 GB), and plugin `enabled = false` is ignored

Open 💬 4 comments Opened Aug 9, 2026 by EngSayh
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

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

OpenAI.Codex 26.803.5235.0 (MSIX, WindowsApps)

What subscription do you have?

PRO 20X

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64 (Windows 11 Pro, build 26200)

What issue are you seeing?

Severity: High — reproducible, unbounded resource consumption on every app launch.

1. Summary

On every launch of the Codex desktop app (bundled in ChatGPT.exe), the Codex app-server — started with the experimental flag features.code_mode_host=true — spawns ~271 Node.js helper processes within a single minute and never reaps them. On this machine that is a fixed ~10–13 GB memory cost per launch, sustained for the lifetime of the app session.

Two findings make this materially worse than the already-tracked leak issues:

  1. The documented mitigation does not work. Setting enabled = false on plugins in ~/.codex/config.toml has zero effect on the spawn count. The code-mode host enumerates the plugin marketplace cache on disk, not the enabled list. Verified by controlled A/B test (§5.2) — including a disabled plugin that continued to spawn its MCP server.
  2. The spawn is a startup burst, not gradual creep. 271 of 279 helpers appear inside one 60-second window at app start. Restarting the app does not reduce steady state; it re-pays the full cost.

Because every helper's parent process is alive, killing the helpers individually causes immediate respawn. The only recovery is terminating the app entirely.

2. Environment

| Item | Value |
| --- | --- |
| OS | Microsoft Windows 11 Pro, build 26200 (10.0.26200) |
| CPU | AMD Ryzen 9 9950X, 16 cores / 32 logical |
| RAM | 125.7 GB |
| Codex package | OpenAI.Codex 26.803.5235.0 (MSIX, WindowsApps) |
| Install path | C:\Program Files\WindowsApps\OpenAI.Codex_26.803.5235.0_x64__2p2nqsd0c76g0\ |
| Node on PATH | v24.18.1 at C:\nvm4w\nodejs\node.exe (nvm4w) |
| Plugins configured | 37, all enabled = true |
| Codex home | C:\Users\<user>\.codex |

Observed launch command line:

"C:\Program Files\WindowsApps\OpenAI.Codex_26.803.5235.0_x64__2p2nqsd0c76g0\app\resources\codex.exe" -c features.code_mode_host=true app-server --analytics-default-enabled

Process ancestry:

explorer.exe
  └─ ChatGPT.exe (supervisor, 11–12 processes)
       └─ codex.exe (app-server)   <-- spawns and owns all helpers
            ├─ node_repl.exe  × 127
            └─ node.exe       × ~114  (code-mode hosts)
                 └─ cmd.exe → node.exe  (npx-wrapped MCP servers)

3. Impact — measured

Memory delta attributable to the Codex app-server, measured minutes apart on an otherwise unchanged system:

| State | Free RAM | Helper processes |
| --- | --- | --- |
| Codex app closed | 99.1 GB | 0 |
| Codex app running (~2 min after launch) | 89.4 GB | 291 |

Cost: ~9.7 GB and 291 processes, paid on every launch. Peak observed in a single session: 291 processes / 13.16 GB.

On a 125.7 GB workstation this is tolerable. On a typical 16 GB developer laptop this profile is unusable — which matches the symptom described in #29079 ("until memory pressure makes PC unresponsive").

4. Evidence

4.1 Process inventory (steady state, ~2 minutes after launch)

| Command signature | Count | RAM |
| --- | --- | --- |
| ...\runtimes\cua_node\<hash>\bin\node_repl.exe (no args) | 127 | 1.19 GB |
| C:\nvm4w\nodejs\node.exe ./mcp/server.mjs | 29 | |
| C:\nvm4w\nodejs\node.exe ./mcp/server.mjs --stdio | 29 | |
| C:\nvm4w\nodejs\node.exe ./mcp/server.bundle.mjs | 28 | |
| C:\nvm4w\nodejs\node.exe ./mcp/server.cjs --stdio | 28 | |
| npx-cli.js -y xcodebuildmcp@latest mcp (wrapper) | 15 | |
| ...\_npx\<hash>\...\xcodebuildmcp\build\index.js (server) | 15 | |
| Total node.exe | 164 | 11.97 GB |
| Total node_repl.exe | 127 | 1.19 GB |
| Combined | 291 | 13.16 GB |

4.2 Spawn timing — single-minute burst

09:17 ->   6     (unrelated: another vendor's MCP servers)
09:18 ->   2     (unrelated)
09:38 -> 271     <-- Codex app-server launch

All 271 Codex helpers appear inside one 60-second window at app start.

4.3 Ownership — no orphans, so selective reaping is impossible

[241]  codex.exe(72356)          <- single live parent
[  1]  cmd.exe(...)  × 30        <- npx wrappers, themselves children of codex.exe

An orphan scan (helpers whose parent PID no longer exists) returned 0 of 271. Consequence: terminating individual helpers triggers immediate respawn by the live app-server. Observed during testing:

kill 146 helpers  ->  83 respawned within ~5 seconds
kill app-server   ->  all children died instantly (clean job-object teardown)

4.4 App-server PID churn

Across ~20 minutes of observation the app-server was seen under four different PIDs (52040, 19444, 64304, 72356), indicating it restarts during normal use. Each restart re-runs the full spawn burst, and the previous generation is not reaped by the supervisor.

4.5 Teardown is clean — the defect is in-session lifetime, not exit

Terminating ChatGPT.exe then codex.exe removed all 280 helpers with zero stragglers, twice, reproducibly. The child processes are correctly bound to a job object. The defect is therefore not a shutdown-cleanup failure — it is that the helpers are spawned in bulk and never reaped while the session is alive.

5. Key findings

5.1 The 4-variant probe never collapses to a winner

For each plugin, the code-mode host appears to launch four candidate entry points simultaneously rather than probing them in sequence and terminating the losers:

./mcp/server.mjs
./mcp/server.mjs --stdio
./mcp/server.cjs --stdio
./mcp/server.bundle.mjs

All four survive indefinitely at ~75–120 MB each. With ~29 plugins carrying an mcp/ directory this alone accounts for ~114 processes and ~9 GB.

Note also the relative path ./mcp/server.mjs, which makes the launch dependent on the working directory of the host.

5.2 enabled = false is ignored — this is the critical finding

The mitigation recommended in existing reports and community threads ("reduce the number of active MCP servers") has no effect on this build.

Controlled test:

| | Plugins enabled | Combined helpers | RAM |
| --- | --- | --- | --- |
| Before | 37 | 287 | 13.08 GB |
| After (full app restart) | 11 | 291 | 13.16 GB |

26 plugins were set to enabled = false in ~/.codex/config.toml, the app was fully terminated and relaunched, and the process count did not drop.

Direct proof: build-ios-apps@openai-curated was enabled = false at the time of measurement, yet xcodebuildmcp was still being launched 15 times. Post-restart the code-mode host was still probing ~29 plugins, not 11.

The code-mode host is evidently enumerating the marketplace cache (~/.cache/codex-runtimes/codex-primary-runtime/plugins/...) rather than honouring the [plugins."<name>"] enabled flags in config.toml.

This means users currently have no working mitigation.

5.3 node_repl.exe pool is oversized by two orders of magnitude

127 instances of node_repl.exe spawn simultaneously at startup, all direct children of the app-server, all from the bundled runtime:

C:\Users\<user>\AppData\Local\OpenAI\Codex\runtimes\cua_node\<hash>\bin\node_repl.exe

config.toml declares exactly one [mcp_servers.node_repl] entry. A single REPL server producing 127 processes suggests a pool-sizing or reconnect-retry defect. (Cross-reference: "Large number of node_repl.exe processes" on the OpenAI Developer Community forum.)

5.4 Platform-impossible plugin retries forever

build-ios-apps@openai-curated launches:

npx -y xcodebuildmcp@latest mcp

Xcode is macOS-only, so this can never succeed on Windows. It was observed retrying 13–18 times per session, each attempt costing two processes (npx wrapper + server) and a cmd.exe. There appears to be no platform gate and no retry ceiling.

The -y ... @latest form also forces an npm registry round-trip on every attempt, adding network latency and cache churn (31 cached _npx package folders accumulated).

5.5 Runtime inconsistency

node_repl.exe correctly uses the bundled cua_node runtime, but the code-mode hosts invoke node from the user's PATH (C:\nvm4w\nodejs\node.exe, an nvm4w symlink). This makes the feature's behaviour dependent on whatever Node version the user has active, and on nvm4w's symlink indirection.

What steps can reproduce the bug?

  1. Windows 11 with the Codex desktop app installed (ChatGPT.exe bundle), version 26.803.5235.0.
  2. Have a substantial plugin set installed (~30+ with mcp/ entry points).
  3. Fully exit ChatGPT/Codex. Confirm zero node.exe / node_repl.exe from Codex.
  4. Record free RAM.
  5. Launch the app. Wait 60–120 seconds.
  6. Run:
$a = Get-CimInstance Win32_Process -Filter "Name='node.exe'"
$b = Get-CimInstance Win32_Process -Filter "Name='node_repl.exe'"
"node.exe      : {0}  {1} GB" -f $a.Count, [math]::Round((($a|Measure-Object WorkingSetSize -Sum).Sum)/1GB,2)
"node_repl.exe : {0}  {1} GB" -f $b.Count, [math]::Round((($b|Measure-Object WorkingSetSize -Sum).Sum)/1GB,2)
  1. To confirm §5.2 (enabled = false is ignored), set every [plugins."..."] enabled to false except a handful, fully restart the app, and repeat step 6. The counts will not drop.

Grouping helper (shows what each process actually is):

Get-CimInstance Win32_Process |
  Where-Object { $_.Name -in @('node.exe','node_repl.exe') } |
  ForEach-Object { $c = $_.CommandLine; if ($c.Length -gt 105) { $c = $c.Substring(0,105) }; $c } |
  Group-Object | Sort-Object Count -Descending | Format-Table Count, Name -AutoSize

What is the expected behavior?

Launching the Codex desktop app should start only the MCP/code-mode helpers that are actually enabled and actually needed, and should reap helpers that never complete a handshake — not hold ~271 processes and ~13 GB for the lifetime of the session. In particular, enabled = false in ~/.codex/config.toml should prevent a plugin's servers from being launched at all.

Suggested fixes, in priority order:

  1. Honour enabled = false. The code-mode host must filter against the [plugins."<name>"] enabled flags in config.toml before enumerating. This alone restores a working user-side mitigation and would be a small, low-risk change.
  2. Probe sequentially, not in parallel. Try entry-point candidates in order and stop at the first success, or launch all four and terminate the losers once one handshakes. This is a ~4× reduction on its own.
  3. Bound the node_repl pool. 127 processes for one declared server is almost certainly unintended. Cap the pool and add backoff on reconnect.
  4. Platform-gate plugins. build-ios-apps / xcodebuildmcp should not be launched on Windows at all. Add an OS capability check in the plugin manifest, plus a global retry ceiling with exponential backoff for any MCP server that fails to start.
  5. Reap idle hosts. Add an idle timeout so code-mode hosts that never complete a handshake are terminated rather than held for the session lifetime.
  6. Use the bundled runtime. Invoke the bundled cua_node binary rather than PATH node, for consistent behaviour across user Node installations.

Additional information

Tested and ruled out

| Hypothesis | Result |
| --- | --- |
| Orphans from previous crashed generations | Ruled out — 0 of 271 helpers had a dead parent |
| Failure to clean up on app exit | Ruled out — teardown removed all 280 with zero stragglers, twice |
| Reducing enabled plugins (the documented mitigation) | Ruled out — 37 → 11 plugins produced no change |
| Restarting the app as a durable fix | Ruled out — reclaims memory, then re-pays the full cost within one minute |
| A local toggle for code_mode_host | None exists — the string is absent from config.toml, .codex-global-state.json, the [features] block, all four app-data roots, and the environment. It is injected by ChatGPT.exe at launch |
| A newer build with a fix | None available — 26.803.5235.0 is already newer than the most recent publicly noted desktop release |

Related issues

  • #29079 — Codex Desktop on Windows leaves Node/MCP helper processes alive until memory pressure makes PC unresponsive (open) — closest match; this report adds the enabled = false finding and the controlled A/B test
  • #33778 — Windows Codex desktop app spawns hundreds of taskkill.exe and conhost.exe during local tool execution
  • #13970 — Codex Windows app leaves at least 5 running processes after exit every time
  • #25935 — Codex appears to leave orphaned git.exe processes on Windows
  • #1570 — Codex spawning multiple node processes that block computer
  • #30527 — Windows 10: Codex app triggers Microsoft Defender Behavior Monitoring / high CPU after recent update
  • OpenAI Developer Community — "Large number of node_repl.exe processes"

Current workaround

None that preserves functionality. The only effective recovery is to fully exit ChatGPT/Codex, which cleanly reclaims all helpers and their memory. Relaunching immediately re-pays the full ~10–13 GB cost. Disabling plugins does not help.

# Full reclaim — stop the supervisor first so it cannot respawn the app-server
Get-Process ChatGPT -ErrorAction SilentlyContinue | Stop-Process -Force
Start-Sleep 3
Get-Process codex, codex-code-mode-host -ErrorAction SilentlyContinue | Stop-Process -Force

Measured result: 280 helpers removed, 12.26 GB reclaimed, zero stragglers.

View original on GitHub ↗

4 Comments

github-actions[bot] contributor · 19 days ago

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

  • #37453
  • #37426
  • #37402
  • #37401

Powered by Codex Action

WeipengMO · 18 days ago

Correction: this comment was posted to the wrong issue while reviewing duplicate suggestions for another report. Please disregard it. Sorry for the noise.

nos1609 · 13 days ago

Independent reproduction on Windows ARM64 / current Desktop build

This reproduces on a newer Windows ARM64 build and confirms two parts of the report: the missing platform gate for build-ios-apps and incremental helper retention under one unchanged app-server.

Environment:

  • Windows 11 Pro ARM64, build 28000
  • OpenAI Codex MSIX 26.810.4967.0, ARM64
  • system Node.js v24.14.1, arm64
  • build-ios-apps plugin 0.1.2
  • app-server command: codex.exe -c features.code_mode_host=true app-server --analytics-default-enabled

The plugin manifest has no platform declaration. Its MCP definition unconditionally launches:

npx -y xcodebuildmcp@latest mcp

The same app-server remained alive for the entire observation. Five complete XcodeBuildMCP process generations accumulated incrementally, rather than only during startup:

app-server start
+00:36  generation 1
+01:02  generation 2
+03:01  generation 3
+04:20  generation 4
+04:29  generation 5

Each generation retained this four-process chain:

cmd.exe /c npx -y xcodebuildmcp@latest mcp
  node.exe ... npx-cli.js -y xcodebuildmcp@latest mcp
    cmd.exe /c xcodebuildmcp mcp
      node.exe ... xcodebuildmcp/build/cli.js mcp

Measured snapshot:

| Scope | Processes | Working set | Private memory |
| --- | ---: | ---: | ---: |
| XcodeBuildMCP, 5 generations | 20 | 18.7 MiB | 1,121.5 MiB |
| Other repeated plugin MCP helpers | 20 | mostly paged out | 789.6 MiB |
| Complete Codex Desktop tree | 75 | 1,867.9 MiB | 6,401.1 MiB |
| Primary app-server alone | 1 | 141.0 MiB | 1,317.1 MiB |

The low XcodeBuildMCP working set is a consequence of memory pressure: most of its 1.1 GiB private allocation had already been paged out. It still consumes commit and contributes to system-wide paging.

This run did not repeat the original report's enabled = false A/B test. It independently confirms that:

  1. a macOS-only MCP is launched on Windows because the plugin has no platform gate;
  2. new full helper generations can accumulate over several hours under one app-server;
  3. the failed or idle platform-incompatible helpers are not reaped.

Expected behavior:

  • Reject or disable build-ios-apps / XcodeBuildMCP before process creation on non-macOS hosts.
  • Resolve plugin MCP compatibility for every restored or newly created context.
  • Reuse a compatible MCP instance or reap the entire failed/idle process group at a bounded lifecycle boundary.
  • Do not execute an unpinned @latest npm launcher repeatedly on a platform where the server cannot provide supported functionality.

This comment contains no task IDs, project names, usernames, local paths, prompts, or raw logs.

NovaSabre · 13 days ago

Independent reproduction: large MCP/helper accumulation on a 16 GB Windows machine

I found a closely related helper-process accumulation while investigating the Windows stutter/hash-loop regression in #38547.

Environment:

  • Codex Windows MSIX: affected 26.810 line
  • Previous version before the regression: 26.803.10989.0
  • Windows x64
  • 16 GB RAM

During an affected session, process inspection showed:

  • complete Codex process tree: ~205 descendants, ~9.65 GB combined working set
  • Chrome DevTools MCP-related Node processes: 57 processes, ~5.2 GB
  • Playwright MCP-related Node processes: 38 processes, ~3.0 GB
  • node_repl contexts: 20

At that point the machine was at ~92% memory use with only ~1.3 GB available. Fully terminating ChatGPT.exe removed the Codex-managed process tree and immediately stabilized the system.

The large repeated process groups were Chrome DevTools MCP and Playwright MCP. I did not find active Cloudflare/Wrangler, Mailjet, or Pencil worker processes accounting for this memory use.

This was observed simultaneously with the Electron main-process SHA-256 reconciliation loop documented in #38547, so the user-visible machine slowdown may be compounded by two separate defects: the main-process hashing loop and MCP/helper lifecycle/retention.

A fresh Windows reboot does not eliminate the problem: the system is responsive after boot, but launching Codex is enough for the slowdown to begin without starting any new work. This makes startup/background initialization worth investigating as part of the helper lifecycle as well.

Version clarification: a subsequent package check shows this machine is currently on OpenAI.Codex 26.810.6296.0. The earlier process measurements were collected during the affected investigation where 26.810.4967.0 had been recorded, but the later fresh-reboot/immediate-launch reproduction may have occurred after the automatic update to 26.810.6296.0 and should not be interpreted as specific to 26.810.4967.0.

I am waiting for 26.810.7004.0 to become available so I can retest. The Codex updater currently reports “Update is becoming available, try checking again later”, so the new build has not yet been offered to this machine. The currently installed package is OpenAI.Codex 26.810.6296.0.

I am not attaching raw traces/process dumps because they contain local paths and task metadata, but I can provide sanitized diagnostics if maintainers request a safe upload method.