Summary
Unify Claude Code worktree creation so that both entry paths — the native WorktreeCreate hook (fires for claude --worktree and subagent isolation:"worktree") and the /worktree skill (EnterWorktree) — place worktrees in the same location via one shared helper. Today they diverge: the hook can relocate; the skill's EnterWorktree-in-a-git-repo lands in .claude/worktrees/ and the hook does not fire for it.
Component
plugins/source-control/skills/worktree/** + a shared helper script; consumed by the setup skill.
Background (verified this session)
- The
WorktreeCreate hook prints the worktree dir to stdout and replaces git's default placement — but per the EnterWorktree tool contract, inside a git repo EnterWorktree creates under .claude/worktrees/ and does NOT consult the hook (it only delegates to the hook outside a git repo). So a hook alone cannot standardize the interactive /worktree create path.
- The hook must create the worktree itself (not merely echo a path) and re-implement
.worktreeinclude copying (bypassed under a hook). Real stdin field is .name (docs say worktree_name — anthropics/claude-code #77566).
Design
A single shared helper (in the plugin) that: computes <root>/<owner>-<repo>-<slug> (root from the setup skill), runs git worktree add with the correct base, sanitizes the branch slug, handles detached HEAD, and copies .worktreeinclude-matched local files. Invoked by:
- The
WorktreeCreate hook (native --worktree / subagent isolation).
- The
/worktree skill — patched to call the shared helper (git worktree add to the external root) instead of relying on EnterWorktree's in-repo default.
Result: identical placement regardless of entry path.
Empirical gates (must pass before shipping the hook)
Acceptance criteria
Part of
Worktree-convention epic: #398
Summary
Unify Claude Code worktree creation so that both entry paths — the native
WorktreeCreatehook (fires forclaude --worktreeand subagentisolation:"worktree") and the/worktreeskill (EnterWorktree) — place worktrees in the same location via one shared helper. Today they diverge: the hook can relocate; the skill'sEnterWorktree-in-a-git-repo lands in.claude/worktrees/and the hook does not fire for it.Component
plugins/source-control/skills/worktree/**+ a shared helper script; consumed by the setup skill.Background (verified this session)
WorktreeCreatehook prints the worktree dir to stdout and replaces git's default placement — but per theEnterWorktreetool contract, inside a git repoEnterWorktreecreates under.claude/worktrees/and does NOT consult the hook (it only delegates to the hook outside a git repo). So a hook alone cannot standardize the interactive/worktree createpath..worktreeincludecopying (bypassed under a hook). Real stdin field is.name(docs sayworktree_name— anthropics/claude-code #77566).Design
A single shared helper (in the plugin) that: computes
<root>/<owner>-<repo>-<slug>(root from the setup skill), runsgit worktree addwith the correct base, sanitizes the branch slug, handles detached HEAD, and copies.worktreeinclude-matched local files. Invoked by:WorktreeCreatehook (native--worktree/ subagent isolation)./worktreeskill — patched to call the shared helper (git worktree addto the external root) instead of relying onEnterWorktree's in-repo default.Result: identical placement regardless of entry path.
Empirical gates (must pass before shipping the hook)
EnterWorktreeinside aD:\reposgit repo fires the hook or goes to.claude/worktrees/; simultaneously dump raw hook stdin (jq .) to capture the real field set (.name, base ref, cwd) for the tested CC version. Pin the contract to that version..claude/worktrees/) prompts/blocks under normal (non-bypassPermissions) permissions (docs: out-of-.claude/worktreespaths need approval; anthropics/claude-code #78212). If it blocks, autonomous isolation is incompatible withoutbypassPermissions— decide accordingly.Acceptance criteria
WorktreeCreatehook and/worktreeskill both route through it → identical placement..name; base-ref logic (fresh/head) reimplemented in the helper.Part of
Worktree-convention epic: #398