anthropics / anthropics/claude-code
[BUG] Desktop over SSH leaves previous builds' remote servers running on the host; sessions inherit launchd's 256 fd limit and crash
- Langage dominant
- Python
- Étoiles
- 145k
- Forks
- 23.1k
- Métriques de merge des PR
- Métriques de PR en attente
Description
### Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
### What's Wrong?
Claude Desktop (macOS) connected to a remote Mac over SSH starts a remote server process on the host (`~/.claude/remote/srv//server --serve`) for each app build, but never tears the previous build's server down on update or reconnect. Existing sessions reconnect to whichever old server they were on. Over two months this left ten `--serve` processes alive on the host, seven of them from builds dating back to early July, plus 24 orphaned `ccd-cli` session processes across versions 2.1.229 to 2.1.260.
The practical consequence on macOS hosts: the servers are launched under launchd's default soft limit of 256 file descriptors and pass that limit to every session they spawn. A session with a few MCP servers plus subagents then crashes with:
```
Claude Code process exited with code 1
error: An unknown error occurred, possibly due to low max file descriptors (Unexpected)
Current limit: 256
To fix this, try running:
ulimit -n 2147483646
If that still doesn't work, you may need to run:
sudo launchctl limit maxfiles 2147483646
```
The Desktop dialog wraps this as "Couldn't access this folder", which points users at folder permissions rather than the real cause.
Two things in the advice text don't work in this configuration:
- `ulimit -n` in a terminal does nothing, because the session is not launched from that shell. Only the launchd limit matters.
- The suggested value exceeds `kern.maxfilesperproc` (61440 here).
Fully quitting and relaunching Desktop does not fix it: a fresh server starts, but the crashed session reconnects to the old server (verified by the new session process's parent pid) and inherits 256 again. The only fix was to raise the launchd limit, quit Desktop, `pkill` every remote server and CLI process on the host, and relaunch.
### Steps to Reproduce
1. On a Mac host with default launchd limits, use Claude Desktop from another Mac over SSH for several weeks across multiple Desktop updates.
2. On the host, list server processes:
```
ps -axo pid,lstart,command | grep 'remote/srv/.*--serve'
```
One server per historical build is still running, most with no live sessions.
3. In a Desktop session attached to one of the older servers, open a session with a couple of MCP servers and spawn subagents. It exits with the fd error above.
4. Cmd+Q and relaunch Desktop, retry the session: same error, because it reconnects to the old server.
### Expected Behavior
- On update or reconnect, Desktop should stop the previous build's remote server once its sessions have been migrated, or migrate sessions to the new server so old servers can exit.
- The remote server should raise its own soft fd limit toward the hard limit at startup (the hard limit was `unlimited` here), the way the CLI appears to when launched from a shell, rather than inheriting launchd's 256.
- The error text should not recommend `ulimit -n` for Desktop-launched sessions, and should not suggest a value above the kernel cap.
### Environment
- Host (where sessions run): Mac mini, macOS 26.x (Darwin 25.5.0), Claude Code remote CLI 2.1.260, remote server builds 7c2f88d, 5db5e4a, 7d193f8, 678bbae, 4534d86 all found running concurrently
- Client: Claude Desktop on a MacBook, connecting over SSH via Tailscale
- `launchctl limit maxfiles` on the host before fix: `256 unlimited`; `kern.maxfilesperproc`: 61440
### Workaround
On the host:
```
sudo launchctl limit maxfiles 65536 200000
```
plus a `/Library/LaunchDaemons/limit.maxfiles.plist` with the same values, then quit Desktop, `pkill -f '.claude/remote/srv' ; pkill -f '.claude/remote/ccd-cli'`, and relaunch. Note that Claude Code's own permission classifier blocks the `pkill` from inside a session, so the sweep has to be done by hand.
Guide de contribution
Aucun guide de contribution indexé pour ce dépôt
Piste de recherche
Start by reproducing the remote-server process listing with `ps -axo ...` on a macOS host, then trace how Desktop updates and reconnects choose and retire `~/.claude/remote/srv//server --serve` and spawn `ccd-cli` sessions. Done means old servers and orphaned sessions exit or migrate, new sessions inherit an appropriate descriptor limit, and Desktop guidance matches the actual launchd and kernel limits.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- cli, macos
- Domaine
- cli, desktop, infrastructure, operating-systems
- Type d'issue
- Bug
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- Active
- Clarté
- Plutôt claire
- Accessibilité débutants
- 32/100