ExitWorktree remove always reports 'Could not verify worktree state' for hook-created worktrees

Status Open
Reported on v2.1.295
Maintainer reply None cached
Activity 0 comments · opened Oct 9, 2026

Version: Claude Code 2.1.295, macOS (Darwin 25.6.0)

Steps to reproduce

  1. 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).

  1. Start claude in a git repository and ask it to "work in a worktree named test".

The hook runs and EnterWorktree switches into the new worktree.

  1. 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 without
originalHeadCommit (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.

View original on GitHub ↗