CLI process survives terminal close — no stdin end handler, unbounded memory growth
Resolved 💬 3 comments Opened Apr 7, 2026 by DanielleFong Closed Apr 10, 2026
Summary
Claude Code CLI processes survive terminal close and grow memory unbounded. Observed a single orphaned process consume 35.4GB RSS over 21 days at 95% CPU on WSL2.
Root Cause (from cli.js source analysis)
- When a terminal closes, SIGHUP is sent. The
signal-exitlibrary catches it and re-emits, but other listeners can prevent the default exit behavior. - The main CLI entry point has no
process.stdin.on("end")handler. The Computer Use MCP codepath does have one (around offset 6890881 in the minified bundle), but the interactive CLI session does not. - With stdin dead and no exit trigger, the 55+
setIntervaltimers in the codebase (settings polling, telemetry, status line refresh, etc.) keep the Node.js event loop alive indefinitely. - V8 heap grows unchecked — no idle GC pressure, no
--max-old-space-sizelimit, no self-termination watchdog.
Evidence
- PID 258760: 21 days uptime, 35.4GB RSS, 95.5% CPU, ppid=1 (orphaned), no TTY
- 13 additional boot-time sessions: 25 days old, 120-450MB each, all with dead terminals (Windows Terminal tabs that were closed but WSL processes survived)
- Killing the orphan reclaimed 34GB immediately
- Environment: WSL2 (Linux 6.6.87.2), Claude Code 2.1.92, Windows Terminal
Suggested Fix
Add to the main CLI entry point:
process.stdin.on("end", () => {
// Terminal closed — stdin is dead, no user to interact with
process.exit(0);
});
This already exists in the Computer Use MCP server codepath but is missing from the interactive CLI session.
Additionally, consider:
- Setting
--max-old-space-sizeon the Node process - A watchdog timer that checks if stdin/stdout are still connected
- Clearing
setIntervaltimers when the session becomes idle
Reproduction
- Open Claude Code in a terminal
- Close the terminal window (not Ctrl+C — close the window/tab)
- Observe the
claudeprocess continues running with ppid=1 - Over days/weeks, RSS grows unbounded
Impact
On a 96GB WSL2 system running multiple Claude Code sessions, a single orphaned process consumed 35GB (37% of total RAM) and pushed 12GB into swap, degrading performance for all other sessions.
🤖 Generated with Claude Code
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗