Orphaned claude.exe subprocesses (resume flag) accumulate after closing Claude Desktop session windows on Windows

Resolved 💬 3 comments Opened May 13, 2026 by nwong-kftea Closed May 16, 2026

## Summary

Closing a Claude Code session window inside the Claude Desktop app does not terminate the underlying claude.exe --resume <uuid> subprocess. These orphans accumulate over hours/days, each holding ~50-75 MB of RAM and an open stdin pipe to the parent Electron main process.

Environment

  • OS: Windows 11 Pro 10.0.26200
  • Claude Desktop: 1.7196.0.0 (C:\Program Files\WindowsApps\Claude_1.7196.0.0_x64__pzs8sxrjxfjjc\app\claude.exe)
  • Claude Code: 2.1.138 (%AppData%\Roaming\Claude\claude-code\2.1.138\claude.exe)
  • Repro: consistent — observed 6 orphans after ~6 hours of normal use

Reproduction

  1. Open Claude Desktop and start a Claude Code session.
  2. Have a brief conversation so the session gets a UUID and is persisted.
  3. Close the session window (X button) — the UI is gone.
  4. Inspect processes:

``powershell
Get-CimInstance Win32_Process -Filter "Name='claude.exe'" |
Where-Object { $_.CommandLine -like "*--resume*" } |
Select-Object ProcessId,
@{N='AgeMin';E={[math]::Round(((Get-Date) - $_.CreationDate).TotalMinutes,0)}},
@{N='MemMB';E={[math]::Round($_.WorkingSetSize/1MB,1)}}
``

  1. Observe: the claude.exe --resume <uuid> process for the closed session is still running, still parented to the Claude Desktop main process. It will sit idle indefinitely.

Actual observation

8 claude.exe processes running, 6 of them orphans aged 5–6 hours with no corresponding UI window. All share parent PID matching the Claude Desktop main process and were launched with --output-format stream-json --verbose --input-format stream-json ... --resume <uuid>.

Expected behavior

When a session window closes, the corresponding claude.exe --resume subprocess should terminate within a few seconds — via explicit Stop-Process/SIGTERM from the parent on renderer destroy, closing the stdin pipe so the child reads EOF and exits, or a Windows Job Object association so children die with the parent.

Why the leak happens (best guess)

  • The claude.exe --resume subprocess is spawned by the Electron main process, not the renderer hosting the session UI.
  • When a renderer is destroyed (window closed), the main process keeps running and keeps the stdin pipe to the subprocess open.
  • The subprocess blocks on read from stdin waiting for the next stream-json message, never receives EOF, never exits.
  • No idle timeout or heartbeat detects the lost UI peer.

Workaround

Get-CimInstance Win32_Process -Filter "Name='claude.exe'" |
  Where-Object {
    $_.CommandLine -like "*--resume*" -and
    ((Get-Date) - $_.CreationDate).TotalHours -gt 2
  } |
  ForEach-Object { Stop-Process -Id $_.ProcessId -Force }

Suggested fixes (in order of robustness)

  1. Windows Job Object with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE so children die if Desktop main dies.
  2. Renderer lifecycle hook — track renderer-to-subprocess mapping; kill subprocess on renderer closed event.
  3. Close stdin pipe on UI close so child reads EOF and exits cleanly.
  4. Idle timeout in the CLI — exit after N minutes of stdin silence when launched in stream-json mode.

Impact

  • ~50-75 MB RAM leak per closed session
  • Pollutes process list, making it harder to identify real active sessions
  • Confusing for users — looks like Claude Code has a phantom session problem when it is actually a Desktop wrapper issue
  • Could mask other subprocess leaks (MCP server connections, child agents)

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗