Documentsclaude-code
Subagent Resource Management
Subagent Resource Management
Type
Topic
Status
Published
Created
May 29, 2026
Updated
May 29, 2026

Subagent Resource Management#

When Claude Code spawns a subagent via the Agent tool, each subagent initializes its own full set of MCP server child processes from the current configuration. When the subagent's claude process terminates, those MCP child processes are not reliably cleaned up — they become orphans that accumulate across sessions .

This is an ongoing, cross-platform bug (tracked in issue #1935) with multiple partial fixes across versions. The problem is not limited to subagents: the main Claude Code process itself has repeatedly failed to clean up MCP servers on exit .


Why Orphans Accumulate#

Unix (macOS/Linux): When the parent claude process exits without explicitly terminating its stdio-MCP children, those children are reparented. On macOS they reparent to launchd (PPID=1); on Linux to systemd --user . Neither of those reapers terminates them.

Windows: Child process trees (cmd.exenode.exe/bun.exe) are not automatically killed on parent exit. The canonical fix is to use Win32 Job Objects with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, which Claude Code does not currently apply to MCP children. Each short-lived subagent run can leave 5–10 orphan processes (one per configured MCP server) .

--print / headless mode: In non-interactive --print mode, Claude Code closes stdin without sending SIGINT/SIGTERM to MCP servers, leaving processes alive if they have other active handles .

Desktop app (Windows): Closing the window via the X button is not equivalent to quitting the app — the backend process remains alive, and spawned MCP children survive. Subsequent window opens may fail to re-acquire those processes and silently skip them from the MCP roster .


Observed Severity#

PlatformObserved accumulationImpact
macOS40+ orphaned Docker/Node/Python MCP processes from multiple sessions Resource drain; stale Docker containers
Linux80 orphaned lark-mcp processes (~1 GB RSS each), 32 GB RAM consumed on a 92 GB workstation OOM kills on concurrent builds
Windows27 cmd.exe + 20 node.exe + 6 bun.exe orphans from a few subagent runs; 5 MCP servers × N subagents = N×5 orphan burst Rapid process count explosion
Desktop app156 accumulated claude CLI subprocess instances, ~31 GB RAM Unbounded memory growth

Version History of Fixes (Partial)#

The following fixes have landed but the issue persists as of v2.1.128+:

VersionFix
1.0.21Stdio MCP server processes linger after quit — first fix attempt
1.0.36Stdio MCP servers not terminating properly on exit
2.1.15MCP stdio server timeout not killing child process, causing UI freezes
2.1.19Dangling Claude Code processes on terminal close — EIO/SIGKILL fallback added
2.1.24Stdio MCP server processes linger after quit — second fix pass
2.1.73Background bash processes spawned by subagents not cleaned up on agent exit
2.1.132External SIGINT (IDE stop button, kill -INT) not triggering graceful shutdown

Workarounds#

Session-end hook (macOS/Linux)#

cc-reaper implements a Stop hook that fires when a session ends and kills orphan MCP processes, plus a proc-janitor daemon for crash scenarios. Uses PPID=1 detection to target only true orphans .

Periodic daemon (macOS/Linux)#

mcp-orphan-monitor runs every 10 minutes via launchd (macOS) or cron (Linux), detects orphans by PPID=1 and sends SIGKILL . Complements the hook approach: covers crash/force-quit cases where no Stop hook fires.

Subagent-cleanup plugin (cross-platform)#

PR #47830 (open as of 2026-05) proposes a SessionStart hook plugin that walks the current process's parent PID chain, identifies unprotected claude --resume orphans from prior subagent runs, and sends SIGTERM .

MCP gateway (Docker)#

airis-mcp-gateway wraps all MCP servers behind a single long-lived Docker container that lazily starts servers on first tool call and idle-kills them. docker compose down guarantees cleanup regardless of Claude Code exit behavior .

MCP server self-defense (server authors)#

Servers can self-terminate on stdin EOF — the canonical signal that the parent dropped the connection — in addition to SIGTERM/SIGINT/SIGHUP. On Windows, handle SIGBREAK as well .


  • #1935 — Primary tracking issue (MCP servers not terminated on exit)
  • #48649 — Subagents multiply MCP server processes (N×M kernel resource consumption)
  • #54554preview_stop leaves orphaned descendant processes
  • #53134 — MCP servers spawned twice at startup (directMcpHost vs LocalMcpServerManager)
  • PR #61750 (open) — Desktop app subprocess accumulation troubleshooting docs
Subagent Resource Management | Dosu