ExitWorktree remove always reports 'Could not verify worktree state' for hook-created worktrees
Version: Claude Code 2.1.295, macOS (Darwin 25.6.0)
Steps to reproduce
- Configure a WorktreeCreate hook in ~/.claude/settings.json that creates the worktree with
git worktree add and prints its path (any location, mine is a sibling of the checkout).
- Start
claudein a git repository and ask it to "work in a worktree named test".
The hook runs and EnterWorktree switches into the new worktree.
- Make no changes, then ask Claude to delete the worktree.
Expected
The worktree is clean, so ExitWorktree with action "remove" removes it without a confirmation
step, the same way the keep/remove prompt at session exit does for a clean hook-based worktree.
Actual
ExitWorktree refuses every time:
Could not verify worktree state at <path>. Refusing to remove without explicit confirmation.
Re-invoke with discard_changes: true to proceed — or use action: "keep" to preserve the worktree.
Claude then checks git status by hand and re-invokes with discard_changes: true, which works
and does run the WorktreeRemove hook. The refusal happens on a clean worktree, on every attempt,
regardless of repository.
Cause
In the EnterWorktree creation code, the hook path builds the session record withoutoriginalHeadCommit (it only sets path, name, session id and hookBased: true), while the
built-in git path records originalHeadCommit from the worktree it created.
The ExitWorktree state check destructures originalHeadCommit and returns null when it is
missing, before counting commits, with no exemption for hookBased:
async function Cr(e,r){let{originalHeadCommit:n}=r; ... if(!n)return null; ...}
A null result maps directly to the "Could not verify worktree state" message. The session-exit
cleanup path already handles this case differently: it treats a hook-based worktree with no
recorded head commit as having zero new commits and only counts file changes
(let En=oo.hookBased?0:null; if(oo.originalHeadCommit){...}). ExitWorktree needs the same
exemption, or the hook path should record the worktree's HEAD after the hook returns.
Side note
The docs (worktrees.md) say the "can't verify" prompt "names what it couldn't check". The
ExitWorktree message is generic, so it took reading the bundle to find the reason. Naming the
missing piece in the message would have made this a five-minute diagnosis.