Shell snapshot subprocesses leaked on every session start (orphaned zsh/bash, zombies)
Summary
Claude Code leaks orphaned zsh (and bash) shell processes on every session start. Each launch spawns ~3 shell subprocesses to capture the user's shell environment into ~/.claude/shell-snapshots/. When the Claude Code process exits, these shells are reparented to PID 1 (launchd on macOS, init on Linux) but are never killed.
Over time these accumulate. On my system I found 18 orphaned -zsh processes (ppid=1), the oldest being 41 days old.
Steps to Reproduce
- Start Claude Code in a terminal (
claudeorclaude --resume <id>) - Observe 3 new
-zshprocesses spawned at the same timestamp - Exit the claude session (Ctrl+C or
/exit) - The 3 zsh shells remain running, reparented to PID 1
Repeating this over days/weeks accumulates dozens of idle shells.
Observed Behavior
$ ps -eo pid,ppid,stat,etime,command | awk '$2 == 1 && $4 == "-zsh"'
3173 1 S 34-15:12:35 -zsh
20841 1 S 24-17:30:54 -zsh
55080 1 S 14-17:40:07 -zsh
55081 1 S 14-17:40:07 -zsh
65977 1 S 41-12:22:04 -zsh
69073 1 S 14-17:15:14 -zsh
69078 1 S 14-17:15:14 -zsh
95864 1 S 34-19:45:17 -zsh
...
Some of these shells also hold zombie children (from the environment capture fork) that can never be reaped:
$ ps -eo pid,ppid,stat | awk '$3 ~ /Z/'
47738 47733 Z <defunct>
46658 46653 Z <defunct>
With powerlevel10k / oh-my-zsh, these orphans also leak gitstatusd child processes (p10k's git status daemon spawned during shell init).
The shell snapshot files in ~/.claude/shell-snapshots/ also accumulate indefinitely (52 files on my system, never cleaned up).
Expected Behavior
Shell subprocesses spawned for environment snapshotting should be killed after the snapshot is captured, or at minimum when the parent Claude Code process exits.
Environment
- Claude Code: 2.1.34
- Platform: macOS 15 (Darwin 24.6.0, ARM64)
- Shell: zsh with powerlevel10k + oh-my-zsh
- Terminal: iTerm2
Notes
- The leaked shells are bare
-zshlogin shells (not the Bash tool execution shells which are properly parented to the claude process) - They retain the original tty even after reparenting to launchd
- This affects any shell (zsh/bash) — the snapshot mechanism is shell-agnostic
- Workaround: periodic cleanup via launchd/cron to kill orphaned shells matching
ppid=1 && command == "-zsh"with age > 1 hour and no living children
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗