Repository navigation
Description
Use case: portable Claude Code workspace on an external SSD
I run Claude Code on an external SSD that physically shuttles between a Mac and a Windows desktop, with the same project directories accessible on both OSes (exFAT-formatted for cross-platform read/write). This is a common setup for solo developers / business owners who don't have a fixed workstation but want one consistent project tree.
The problem: MCP child processes outlive their parent Claude Code session and lock the SSD
After a few days of normal use (open Claude → work on a project on the SSD → close terminal or /exit), I end up with multiple orphan MCP server processes (firebase-tools mcp, shopify-dev-mcp, npm exec wrappers) holding open file handles on the SSD. They survive past Claude Code sessions and prevent safe ejection of the drive.
Today's diagnostic on Mac: 12 orphan MCP processes across 4 detached claude CLI processes (3 of which had tty=?? — terminals long since closed). Each Claude session had spawned 3 MCP children (firebase + shopify + npm wrapper). None had been cleaned up.
On Windows it's worse: no SIGHUP, so closing PowerShell silently orphans the parent claude.exe along with its MCP children. Defender's real-time scanning compounds the problem by holding additional handles.
The downstream consequence: filesystem corruption
When the drive can't be ejected cleanly, the user eventually force-unplugs. On the next Windows mount, the exFAT dirty bit is set, Windows reports wrong free-space numbers ("Full Repair Needed" in the Volume status), and chkdsk /f is the only fix. In my case chkdsk.exe was being silently blocked by the antivirus stack and would not run at all (exited in 0 seconds with no output), so the volume stayed dirty indefinitely. macOS fsck_exfat cleared it cleanly when I moved the drive there — but that's only because I happen to have both OSes available.
This isn't theoretical — I went through the full cycle today: chkdsk-blocked-by-AV → drive yanked → exFAT dirty bit → wrong free space → Mac fsck recovery. The chain started with "can't eject because MCP children won't release the drive."
Related but distinct issues
- [BUG] Child/nested claude processes orphan on /exit in WSL systemd environments, triggering cross-process GUI freezes via vmmem CPU spikes #51516 — Child claude processes orphan on
/exitin WSL (closely related, but WSL-specific) - [bug] agent-browser skill: Chrome headless processes orphaned after session ends (97% CPU, 10GB RAM leak) #50783 — agent-browser Chrome processes orphan after session ends (same shape, different child)
- [BUG] Docker-based MCP server containers not stopped when session ends #29058 — Docker MCP containers not stopped when session ends (same shape, container variant)
- Team shutdown_request acknowledged but teammates never terminate; TeamDelete blocked until session ends #49671 — Team shutdown_request acknowledged but teammates never terminate
- [FEATURE] Pre-exit Claude-action hook — let Claude perform actions before session ends #47612 — Pre-exit hook feature request
What distinguishes this issue: the orphan-process pattern has a tangible, recurring data-corruption impact for users on portable workspaces, not just a memory/CPU leak. And it's cross-platform — same root cause, different downstream symptoms on Mac vs Windows.
Reproduction
- Use Claude Code CLI on a project whose CWD is on an exFAT external drive
- Have user-scope MCP servers configured (e.g., the official
firebase-tools mcp,shopify-dev-mcp) - Close the terminal window without typing
/exit - Check
ps aux | grep mcp— MCP child processes are still running - Repeat across multiple sessions over a few days
- Try to eject the SSD — fails because of stale file handles
- Force-unplug → on Windows, dirty bit set on next mount
Proposed solutions (any one would help)
-
A reliable
SessionTerminatehook that fires on SIGHUP/terminal-close, not just on/exit. The currentSessionEndhook explicitly documents that it "may not run on ungraceful terminations" — this is the gap. -
MCP child-process tracking with parent-death detection. When the parent
claudeprocess exits or becomes orphaned (PPID=1), automatically send SIGTERM/SIGKILL to children. On Windows, register a process tree via job objects so termination cascades correctly. -
A
claude mcp reaporclaude doctor --cleansubcommand that finds and kills orphan MCP children whose parent claude process is no longer attached to a terminal. Even a manual mitigation would help — currently users have to write custompgrep/Get-CimInstancescripts. -
Explicit documentation of the orphan-process risk for users on portable drives + a recommended pre-eject workflow, until a proper fix lands.
My current workaround (in case helpful as a reference)
I had to build my own safe-eject scripts for both OSes:
- macOS:
lsof +Dto find blockers +pgrep -f "firebase-tools.*mcp|shopify-dev-mcp"+ parent-PID inspection +diskutil eject - Windows:
Get-CimInstance Win32_Processwith command-line regex + parent-process inspection +Shell.ApplicationCOM eject
Plus permanent on-volume markers (.metadata_never_index, .fseventsd/no_log on Mac; disabled IndexingEnabled on Windows) to stop the indexers from compounding the problem.
This works but it's user infrastructure that Claude Code itself should arguably own — especially given the data-loss-adjacent failure mode.
Environment
- Claude Code: latest stable (v2.1.144 area)
- Mac: macOS 14 Sequoia, external Extreme SSD via USB-C
- Windows: Windows 11, same physical drive
- MCP servers:
firebase-tools(Node.js),shopify-dev-mcp(Node.js), via user-scope configuration - Filesystem: exFAT (the only practical cross-platform option for >32 GB drives)
Happy to provide more diagnostic logs or test patches.
Activity
github-actions commentedon May 20, 2026
Found 3 possible duplicate issues:
disclaimer+ MCP child processes alive, accumulating GBs of RAM over a day #58915This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
jshaofa-ui commentedon May 20, 2026
Proposed Solution: MCP Subprocess Reaping on Parent Exit
Root Cause
No process group management for MCP children, missing signal handlers (SIGINT/SIGTERM/SIGHUP), no cleanup on /exit, and Windows has no SIGHUP equivalent. 12 orphan MCP processes observed across 4 detached claude sessions.
Proposed Fix
Process group + signal propagation with platform-specific handling:
Testing Strategy
Impact
Estimated service fee: $900-$1,700
Full solution:
~/.hermes/solutions/anthropics-claude-code-60747-mcp-subprocess-reaping-fix.mdlocalden commentedon May 23, 2026
Thanks for the report. This is the same issue as #1935 (stdio MCP child processes not terminated on exit). Consolidating tracking there.
github-actions commentedon Jul 12, 2026
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.