Desktop: manual Archive deletes worktree with uncommitted changes, no confirmation
What happens
The "Archive" button in Claude Code Desktop unconditionally deletes the session's git worktree, including any uncommitted local changes — with no confirmation dialog and no dirty-state check.
The session JSON is preserved (just flagged isArchived: true), but anything in the worktree filesystem that wasn't committed/pushed is gone.
Repro
- Start a session in a Claude-Desktop-managed worktree.
- Have any uncommitted/unpushed work in the worktree.
- Trigger Archive — either:
- Right-click session → "Archive" in the context menu, or
- Press
Awhile the context menu is open (this is the worse footgun: an accidental keystroke with the menu visible silently nukes the worktree).
- Worktree directory is removed via
git worktree remove --force(withfs.rmrecursive-force fallback). No prompt, no undo.
Code path (extracted from app.asar @ v1.5354.0)
UI side (ion-dist/.../index-BNbM_KX7.js, cbc59a8af-D4zw98by.js):
await archive(sessionId, { cleanupWorktree: true })
Hardcoded true everywhere it's called.
Main process (teardownSession):
if (i.cleanupWorktree !== false && o.worktreePath) {
// removeWorktree
}
Worktree removal:
git -c core.longpaths=true worktree remove --force <path>
// fallback:
await fs.rm(path, { recursive: true, force: true })
--force overrides git's "uncommitted changes" guard; the fs.rm fallback bypasses it entirely.
Searching the whole bundle: every caller of archive / archiveSession passes either cleanupWorktree: true or undefined (which the !== false check still treats as "delete"). The backend has the capability to skip cleanup, but no code path uses it.
Why this is the wrong default for manual archive
Aggressive cleanup makes sense for AutoArchiveEngine (PR merged → worktree disposable). It's the wrong default for the user-facing Archive button, where the user may have:
- Uncommitted experimental changes
- Local-only branches not yet pushed
- Work-in-progress not ready for PR
There's also an asymmetry users don't expect: session JSON is soft-deleted (preserved + flagged, recoverable via tooling), worktree is hard-deleted with --force. "Archive" reasonably implies the same retention semantics for both.
Related: #54047 (transcript deletion on PR-merge cleanup, closed). Same root pattern — cleanup decisions coupled to a single irreversible flag.
Ask
For the manual Archive flow, at minimum one of:
- Confirmation dialog when the worktree has uncommitted changes or unpushed commits.
- UI toggle "Also delete worktree" (visible, defaultable).
- Soft-delete the worktree (move to Trash /
~/.claude/archived-worktrees/) instead of recursive force-delete. - Drop
--force, surface the git error to the user, let them decide.
The backend already supports cleanupWorktree: false end-to-end — only the UI never sends it.
Environment
- Claude Desktop v1.5354.0
- macOS 15.4 (Darwin 25.4.0)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗