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)

  1. When a terminal closes, SIGHUP is sent. The signal-exit library catches it and re-emits, but other listeners can prevent the default exit behavior.
  2. 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.
  3. With stdin dead and no exit trigger, the 55+ setInterval timers in the codebase (settings polling, telemetry, status line refresh, etc.) keep the Node.js event loop alive indefinitely.
  4. V8 heap grows unchecked — no idle GC pressure, no --max-old-space-size limit, 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-size on the Node process
  • A watchdog timer that checks if stdin/stdout are still connected
  • Clearing setInterval timers when the session becomes idle

Reproduction

  1. Open Claude Code in a terminal
  2. Close the terminal window (not Ctrl+C — close the window/tab)
  3. Observe the claude process continues running with ppid=1
  4. 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

View original on GitHub ↗

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