[BUG] Desktop remote/SSH: archive never cleans up worktrees since 2.1.235 — app requires hardened git.status(baseRepo) but only ships a 2026-07-06 daemon, so "reconnect to deploy the updated daemon" is a no-op
Summary
Since ~2.1.235, archiving a remote (SSH/devcontainer) session in the Claude desktop app never cleans up its git worktree. The app requires a hardened git.status(baseRepo) RPC from the remote daemon, but the daemon it deploys was built 2026-07-06 — roughly six weeks before the requirement landed. Every archive fails the pre-delete dirty-check and leaks the worktree.
The error tells you to reconnect to deploy an updated daemon. Reconnecting redeploys the same binary, byte-identically. There is no newer daemon on the machine, so the documented remedy cannot succeed from the user side.
Environment
- Claude desktop app on macOS
- Remote devcontainers over SSH on a separate Linux host (3 independent containers, same behaviour in all)
ccd-cli2.1.237- Remote daemon:
claude-ssh 5db5e4a12f88487e47c2c48259b69a2d630bb3f7 (built 2026-07-06T20:46:38Z)
Reproduce
- Open a Claude Code Desktop session against a remote/SSH devcontainer (session gets a worktree under
.claude/worktrees/). - Archive the session.
- The worktree remains on disk;
~/Library/Logs/Claude/main.logshows the error below.
Reproduced with a brand-new session created and archived immediately, on a freshly respawned daemon.
The error
[warn] getSessionUncommittedChanges: remote check failed for session local_34dd3473-…
[error] Failed to clean up worktree for session local_34dd3473-…
Remote daemon predates hardened git.status (baseRepo); refusing unhardened dirty-check
for "/workspace/.claude/worktrees/new-session-fbdec3" — reconnect to deploy the updated daemon
at Ot.getRemoteUncommittedChanges (…/app.asar/.vite/build/index.chunk-CgncK-Xq.js:1:56502)
at e.getSessionUncommittedChanges (…/app.asar/.vite/build/index2.chunk-BoMiMWA8.js:1:357508)
at Object.getUncommittedChanges (…/app.asar/.vite/build/index.chunk-2g9lpGtG.js:1:24092)
Why the suggested remedy cannot work
Killed the --serve daemon and reconnected, forcing a full respawn + redeploy. The app rewrote the binary — with identical content:
before: 6336664 bytes, mtime 2026-08-20 23:16
after: 6336664 bytes, mtime 2026-08-22 12:13
The respawned daemon self-reports the same pre-hardening build:
$ ~/.claude/remote/srv/5db5e4a12f88487e47c2c48259b69a2d630bb3f7/server --version
claude-ssh 5db5e4a12f88487e47c2c48259b69a2d630bb3f7 (built 2026-07-06T20:46:38Z)
Only two daemon builds exist on disk, and both predate the requirement:
5db5e4a1… built 2026-07-06T20:46:38Z ← the one deployed
7c2f88d1… built 2026-07-02T06:09:19Z
Verified across three independent devcontainers, all respawned at the same moment; all three came back on the 2026-07-06 build, and archiving still fails.
Note the two remote artifacts are on very different update cadences — ccd-cli moved 2.1.234 → 2.1.235 → 2.1.237 in three days, while the daemon has not moved since early July. The hardening appears to have shipped in the app without a matching daemon build.
Version boundary
| Session archived | ccd-cli at the time | Worktree |
|---|---|---|
| 2026-08-19 03:30Z | 2.1.234 (installed Aug 18 18:46) | cleaned up correctly |
| 2026-08-20 21:40Z | 2.1.235 (installed Aug 20 15:57) | leaked |
| every archive since | 2.1.235 / 2.1.237 | leaked (9 of 9) |
Last good is 2.1.234, matching the boundary independently reported in #88836.
Impact
Worktrees accumulate silently — one per archived session, each a full checkout. In our repo this is not cosmetic: worktrees are allocated a port/DB offset from a pool of 10, so once the leaked worktrees fill it, the test suite fails to start with an error that names nothing relevant (claim-offset: no free offset). It took a full debugging session to trace that back to archive cleanup.
Ruled out
- Not the remote setup itself. Cleanup worked in this exact SSH/devcontainer arrangement on Jul 29, Aug 4, Aug 9 and Aug 19; the container and its remote tooling predate all of them.
- Not git locks. No worktree is locked (
git worktree list --porcelainreports none; nolockedfiles). - Not dirty worktrees. 7 of 8 leaked worktrees are clean per
git status --porcelain;git worktree removesucceeds on them by hand. - Not a stale daemon process. Killing it and letting the app respawn reproduces the failure on the fresh process.
Related
- #88239 — same consequence (a refused pre-delete check leaks the worktree) but local rather than remote, and gated on commit reachability after a squash merge rather than a daemon version handshake. Possibly the same hardening push landing on two surfaces.
- #88253 — Desktop's own git subprocesses failing inside worktrees, but caused by macOS sandbox EPERM, not a version handshake.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗