Claude desktop app leaks pseudo-terminals (/dev/ptmx masters), exhausting the macOS pty pool
Summary
The Claude desktop app (/Applications/Claude.app) leaks pseudo-terminals: it appears to open a /dev/ptmx master fd per shell/tool command and never close it. Over a couple of days of normal use these accumulate until they hit kern.tty.ptmx_max (511 on macOS), after which no process on the machine can allocate a new pty — every terminal app breaks system-wide.
Environment
- macOS Darwin 25.5.0 (Apple Silicon)
- Claude desktop app:
/Applications/Claude.app claude-code2.1.156, running inside the desktop app
Symptom
After the app has been running ~2 days with regular Bash/tool use, launching any terminal (Terminal.app, iTerm2, VS Code integrated terminal) fails to start a shell:
forkpty: Device not configured
Could not create a new process and open a pseudo-tty.
This is system-wide — it affects every terminal app, not just Claude.
Root cause (confirmed via lsof)
The single Claude.app process holds open exactly kern.tty.ptmx_max master pty handles:
$ sysctl kern.tty.ptmx_max
kern.tty.ptmx_max: 511
$ lsof -n -P /dev/ptmx | grep -c ptmx
511
# every one owned by the same Claude.app PID; FDs 43,44,45,72,85,86,… climbing
So the entire pty pool is consumed by one long-lived process. The monotonically climbing fd numbers indicate masters opened per-command and never closed.
Workaround
Quitting and relaunching Claude.app closes all leaked fds and instantly restores the pty pool. (A reboot also works but is unnecessary.) Raising kern.tty.ptmx_max only defers the exhaustion since the leak continues.
Expected behavior
The pty master fd should be closed when each tool/command completes (and the child reaped), so the number of open ptys stays bounded by concurrent commands rather than total commands run over the app's lifetime.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗