Pin Claude marker hooks to launch worktree - #3956
Conversation
worktrunk-bot
left a comment
There was a problem hiding this comment.
The cwd-drift this fixes is real, and for a session that stays where it was launched -C "$CLAUDE_PROJECT_DIR" is the right pin. But it inverts the case the plugin itself creates: EnterWorktree re-roots the session into a new worktree while CLAUDE_PROJECT_DIR deliberately stays at the launch root, so after /wt-switch-create every marker lands on the launch worktree's branch and the worktree the user is watching in wt list never gets one. Detail inline on hooks/hooks.json.
Three follow-ons, inline: the user-facing rule in claude-code.md now describes something other than what the Claude plugin ships; the tradeoff #3921 left open is settled here but recorded nowhere; and the new assertions could be an execution test rather than a substring check, using the WorktreeRemove harness already in this file.
Minor, not inline: the sibling WorktreeCreate hook guards with ${CLAUDE_PROJECT_DIR:-.} while the six new ones use a bare "$CLAUDE_PROJECT_DIR". With || true on the end, an unset variable is -C "" and markers silently stop entirely rather than falling back to cwd. Claude exports the variable for both hook forms so this is unlikely in practice — and the brace form can't be used inline here anyway, since the outer command line is parsed by the user's login shell and fish rejects ${...} (the assertion above these lines pins exactly that). Worth a bash -c wrapper only if you want the fallback.
Pins Claude activity-marker updates and cleanup to
CLAUDE_PROJECT_DIR, so a shellcdcannot retarget them to another repository.Claude markers deliberately remain on the launch worktree after
EnterWorktree, and sessions launched outside a repository have no marker. Codex and Gemini remain cwd-based until their hook harnesses expose a stable session project directory.The hook lifecycle was not exercised inside a live Claude session; tests cover the manifest wiring and cross-shell parsing.
Part of #3921