Codex Desktop 26.506.31421 main Electron process pegs ~280% CPU on macOS while app-server is idle
Codex Desktop 26.506.31421 main Electron process pegs ~280% CPU on macOS while app-server is idle
Summary
On macOS, Codex Desktop 26.506.31421 (Electron 41.2.0) can drive the main Electron process to sustained ~264–285% CPU for many hours while the underlying codex app-server process stays effectively idle (~0–1% CPU). The hot path captured via sample(1) is in libuv stream reads / Node StreamBase JS callbacks with heavy Buffer/ArrayBuffer allocation, which strongly suggests the cost is in the desktop client's IPC/log/history processing rather than in model or backend compute. Restarting the app temporarily clears the main-process pegging but renderers remain unusually busy (~11% / 4.8% / 4.6%).
This appears related to (but distinct from) several existing reports; filing with concrete sample/profile evidence in case it helps narrow the root cause.
Environment
- Codex Desktop: 26.506.31421 (CFBundleVersion 2620)
- Electron: 41.2.0 (from crashpad annotation)
- OS: macOS 26.4.1 (25E253), Darwin 25.4.0
- Hardware: Mac mini, Apple M4, 10 cores, 16 GB RAM
~/.codex/sessions: 596 MB, with individual rollout JSONL files of 178M, 65M, 64M, 62M, 46M, 23M
Observed behavior
Live process snapshot before restart (uptime of main process ~23h38m):
| Process | CPU | RSS |
|---|---|---|
| Codex.app/Contents/MacOS/Codex (main, PID 665) | 264–285% | 1.35–1.52 GB |
| Codex Helper (GPU) | 16–24% | — |
| Codex Helper (Renderer, one of several) | 13–21% | ~1.9 GB footprint |
| codex app-server | 0.1–1.3% | — |
After a full app restart:
- Main process drops near idle.
- Renderers still show abnormal steady-state activity (~11%, 4.8%, 4.6%) without user interaction.
High-signal evidence
sample(1) of the main process shows the hot path concentrated in Electron/Node's local stream pipeline:
uv__io_poll
-> node::LibuvStreamWrap::OnUvRead
-> node::StreamBase::CallJSOnreadMethod
-> V8 / JS frames
-> heavy Buffer / ArrayBuffer allocation
-> _platform_memmove, __bzero
Concurrent log patterns (repeating at high frequency):
AppServerConnectionresponse routing forthread/list,skills/list,mcpServerStatus/list.browser-session-registryIAB_LIFECYCLEduplicate route captures.Received turn/started for unknown conversation.- Repeated
git status/git rev-parseprobes against saved workspace roots; several roots are Git repos with "No commits yet on main" / no HEAD, causinggit rev-parseto return exit code 128 in a tight loop.
Local samples available (no secrets):
/tmp/codex-main-665.sample.txt/tmp/codex-renderer-1485.sample.txt/tmp/codex-gpu-975.sample.txt
Why this looks client-side, not model/backend compute
codexapp-server CPU is ~0–1% throughout, while the Electron main process is at ~280%. If the cost were model/tool execution, the app-server (or a tool subprocess) would show it.- The sampled hot stack is purely libuv stream read → Node
StreamBaseJS callbacks → Buffer allocations andmemmove/bzero, i.e. IPC/stream-decode work in the desktop client. - Memory footprint and uptime correlate: the longer the app runs and the larger
~/.codex/sessionsgrows, the worse it gets; restart resets main-process CPU. - Log volume is dominated by client-side housekeeping (sidebar lists, lifecycle dedupe, git polling) rather than turn execution.
Possible contributing factors / related issues
These look plausibly connected; not claiming any are the root cause:
- Large local rollout history.
~/.codex/sessionsat 596 MB with multiple 50–180 MB JSONL files seems likely to amplify any per-startup or per-list scan. See #18693 (open: large local histories causing desktop performance collapse). - Sidebar / workspace git polling against repos without a HEAD. Saved roots with "No commits yet on main" produce repeated
git rev-parseexit-128s. See #19115 (closed as duplicate: non-git saved workspace roots / git warning loops). - Prior high-CPU reports on macOS with similar magnitudes:
- #18467 ("~276% CPU" on macOS; closed, but later commenters reproduced).
- #18481 (duplicate high CPU / overheating).
- Possibly related but unconfirmed: #21911 mentions a feature-negotiation mismatch in 26.506.31421 (unsupported feature requests). The
Received turn/started for unknown conversationand duplicateIAB_LIFECYCLEroute captures here may or may not be the same surface — flagging without overclaiming.
Expected behavior
- Idle/steady-state main-process CPU should be low (single digits) when no turn is active, regardless of session-history size or how long the app has been running.
- Workspace roots without a Git HEAD should not trigger a tight loop of
git rev-parsefailures; failed probes should back off or be cached. - Sidebar list endpoints (
thread/list,skills/list,mcpServerStatus/list) should not generate sustained stream traffic sufficient to peg the Node event loop. - Duplicate
IAB_LIFECYCLEroute captures andturn/started for unknown conversationwarnings should not occur in steady state.
Attachments available
Happy to share on request:
sample(1)output for main, renderer, and GPU helper processes (paths above).- Redacted excerpts of the AppServerConnection / browser-session-registry / git-probe log loops.
ls -lhS ~/.codex/sessionssummary (sizes only, no content).
Let me know what additional captures (e.g. --cpuprof of the main process, heap snapshot of a renderer) would be most useful and I can attach them.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗