Skip to content

feat(source-control): unify native-hook + /worktree-skill worktree creation via one shared helper #399

Description

@kyle-sexton

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:

  1. The WorktreeCreate hook (native --worktree / subagent isolation).
  2. 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)

  • Gate 1: Confirm whether EnterWorktree inside a D:\repos git 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.
  • Gate 2: Confirm whether a hook-relocated subagent-isolation worktree (outside .claude/worktrees/) prompts/blocks under normal (non-bypassPermissions) permissions (docs: out-of-.claude/worktrees paths need approval; anthropics/claude-code #78212). If it blocks, autonomous isolation is incompatible without bypassPermissions — decide accordingly.

Acceptance criteria

  • One shared helper owns path computation + creation + local-file copy.
  • WorktreeCreate hook and /worktree skill both route through it → identical placement.
  • Built against stdin .name; base-ref logic (fresh/head) reimplemented in the helper.
  • Both empirical gates run and documented; ship gated on their outcome.
  • Failure-safe: helper errors surface clearly; a hook failure that would brick all CC worktree creation is guarded/tested.

Part of

Worktree-convention epic: #398

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: highSignificant impact, or blocks an imminent release; staff this cycle.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions