[Desktop Linux] Codex Desktop leaves orphaned `zcode-cli` processes after app quit (no SIGHUP/SIGTERM reaping)

Resolved 💬 0 comments Opened Jul 7, 2026 by SOSANA Closed Jul 7, 2026

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 annotation prod=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:

  1. PPID = 1247 (systemd --user), confirming the processes were reparented when Codex Desktop exited. PPID 1247 is /usr/lib/systemd/systemd --user, started Sun Jul 5 21:23:01 2026.
  2. PGID = SID = PID for each orphan, meaning each zcode-cli became 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.
  3. STAT = Ssl — sleeping, session leader, multi-threaded. Not spinning at 100% CPU (unlike #13928 / #19958), but still consuming memory and accumulating CPU time indefinitely.
  4. ~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

  1. Launch Codex Desktop on Linux.
  2. Use it normally (open a conversation, run a task).
  3. Quit/close Codex Desktop (window close or app quit).
  4. Check for orphaned processes:
ps -ef | grep zcode-cli | grep -v grep
  1. Observe: zcode-cli processes 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-cli holds 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:

  1. Track all zcode-cli child PIDs it spawns.
  2. On app quit, send SIGTERM to each child's process group (kill(-pgid, SIGTERM)), not just the direct child.
  3. After a bounded grace (e.g. 3–5s), send SIGKILL to any surviving process group.
  4. 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 /status orphan 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 SIGTERM to 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.

View original on GitHub ↗