feat(herdr): install dependencies in a new worktree - #89
Open
fveracoechea wants to merge 2 commits into
Open
fveracoechea wants to merge 2 commits into
fveracoechea wants to merge 2 commits into
Conversation
A Herdr worktree is a fresh checkout with no node_modules. In a project whose Claude hooks run a package bin, such as `bun run jarvis`, every tool call in that worktree reports `Script not found "jarvis"`. The plugin now handles `worktree.created`. It picks the package manager from the lockfile and runs a frozen install, `bun install --frozen-lockfile` or `npm ci`, so the lockfile is never rewritten and the checkout stays removable. Herdr starts the hook and returns from `worktree create` without waiting, and a warm bun install finishes long before an agent's first tool call. The release build skips test files under herdr/, so the hook's test sits beside it. The release test now compares real paths, because the macOS temporary directory is a symlink and it failed locally.
Review found tests that could not fail: dropping `--frozen-lockfile`, a lockfile name, or the bun-over-npm order kept them green. A table test now covers each lockfile and the both-lockfiles case, and a stale lockfile must fail the hook and stay unchanged. The hook runs the install with the Bun that runs it, so PATH no longer decides which Bun installs, and a missing npm reports a clear message instead of a stack trace. WAKE.md no longer claims the first tool call works. The install runs in the background, so it says a hook can still fail until the install ends, and that the Operative brief keeps its own install step as the fallback. It also says that `npm ci` runs dependency lifecycle scripts, which bun blocks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A Herdr worktree is a fresh checkout with no
node_modules.In a consumer such as mystique, each Claude hook runs
bun run jarvis ..., so every tool call in a new worktree fails withScript not found "jarvis".The
operator.wakeplugin now handlesworktree.createdand installs from the lockfile.Start reading at
herdr/worktree.ts.Things that look wrong and are not:
build.tsnow skips*.test.tswhen it copiesherdr/andskills/. The existing assert that the artifact has no.test.file guards it. It fails if the skip is removed.realpath. On macOS the temporary directory is a symlink, and that test failed locally onmainbefore this change.Evidence
herdr worktree create --cwd ~/Code/mystique ..., then the Claude hook command in the new worktree:error: Script not found "jarvis", exit 1, nonode_modules.After: the same steps with this branch's plugin linked. The plugin log shows
Running \bun install --frozen-lockfile`andInstalled dependencies, exit 0.git status` is clean, and the hook command exits 0.herdr/worktree.test.ts, 10 tests:a bun checkout whose dependency ships a bin fails
bun run toolbefore the hook and passes after it.A stale lockfile fails the hook and stays unchanged.
A table covers each lockfile name, plus both lockfiles together.
A failed install, a missing npm, and no lockfile are also covered.
--frozen-lockfile, droppingbun.lockbornpm-shrinkwrap.json, npm before bun, and a swallowed spawn error.bun run qualitypasses, with 594 tests.Verified Herdr behavior (0.9.x): the hook starts about 50 ms before
herdr worktree createreturns, and the CLI does not wait for it.A 150 s hook ran to completion.
A warm bun install in mystique takes 1.4 s.
Not proven: the end-to-end run used a scratch copy of
herdr/withmin_herdr_versionlowered to 0.9.0, because the local Herdr server is 0.9.0. The scripts were the same bytes.Merge Danger
Door: two-way
Revert the commit and relink the plugin.
Blast Radius: machine-wide
After a relink, every worktree that Herdr creates on the machine gets an install, in any project, with no opt-out.
The install runs in the background, so a slow
npm cican still lose the race with an agent's first tool call.When the project runs Operator through
bun run operator, the Operative brief keeps its ownbun install --frozen-lockfilestep as the fallback.Review ran two frozen bun installs at once in one directory five times, and every run passed.
npm ciruns dependency lifecycle scripts, including in worktrees of untrusted branches. Bun blocks them by default.Not in this PR: pnpm and yarn, a lockfile below the worktree root,
worktree.opened, and an opt-out setting.🤖 Generated with Claude Code