[FEATURE] Make git worktree pooling opt-out: one worktree per session, removed only when the session is archived
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Claude Code Desktop maintains a pool of git worktrees with leases in %APPDATA%\Claude\git-worktrees.json. When a session is paused or stopped, that entry's leasedBy is set to null and a pooledAt timestamp is written. The next new session leases the now-free directory, overwrites the entry's branch and createdAt, and switches the directory's checked-out branch to its own per-session branch. A directory that a paused session was working in therefore silently changes identity, even though that session is still listed and expected to be resumed.
The timestamps line up to the second and make the mechanism unambiguous: an entry's createdAt equals the second at which the directory's git reflog records checkout: moving from <owner branch> to <foreign branch>, and its pooledAt equals the second at which the reflog records the release pair reset: moving to HEAD followed by checkout: … to HEAD. A non-null leasedBy protects a directory reliably — entries leased by long-stopped sessions have never been reclaimed, while every hijacked directory had leasedBy: null at the time.
What makes this expensive is that the release is invisible. It leaves the worktree detached on the correct commit, with identical content and a clean git status, so no cleanliness check and no git command reports anything unusual; the only evidence lives in the app's private registry. Observed consequences in one repository: a 118-commit rebase that finished as "updated detached HEAD" with the branch left behind, a session that committed onto a foreign ticket's branch, several sessions that had to be restarted, and hours spent re-diagnosing the same situation. Users who keep one worktree per ticket — the natural model when several tickets are open in parallel — hit this repeatedly, which defeats the purpose of worktrees for parallel work.
Users also cannot work around it. The lease checkout happens before the SessionStart hook fires, so no hook can prevent it; a hook can only re-hold the lease afterwards, which leaves a window. settings.json exposes only worktree.location, and its own schema text limits that to Claude Code Desktop SSH sessions. The desktop settings expose the worktree location but, as far as we can tell, no on/off for pooling. The behaviour appears to be gated by the server-side flag tengu_worktree_mode, which is not user-controllable.
Proposed Solution
A user-visible setting that disables pooling entirely, with the semantics "one worktree per session, removed only when the session is archived": the worktree is created fresh for that session, is never handed to another session, and is never reused in any form.
- Pausing or stopping a session must not touch its worktree. A paused session is expected to be resumed, and its worktree must still be there, on its own branch, when it is.
- The worktree is removed (deleted from disk and unregistered), not released back into a pool, as soon as its session is archived or deleted. No user-triggered cleanup is needed; the archive action is a sufficient trigger.
Alternative Solutions
A per-project or per-worktree "pin" that prevents a specific directory from ever re-entering the pool would already solve the practical problem, even if pooling stays the default elsewhere.
Alternatively, keep the pool but change when a directory enters it: only after its session is archived or deleted, never on pause or stop. That preserves the reuse optimisation for genuinely finished sessions while removing the case that causes damage. It is the weaker option, because a directory is still reused by another session, but it no longer takes a worktree away from a session that can still be resumed.
As a minimum, make the release visible instead of silent: when a lease would switch a directory away from a branch that another (non-archived) session still owns, either skip that directory and create a new one, or surface it in the session that finds itself in a renamed directory. Today the affected session has no signal at all.
Priority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
_No response_
Additional Context
_No response_
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
100% 👍🏼
<img width="426" height="210" alt="Image" src="https://github.com/user-attachments/assets/d1164a24-28cf-4304-9984-d71f04f92168" />
This is VERY misleading. The worktrees are not isolated at all, they share git ignored files, which for most projects is huge part of what is used to run the code you are working on. This causes all kinds of issues during development. You except an environment to be stable and predictable, the current architecture is the opposite of that. You get a stale environment from an unrelated session. Isolated means isolated, and this contract is broken in the desktop app. You can even have files change mid-session after resuming from idle. Even the directory name retains an outdated worktree name from however many sessions ago it was created... you are working on feature X and the terminal shows the CWD as something you worked on a week ago. It's all very confusing and bad DX. There are many more issues, I am only naming a few here.
@MJJKoenig I'd also update the title "released only when the session is archived" should be
removednotreleased(never re-used by another session).Also 100%. I've had sessions fighting with each other due to this. And getting around this is such a pain. I need to have a skill to create fresh worktrees and load a chip to start the "real" session there. Its a 2-session process each time, the first session makes the fresh worktree dir and suggests a task, that I always need to say "Start locally" instead of the always-default "Start with worktree" in the chip. Simply being able to disable the pooling would solve all of this for me.