[Desktop Linux] Codex Desktop leaves orphaned `zcode-cli` processes after app quit (no SIGHUP/SIGTERM reaping)
Summary
Codex Desktop on Linux leaves orphaned zcode-cli processes running after the desktop application is closed/quit. The processes are reparented to systemd --user (PID 1 of the user session) and continue running indefinitely, accumulating CPU time, until manually killed.
This is the Linux equivalent of the well-documented macOS process-lifecycle defect class (see Related issues), but no existing issue covers the Linux Desktop + zcode-cli combination. zcode-cli is the bundled CLI binary that ships with Codex Desktop on Linux (located under /opt/codex-desktop/).
Environment
- Product: Codex Desktop (Electron)
- Desktop version:
26.611.62324(from Crashpad handler annotations:_productName=Codex,_version=26.611.62324) - Electron:
42.1.0(from Crashpad annotationprod=Electron,ver=42.1.0) - OS: Debian GNU/Linux 13 (trixie) — from Crashpad annotation
lsb-release - Architecture: x86_64
- Desktop install path:
/opt/codex-desktop/ - User session manager:
systemd --user(PID 1247)
Observed behavior
After closing Codex Desktop normally, two zcode-cli processes survived as orphans:
PID PPID PGID SID STAT STARTED ELAPSED TIME CMD
2115562 1247 2115562 2115562 Ssl Tue Jul 7 01:03:03 2026 11:02:13 360 zcode-cli
2135400 1247 2135400 2135400 Ssl Tue Jul 7 01:05:25 2026 10:59:51 308 zcode-cli
Key observations:
- PPID = 1247 (
systemd --user), confirming the processes were reparented when Codex Desktop exited. PPID 1247 is/usr/lib/systemd/systemd --user, startedSun Jul 5 21:23:01 2026. - PGID = SID = PID for each orphan, meaning each
zcode-clibecame its own process-group and session leader after being detached by the desktop. They were not killed when the desktop's process group was torn down. - STAT =
Ssl— sleeping, session leader, multi-threaded. Not spinning at 100% CPU (unlike #13928 / #19958), but still consuming memory and accumulating CPU time indefinitely. - ~11 hours elapsed, ~6 min CPU each — the processes ran for 11+ hours after the desktop was closed, accumulating 360s and 308s of CPU time respectively, until manually killed.
For contrast, the same system had 7 active CLI codex sessions on pts/0,1,4,6,7,10,12 — those are intentional interactive terminal sessions and are not orphans. The orphans are specifically the zcode-cli processes spawned by the Desktop app, not the CLI.
Steps to reproduce
- Launch Codex Desktop on Linux.
- Use it normally (open a conversation, run a task).
- Quit/close Codex Desktop (window close or app quit).
- Check for orphaned processes:
ps -ef | grep zcode-cli | grep -v grep
- Observe:
zcode-cliprocesses survive with PPID =systemd --user(or another init-equivalent), continuing to run indefinitely.
Expected behavior
When Codex Desktop quits, it should send SIGTERM (then SIGKILL after a grace period) to all zcode-cli child processes it spawned, ensuring no orphans survive. This is the same fix pattern applied in the OpenCode desktop equivalent (anomalyco/opencode#11959 — "ensure child processes are killed on Linux when app exits").
Actual behavior
zcode-cli processes are not reaped on app quit. They are reparented to systemd --user and continue running indefinitely, accumulating CPU time and holding memory.
Impact
- Memory leak: Each orphaned
zcode-cliholds RSS indefinitely. - CPU waste: Orphans accumulate CPU time over hours/days. In a multi-day, multi-session workflow this compounds.
- Accumulation: Each desktop quit can leave new orphans; they stack across sessions.
- Silent failure: No crash or error is surfaced to the user — the processes are invisible until someone inspects the process table.
Suggested fix
Codex Desktop's Linux exit path should:
- Track all
zcode-clichild PIDs it spawns. - On app quit, send
SIGTERMto each child's process group (kill(-pgid, SIGTERM)), not just the direct child. - After a bounded grace (e.g. 3–5s), send
SIGKILLto any surviving process group. - Ensure the desktop's own process-group teardown cascades to children, or explicitly
setsid()+ reap them on exit.
The root cause appears to be the same defect class as #14962 (SIGHUP not handled in the Node wrapper) and #12491 (MCP child processes not reaped after task completion), but surfaced on Linux Desktop through zcode-cli rather than the CLI or macOS GUI.
Related issues
This is the same defect class as the following, but none cover Linux Desktop + zcode-cli:
- #25388 — Codex Desktop leaves orphaned zsh shell-snapshot processes (macOS, zsh snapshots)
- #14962 — Orphaned process pairs burn CPU when terminal is closed (CLI, SIGHUP not handled)
- #13928 — Codex native binary persists after session exit, ~100% CPU (macOS, Rosetta)
- #24347 —
codex app-server(Linux) leaks chrome-devtools-mcp child trees (Linux, but app-server/MCP lifecycle, not desktop quit) - #12491 — Codex.app GUI MCP child processes not reaped — 1300+ zombies, 37GB leak (macOS GUI)
- #25744 — Codex macOS accumulates Computer Use / MCP helper processes + zombies (macOS)
- #19958 — CLI
/statusorphan spins at 100% CPU with revoked stdio (macOS CLI)
External:
- anomalyco/opencode#11959 — "ensure child processes are killed on Linux when app exits" (OpenCode fixed the same defect class with
SIGTERMto child + process group on app exit)
Workaround
Manual cleanup:
pkill -f zcode-cli
Or per-PID:
kill <pid1> <pid2>
Reaper cron for long-running machines (not a fix — containment only):
# Add to user crontab — kill zcode-cli orphans older than 1 hour
pgrep -f zcode-cli | while read pid; do
elapsed=$(ps -o etimes= -p "$pid" | tr -d ' ')
if [ "$elapsed" -gt 3600 ]; then
# Verify no active Codex Desktop instance owns it
if ! pgrep -f '/opt/codex-desktop/electron' >/dev/null 2>&1; then
kill "$pid"
fi
fi
done
Additional information
Both orphaned processes were manually killed during this report. The system also had 7 active CLI codex sessions on pts/* at the time — those are intentional interactive sessions and were left running. Only the zcode-cli Desktop-spawned processes were orphaned.