Summary
RTK spawns grep subprocesses (via rtk grep rewrites) that accumulate memory without releasing it. On a 96GB Mac
Studio M2 Ultra, 8 concurrent grep processes in RTK's coalition consumed a combined ~514GB (RAM + swap), exhausting
all memory and triggering a macOS kernel panic.
Environment
- RTK version: 0.29.0
- macOS: 26.3.1 (25D2128), Apple Silicon (Mac15,14 / M2 Ultra)
- RAM: 96GB
- Integration: Claude Code PreToolUse hook via rtk-rewrite.sh
What happened
While Claude Code was running bash commands (all routed through the RTK hook), grep subprocesses spawned by RTK
accumulated memory progressively over the session. The system triggered 5 JetsamEvents between 09:48–10:03 UTC
before crashing.
Kernel panic log:
panic(cpu 3 caller 0xfffffe0038d680e4): userspace watchdog timeout:
no successful checkins from WindowServer in 204 seconds
WindowServer could not allocate memory and hung, causing a hard reboot.
Data from JetsamEvent at crash time (coalition 707 = RTK)
┌─────────┬───────────┬───────────────────────────┐
│ Process │ Instances │ Total memory (incl. swap) │
├─────────┼───────────┼───────────────────────────┤
│ grep │ 8 │ ~505 GB │
├─────────┼───────────┼───────────────────────────┤
│ rtk │ 8 │ ~9 GB │
├─────────┼───────────┼───────────────────────────┤
│ Total │ │ ~514 GB │
└─────────┴───────────┴───────────────────────────┘
Worst individual grep process:
name: grep
pid: 97560
rpages: 12,126,704 (× 16384 bytes = ~198 GB)
cpuTime: 1048.6s
physicalPages.internal: [2010, 12118749]
Each rtk instance has an adjacent grep subprocess (sequential PIDs), confirming RTK spawns one grep per command
invocation. These processes do not terminate after the command completes.
Root cause hypothesis
The grep subprocesses appear to remain alive with their stdin pipe open after the parent rtk process exits. On
Unix, a process reading from a pipe blocks indefinitely if the write end is never closed. Over multiple commands,
these zombie-like grep processes accumulate memory until the system collapses.
Reproduction
Run Claude Code with the RTK PreToolUse hook active for an extended session involving large file reads or many bash
commands. Monitor memory with ps -eo pid,rss,comm | sort -k2 -rn — grep processes will grow continuously and not
exit.
Fix suggestion
Ensure grep subprocesses are killed when the parent rtk process exits — e.g., using a process group and sending
SIGKILL to the group on exit, or closing the write end of the stdin pipe e
Summary
RTK spawns grep subprocesses (via rtk grep rewrites) that accumulate memory without releasing it. On a 96GB Mac
Studio M2 Ultra, 8 concurrent grep processes in RTK's coalition consumed a combined ~514GB (RAM + swap), exhausting
all memory and triggering a macOS kernel panic.
Environment
What happened
While Claude Code was running bash commands (all routed through the RTK hook), grep subprocesses spawned by RTK
accumulated memory progressively over the session. The system triggered 5 JetsamEvents between 09:48–10:03 UTC
before crashing.
Kernel panic log:
panic(cpu 3 caller 0xfffffe0038d680e4): userspace watchdog timeout:
no successful checkins from WindowServer in 204 seconds
WindowServer could not allocate memory and hung, causing a hard reboot.
Data from JetsamEvent at crash time (coalition 707 = RTK)
┌─────────┬───────────┬───────────────────────────┐
│ Process │ Instances │ Total memory (incl. swap) │
├─────────┼───────────┼───────────────────────────┤
│ grep │ 8 │ ~505 GB │
├─────────┼───────────┼───────────────────────────┤
│ rtk │ 8 │ ~9 GB │
├─────────┼───────────┼───────────────────────────┤
│ Total │ │ ~514 GB │
└─────────┴───────────┴───────────────────────────┘
Worst individual grep process:
name: grep
pid: 97560
rpages: 12,126,704 (× 16384 bytes = ~198 GB)
cpuTime: 1048.6s
physicalPages.internal: [2010, 12118749]
Each rtk instance has an adjacent grep subprocess (sequential PIDs), confirming RTK spawns one grep per command
invocation. These processes do not terminate after the command completes.
Root cause hypothesis
The grep subprocesses appear to remain alive with their stdin pipe open after the parent rtk process exits. On
Unix, a process reading from a pipe blocks indefinitely if the write end is never closed. Over multiple commands,
these zombie-like grep processes accumulate memory until the system collapses.
Reproduction
Run Claude Code with the RTK PreToolUse hook active for an extended session involving large file reads or many bash
commands. Monitor memory with ps -eo pid,rss,comm | sort -k2 -rn — grep processes will grow continuously and not
exit.
Fix suggestion
Ensure grep subprocesses are killed when the parent rtk process exits — e.g., using a process group and sending
SIGKILL to the group on exit, or closing the write end of the stdin pipe e