Repository navigation
Description
Symptom
In reDeploy (onboarded before #134, plugin now 0.3.0), .claude/scripts/worktree.sh did not exist and never had:
$ git log --all --diff-filter=AD -- .claude/scripts/worktree.sh
(no output)
Nothing deleted it — no mechanism has ever existed to put it there.
Cause
#134 stopped vendoring agents/ commands/ hooks/ scripts/ skills/ into consumer repos, and sync.sh's managed-file table is only four rows (feature-fanout.js, the two .service templates, arm-loop.sh). It never copies scripts/.
But several shipped templates still assume a repo-local .claude/scripts/:
| Template | Line | Assumes |
|---|---|---|
templates/gates.yml |
48 | run: bash .claude/scripts/gate.sh ${{ matrix.gate }} |
templates/action.yml |
57 | run: bash .claude/scripts/gate.sh install |
templates/gates.json |
worktree._note |
"Run via .claude/scripts/worktree.sh setup|teardown" |
So the templates promise a directory the plugin no longer populates.
Why it can't simply be "resolve from the plugin cache"
The CI ones genuinely need a repo-local copy: a GitHub Actions runner does a bare actions/checkout and has no plugin cache at all, and ${CLAUDE_PLUGIN_ROOT} is a Claude-Code-session-only variable that is never set there. gate.sh (plus resolve-roots.sh, which it sources at line 13) must therefore exist in the repo for CI to work.
resolve-roots.sh also documents that a repo-tracked .claude/scripts layout deliberately wins over the plugin cache, because worktree implementers need the worktree as root. So a repo-local copy is by design — there is just nothing that creates or refreshes one post-#134.
Consequences observed
worktree.shabsent, so theworktree.setupbootstrap the agent prompts call (bash ${CLAUDE_PLUGIN_ROOT:-.claude}/scripts/worktree.sh setup) silently skips via its "if present" guard wheneverCLAUDE_PLUGIN_ROOTisn't set. In-worktree gates then fail for missingnode_modules/ Foundry libs rather than for real defects.- Consumers that hand-maintained the directory (reDeploy topped it up via occasional
chore(harness): sync ...commits) drift arbitrarily far: reDeploy's copy was missing ~25 scripts that 0.3.0 ships. sync.shreports the directory asstale-vendor conflictforever, since it can't distinguish "stale relic" from "required for CI".
Possible directions (owner's call)
- Make
gate.sh+resolve-roots.sh(+worktree.sh?) a managed row in MANIFEST sosetup/synccreate and re-stamp them likearm-loop.sh. Smallest change; makes the required-repo-local set explicit and versioned. - Have the CI templates install the plugin/marketplace in a step before calling
gate.sh, so CI needs nothing repo-local. - Teach
sync.shto recognise a known "required repo-local" subset and stop flagging it as stale-vendor.
Workaround applied in reDeploy
Trimmed .claude/scripts/ to the 8 files that are actually required, each refreshed byte-identical from plugin 0.3.0: gate.sh, resolve-roots.sh, worktree.sh, arm-loop.sh, prepare-pr.sh, bot-gh.sh, merge-ready.sh, notify-poll.sh.
Filed from reDeploy per #223. Labelled backlog — not self-assigning planned, per CONTRIBUTING.md.
Activity