Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .agents/skills/worktrees-pnpm/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,15 @@ printf '{"hook_event_name":"WorktreeCreate","cwd":"%s","worktree_id":"probe"}' "
| .agents/skills/worktrees-pnpm/scripts/worktree-create.sh
# expect: <repo>/worktrees/probe on stdout, git chatter on stderr, exit 0

# The id field is not stable across callers, so .worktreeId and .name are read
# too — `.name` is what a background agent's payload actually carries.
printf '{"hook_event_name":"WorktreeCreate","cwd":"%s","name":"probe-name"}' "$PWD" \
| .agents/skills/worktrees-pnpm/scripts/worktree-create.sh
# expect: <repo>/worktrees/probe-name

printf '{"hook_event_name":"WorktreeRemove","worktree_path":"%s"}' "$PWD/worktrees/probe" \
| .agents/skills/worktrees-pnpm/scripts/worktree-remove.sh
# ...and the same for worktrees/probe-name
```

**2. Add the ignores** described in the next section. Skipping this is the single most common way
Expand Down
16 changes: 13 additions & 3 deletions .agents/skills/worktrees-pnpm/scripts/worktree-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,26 @@
# Layout: /path/to/<repo> -> /path/to/<repo>/worktrees/<worktree_id>
#
# Contract (docs: code.claude.com/docs/en/hooks):
# stdin - JSON with .worktree_id (and .base_path, .cwd, .session_id, ...)
# stdin - JSON identifying the worktree, plus .base_path, .cwd, .session_id, ...
# The id field is NOT stable across callers: a background agent's
# payload carries `.name` (e.g. "agent-a5e1de46e730bdfd7") and no
# `.worktree_id` at all, so all three spellings are read
# (.worktree_id, .worktreeId, .name). Accepting only one of them
# fails worktree creation outright with a message that reads like the
# harness sent nothing. `.name` is the weakest of the three — it is
# justified by one captured payload, not a guaranteed contract — so a
# caller that sends an unrelated `.name` while genuinely lacking both
# id fields lands on the validation below and fails loudly, which is
# the intended floor rather than an accident.
# stdout - the absolute path of the created worktree, plain text, REQUIRED
# exit - non-zero, or zero with empty stdout, fails worktree creation
# This hook replaces the default logic entirely, so it must run `git worktree add`.
set -euo pipefail

payload=$(cat)
worktree_id=$(printf '%s' "$payload" | jq -r '.worktree_id // empty')
worktree_id=$(printf '%s' "$payload" | jq -r '.worktree_id // .worktreeId // .name // empty')
Comment thread
thecodedrift marked this conversation as resolved.
if [ -z "$worktree_id" ]; then
echo "WorktreeCreate: no .worktree_id on stdin" >&2
echo "WorktreeCreate: stdin carried none of .worktree_id/.worktreeId/.name" >&2
exit 1
fi

Expand Down
Loading