Background/agent isolation: "worktree" creates worktrees without firing the WorktreeCreate hook
Summary
Worktrees created by the harness's background/agent worktree isolation (isolation: "worktree" on the Agent tool, FleetView-spawned background tasks) are created via a direct git worktree add into .claude/worktrees/<slug> and do not fire the WorktreeCreate hook event. This makes the path uninterceptable, breaking jj (Jujutsu) repos where a WorktreeCreate hook is the documented mechanism for converting worktrees into jj workspaces.
This is the same class of defect as #36205 (the EnterWorktree tool not firing WorktreeCreate), but for the background-isolation creation path rather than the in-session tool.
Environment
- Claude Code:
2.1.144 - OS: macOS 26.4.1 (build 25E253)
- VCS: Jujutsu (jj) colocated repo with a git backend
The three worktree-creation paths
There are three ways a worktree gets created, and only two are interceptable:
| Path | Fires WorktreeCreate? | Interceptable? |
|---|---|---|
| Terminal claude --worktree | ✅ Yes | ✅ via WorktreeCreate hook |
| EnterWorktree tool (Desktop / mid-session) | ❌ No (#36205) | ⚠️ only via a PreToolUse:EnterWorktree workaround |
| Background / agent isolation: "worktree" | ❌ No | ❌ No event at all |
The first two have workarounds. The third does not: there is no tool call to match with PreToolUse (creation happens during session bootstrap, before the agent runs), and WorktreeCreate is never emitted.
Steps to reproduce
- In a jj (or any non-git-native) repo, configure a
WorktreeCreatehook that converts the new worktree appropriately (e.g.jj workspace add). - Spawn a background agent / task with
isolation: "worktree"(or trigger a FleetView background task that uses worktree isolation). - Inspect the resulting session's working directory.
Expected behavior
Background-isolation worktree creation fires the WorktreeCreate hook (same payload contract as the terminal --worktree path: name, cwd, and honoring the hook's stdout path contract), so existing tooling can convert/relocate the worktree.
Actual behavior
A plain git worktree add is performed into .claude/worktrees/<slug> with branch claude/<slug>. No hook fires. In a jj repo this yields a git-only worktree where jj commands silently resolve against the main repo's working copy (jj root points outside the worktree) — a data-loss footgun for commits.
Observed: six such .claude/worktrees/<slug> worktrees (branches claude/<slug>), none converted, despite a working WorktreeCreate hook that correctly handles the terminal --worktree path.
Impact
- jj / non-git-native repos cannot reliably use background-agent worktree isolation; VCS operations in the worktree target the wrong working copy.
- The
WorktreeCreatehook is documented as the worktree-lifecycle interception point, but the most common automated path (background agents) bypasses it, making the hook contract effectively unreliable.
Suggested fix
Emit WorktreeCreate for all worktree-creation paths, including background/agent isolation: "worktree", with the same payload and stdout-path contract as the terminal --worktree path. Honoring the hook's returned path would additionally let the relocated/converted worktree be used as the session cwd, mirroring the --worktree behavior. Fixing this would also subsume the EnterWorktree workaround needed for #36205.
Related
- #36205 —
EnterWorktreetool does not fireWorktreeCreate(sibling defect, in-session tool path)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗