[BUG] WorktreeRemove hook never fires on worktree removal (claude --worktree exit → remove)

Status Closed — duplicate
Reported on v2.1.214
Maintainer reply None cached
Activity 2 comments · opened Jul 19, 2026 · closed Aug 15, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet (closest is #36205, but it states this path should work — see Additional Information)
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

A WorktreeRemove command hook configured in ~/.claude/settings.json never runs when a worktree created with claude --worktree <name> is removed via the interactive session-exit "remove" prompt. The worktree is deleted correctly, but the WorktreeRemove event is never dispatched, so the hook command never executes.

The hook config is valid and loaded — I verified this two ways in the same session:

  • A PostToolUse control hook in the same settings file fires normally.
  • A --debug trace shows the worktree being removed with no WorktreeRemove dispatch.

Reproduced from a brand-new terminal (fresh claude process), so this is not a mid-session config-reload issue.

What Should Happen?

Per the worktrees and hooks docs, removing a worktree should fire the WorktreeRemove hook (with worktree_path on stdin) so per-worktree cleanup — e.g. dropping a scoped dev database, removing a virtualenv, releasing ports — can run.

Error Messages/Logs

# 1) The synchronous PostToolUse hook DOES register and fire — right after a Bash
#    tool call, Claude processes the hook's (non-JSON) output:
[INFO]  [Stall] tool_dispatch_end tool=Bash toolUseId=... outcome=ok
[DEBUG] Hook output does not start with {, treating as plain text   # <- PostToolUse hook ran

# 2) The worktree is removed cleanly, but NO hook output is processed here —
#    the WorktreeRemove event is never dispatched:
[DEBUG] Removed linked worktree at: .../.claude/worktrees/probe
[DEBUG] Deleted worktree branch: worktree-probe
[DEBUG] Linked worktree cleaned up completely

# Result: post-tool-use.log has a line (hooks live); worktree-remove.log never created.

Please don't be misled by the two 0 hooks debug lines — I checked, and neither refers to the synchronous settings-hook dispatch table:

  • Registered 0 hooks from 0 plugins — the plugin hook registry (I have no plugins).
  • Hooks: Found 0 total hooks in registry — always emitted alongside checkForNewResponses returning 0 responses, i.e. the async-hook response poll (no async hooks here).

The synchronous PostToolUse hook from the same settings file demonstrably fires (the Hook output does not start with { line above is Claude handling its output), so settings hooks load and dispatch fine. WorktreeRemove specifically is never dispatched on removal.

Steps to Reproduce

  1. Add this to ~/.claude/settings.json (the PostToolUse hook is a control, to prove hooks load):

``json
{
"hooks": {
"PostToolUse": [
{ "matcher": "Bash", "hooks": [
{ "type": "command", "command": "echo \"PostToolUse fired $(date)\" >> ~/.claude/post-tool-use.log" } ] }
],
"WorktreeRemove": [
{ "hooks": [
{ "type": "command", "command": "echo \"WorktreeRemove fired $(date)\" >> ~/.claude/worktree-remove.log" } ] }
]
}
}
``

  1. Ensure ~/.claude/post-tool-use.log and ~/.claude/worktree-remove.log do not exist.
  2. In a new terminal: claude --worktree probe
  3. Inside the session, run any bash command (e.g. echo hi).
  4. Exit the session (Ctrl-D or /exit) and choose remove at the keep/remove prompt.
  5. cat ~/.claude/post-tool-use.log ~/.claude/worktree-remove.log

Result: post-tool-use.log contains a line (hooks are live this session); worktree-remove.log is empty (WorktreeRemove never fired). git worktree list confirms the worktree was removed.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

(unknown — not bisected)

Claude Code Version

2.1.214 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

  • Related but distinct — #36205. That issue states the claude --worktree CLI path does invoke these hooks, and only the in-session EnterWorktree/ExitWorktree tool path ignores them. On 2.1.214 the CLI exit-remove path does not fire WorktreeRemove — so this is either a regression or an uncovered path. (I can also confirm the ExitWorktree tool path fails, matching #36205.)
  • Other issues in the same hook-dispatch cluster: #39281 (--worktree --tmux), #37611 (WorktreeCreate disables the cleanup prompt), #29716 / #57209 (Claude Desktop), #27276 (docs don't cover these events).
  • Impact: per-worktree cleanup (scoped dev database, virtualenv, ports) can't be automated on removal; teardown has to be run manually before deleting the worktree.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗