Claude.app leaks PTY master fds (/dev/ptmx) — exhausts macOS kern.tty.ptmx_max after long Bash-heavy sessions
Summary
Claude.app (macOS desktop) leaks one open /dev/ptmx master fd per Bash tool invocation. The fds accumulate until macOS PTY limit (kern.tty.ptmx_max = 511) is exhausted, causing all terminal emulators on the system to fail with "cannot allocate any more pty devices".
Environment
- macOS Darwin 25.5.0
- Claude.app (desktop, Electron)
- Ghostty terminal emulator
kern.tty.ptmx_max = 511(macOS default)
Reproduction
- Start a Claude Code session in Claude.app (desktop).
- Run many Bash tool calls over several hours (e.g., a complex multi-step engineering task with 100+ Bash invocations).
- Observe:
/dev/ttys*accumulates without bound, never shrinks. - Eventually, opening a new terminal tab/window fails with: "Your system cannot allocate any more pty devices."
Evidence
After a ~5-hour session with ~500 Bash tool calls:
$ ls /dev/ttys* | wc -l
527
$ lsof -p <Claude.app PID> | grep ptmx | wc -l
510
$ lsof -p <Claude.app PID> | grep ptmx | head -3
Claude 34050 elihu 43u CHR 15,218 0t0 605 /dev/ptmx
Claude 34050 elihu 73u CHR 15,229 0t0 605 /dev/ptmx
Claude 34050 elihu 80u CHR 15,401 0t0 605 /dev/ptmx
$ sysctl kern.tty.ptmx_max
kern.tty.ptmx_max: 511
PTY creation rate correlates 1:1 with Bash tool invocations (verified via stat timestamps on /dev/ttys*).
Root Cause
Each Bash tool call opens a PTY master via /dev/ptmx but the fd is never closed after the child process exits. On macOS, the slave device (/dev/ttysXXX) is not reclaimed until the master fd is released.
Impact
Exhausts system-wide PTY slots. All processes on the machine that need a new terminal (Ghostty, iTerm2, Terminal.app, ssh, tmux) fail until Claude.app is restarted.
Workaround
Restart Claude.app — releases all leaked fds, kernel immediately reclaims the zombie PTY devices.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗