[BUG] Plugin `WorktreeCreate` hook still ignored for `claude --worktree` on 2.1.296 (#46664 closed as stale, never fixed)

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

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

This is the same bug as [[BUG] Plugin-registered WorktreeCreate hooks in hooks/hooks.json are never dispatched — settings.json hooks for the same event fire normally (2.1.101)#46664](https://github.com/anthropics/claude-code/issues/46664) (reported on 2.1.101, confirmed on 2.1.145, closed as stale by the bot and now locked).

A WorktreeCreate hook defined in a plugin's hooks/hooks.json is still never invoked for claude --worktree <name>. Claude Code silently falls back to its default git worktree add (.claude/worktrees/<name>). The original report (#46664) covers this in detail; this issue adds what has changed since:

  • Still reproduces on 2.1.296, roughly 190 releases after #46664.
  • It's specific to startup --worktree. The same plugin hook does fire for a subagent with isolation: worktree:

| Trigger | Hook defined in | WorktreeCreate fired? | Worktree used |
|---|---|---|---|
| claude --worktree probe | plugin | No | default .claude/worktrees/probe |
| claude --worktree probe | settings.json | Yes | hook's directory |
| subagent with isolation: worktree | plugin | Yes | hook's directory |

In the first row, the same plugin's SessionStart hook fires in the same session, so the plugin is loaded. Plugin WorktreeRemove is not affected either: with WorktreeCreate in settings.json and WorktreeRemove only in the plugin, the plugin's WorktreeRemove runs when an interactive --worktree session exits.

A likely cause (not confirmed): --worktree creates the worktree during startup, before plugin hooks are loaded, while subagent isolation runs after they're registered.

What Should Happen?

Per the hooks reference, WorktreeCreate fires "when a worktree is being created via --worktree, isolation: "worktree", or for a background session" and "replaces default git behavior." Per the plugin docs, plugin hooks "merge with your user and project hooks", with no events excluded. So a plugin's WorktreeCreate hook should run for claude --worktree, as it already does for subagents.

Error Messages/Logs

Steps to Reproduce

Save as repro.sh and run it from an empty directory. It uses a throwaway local marketplace. Make sure no WorktreeCreate hook is configured in your settings files.

#!/bin/bash
set -euo pipefail
ROOT=$(pwd)
LOG="$ROOT/fired.log"

# 1. Probe plugin: WorktreeCreate logs and creates a directory, SessionStart just logs.
mkdir -p mkt/.claude-plugin mkt/probe/.claude-plugin mkt/probe/hooks repo
cat > mkt/.claude-plugin/marketplace.json <<'EOF'
{"name":"probe-mkt","owner":{"name":"probe"},"plugins":[{"name":"probe","source":"./probe"}]}
EOF
cat > mkt/probe/.claude-plugin/plugin.json <<'EOF'
{"name":"probe","version":"0.0.1","description":"WorktreeCreate probe"}
EOF
cat > mkt/probe/hooks/hooks.json <<'EOF'
{"hooks":{
  "WorktreeCreate":[{"hooks":[{"type":"command","command":"${CLAUDE_PLUGIN_ROOT}/hooks/create","timeout":30}]}],
  "SessionStart":[{"hooks":[{"type":"command","command":"${CLAUDE_PLUGIN_ROOT}/hooks/session"}]}]}}
EOF
cat > mkt/probe/hooks/create <<EOF
#!/bin/bash
IN=\$(cat); echo "WorktreeCreate \$IN" >> "$LOG"
D="$ROOT/wts/\$(echo "\$IN" | jq -r .name)"; mkdir -p "\$D"; echo "\$D"
EOF
cat > mkt/probe/hooks/session <<EOF
#!/bin/bash
echo "SessionStart \$(cat)" >> "$LOG"
EOF
chmod +x mkt/probe/hooks/create mkt/probe/hooks/session

claude plugin marketplace add "$ROOT/mkt"
claude plugin install probe@probe-mkt

# 2. A git repo to run in.
git -C repo init -q && git -C repo -c user.email=a@b -c user.name=a commit -q --allow-empty -m init
cd repo

# 3. Startup --worktree: plugin WorktreeCreate is NOT invoked.
: > "$LOG"
claude --worktree probe -p "Reply with only the output of pwd." --allowedTools Bash < /dev/null
echo "== --worktree"; cut -c1-80 "$LOG"     # only SessionStart
git worktree list                          # shows .claude/worktrees/probe (default git worktree)

# 4. Subagent isolation: plugin WorktreeCreate IS invoked.
mkdir -p .claude/agents
cat > .claude/agents/wt-probe.md <<'EOF'
---
name: wt-probe
description: Reports its working directory. Use when asked to run the worktree probe.
isolation: worktree
tools: Bash
---
Run `pwd` with the Bash tool and reply with only the output.
EOF
: > "$LOG"
claude -p "Use the wt-probe agent to run the worktree probe and report the directory." --allowedTools "Agent,Bash" < /dev/null
echo "== isolation: worktree"; cut -c1-80 "$LOG"   # SessionStart + WorktreeCreate
ls "$ROOT/wts"                                     # hook-created directory

Observed output (abridged):

== --worktree
SessionStart {"session_id":"…","cwd":"…/repo/.claude/worktrees/probe",…
…/repo/.claude/worktrees/probe  fab6e8c [worktree-probe]

== isolation: worktree
SessionStart {"session_id":"…",…
WorktreeCreate {"session_id":"…","hook_event_name":"WorktreeCreate","name":"agent-…"}
agent-…

Claude Model

Opus

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.296

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗