[DOCS] WorktreeCreate/WorktreeRemove hooks: ownership rule, clean-exit removal, agent_id example, bypassed defaults, cwd per caller

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

Documentation Type

Unclear/confusing documentation

Documentation Location

https://code.claude.com/docs/en/hooks, https://code.claude.com/docs/en/worktrees, https://code.claude.com/docs/en/sub-agents

Section/Topic

WorktreeCreate and WorktreeRemove hooks; SubagentStart and SubagentStop input

Current Documentation

hooks.md, WorktreeRemove triggers:

* you exit a --worktree session and choose to remove it

hooks.md, WorktreeRemove:

For git-based worktrees, Claude Code handles cleanup automatically with git worktree remove. If you configured a WorktreeCreate hook, pair it with a WorktreeRemove hook to control cleanup of the worktrees it creates

hooks.md, SubagentStart and SubagentStop input examples:

"agent_id": "agent-abc123", "agent_id": "def456",

hooks.md, common input fields:

cwd | Current working directory when the hook is invoked

worktrees.md, Choose the base branch:

New worktrees branch from the repository's default branch, so most sessions don't need this setting.

What's Wrong or Missing?

Investigated and reproduced with an empty CLAUDE_CONFIG_DIR (no user hooks, plugins or CLAUDE.md) by Claude Code 2.1.288 using Opus 5.5.

All observed on 2.1.288 with logging hooks registered through --settings. Details marked "source" come from a reading of the 2.1.288 bundle, not from a run.

  1. The WorktreeRemove trigger list gives "you exit a --worktree session and choose to remove it", but a clean exit also calls WorktreeRemove, without a prompt. The docs also never say in one place that the hook decides whether removal is safe: that follows from several sections, and from a non-zero exit keeping the worktree.
  1. The ownership rule is only implied. WorktreeRemove fires only for worktrees a WorktreeCreate hook created; a worktree Claude Code creates with git is removed by git and never runs the hook, even when a WorktreeRemove hook is configured. A maintainer confirmed this in #74708 and wrote that the docs should say so plainly. No page states it.
  1. The SubagentStart example agent_id is wrong. Both events receive the bare id, for example aaa40a63f12bc5cae. The agent- prefix appears only in the subagent transcript filename (agent-<id>.jsonl) and in the name passed to WorktreeCreate for an isolated subagent (agent-<id>). A hook matching a subagent to its worktree or transcript needs to know which form arrives.
  1. Worktree defaults are described without saying a WorktreeCreate hook bypasses them. worktrees.md says .worktreeinclude is not processed with a hook, but the base branch and worktree.baseRef (Choose the base branch), the pull request fetch for --worktree '#N' (Branch from a pull request), and the isolation row in sub-agents.md describe git-path behaviour with no qualifier. With a hook, the hook receives only name (pr-<N> for a pull request), and Claude Code creates no worktree-<name> branch, resolves no base ref, and fetches nothing.
  1. WorktreeCreate cwd depends on the caller, and isn't the obvious directory for --worktree:

| Caller | cwd |
| ------------------------------------------- | ------------------------------- |
| --worktree from the main checkout | the launch directory |
| --worktree from a subdirectory | the launch directory |
| --worktree from a linked worktree | the main checkout |
| --worktree from a worktree of a bare repo | the bare repository directory |
| subagent with isolation: worktree | the session's current directory |

A hook that resolves paths from cwd, or runs git there expecting a work tree, breaks in the last two --worktree cases.

Suggested Improvement

  1. In the WorktreeRemove trigger list, add that a clean --worktree session exit calls WorktreeRemove without a prompt, and say that the hook decides whether removal is safe, keeping the worktree by exiting non-zero.
  2. Add near the top of the WorktreeRemove section: "WorktreeRemove runs only for worktrees a WorktreeCreate hook created. Worktrees Claude Code creates with git are removed by git and never run the hook."
  3. Change the SubagentStart example to a bare id such as "agent_id": "a1b2c3d4e5f6a7b8c", use the same shape in the SubagentStop example, and note where the agent- prefix appears.
  4. In worktrees.md (Choose the base branch, Branch from a pull request) and the sub-agents.md isolation row, note that with a WorktreeCreate hook these don't apply and the hook receives only name.
  5. In the WorktreeCreate input section, document cwd per caller, as in the table above.

Impact

Medium - Makes feature difficult to understand

Additional Context

Related: #99270 (WorktreeRemove never fires for hook-created subagent worktrees, contrary to the trigger list), #74708 (ownership rule), #92425 (WorktreeRemove contract for adopted worktrees).

View original on GitHub ↗