Context
Per @tobiu's session-end direction (2026-04-26): worktrees created by Claude Code (.claude/worktrees/<name>/) start without node_modules and without prerequisite build artifacts (e.g., dist/parse5.mjs). ai/scripts/bootstrapWorktree.mjs already handles the gitignored ai/mcp/server/*/config.mjs copies and the optional .neo-ai-data/ symlink, but stops short of making the worktree truly "test-ready" or "SDK-consuming-script-ready" out of the box.
The Problem
When picking up a ticket in a fresh worktree that requires running unit tests or invoking SDK-consuming scripts, agents currently hit a multi-step manual bootstrap:
node ai/scripts/bootstrapWorktree.mjs --link-data — configs + data symlink
npm install — node_modules
npm run bundle-parse5 — build prerequisite for unit-test config (not always obvious it's needed)
- (for frontend work)
npm run build-all — bundled dist artifacts
Steps 2-4 are not codified anywhere agents can discover them. Empirically observed during #10339 implementation: ticket-intake passed, branch-before-code created, then test runner failed with Cannot find module '.../dist/parse5.mjs'. Each unfamiliar agent re-derives the chain.
The Architectural Reality
bootstrapWorktree.mjs is the canonical entry point per AGENTS_STARTUP.md §5 Worktree Bootstrap (Claude Code). Adding npm-install + optional build steps there means:
- Agents already know to invoke it (it's in the boot mandate).
- The script's existing flag-based design (
--link-data, --force) accommodates new opt-in flags cleanly.
- No new entry points to document; no new mental model.
The trade-off is install-time cost: npm install takes ~17s on this machine (808 packages installed against an existing local cache). For frontend workflows, npm run build-all is heavier (~minutes). Hence opt-in flags rather than always-on.
The Fix
Extend ai/scripts/bootstrapWorktree.mjs with two new opt-in flags:
--install — runs npm install if node_modules/ does not already exist in the worktree. Idempotent: skip when present. Empirical anchor: ~17s for the install path observed in this session.
--build-all — runs npm run build-all (or npm run bundle-parse5 as a lighter subset) for frontend-affecting tickets. Implies --install. Idempotent: skip if dist/parse5.mjs already exists AND the worktree is up-to-date with origin/dev (timestamp check).
Recommended composition: agents pick up backend/MCP tickets with --install; agents pick up frontend tickets with --build-all. Update AGENTS_STARTUP.md §5 to document the per-task-class invocation guidance.
Also: surface the bundle-parse5 requirement explicitly. Currently it's a hidden test-runner prerequisite — codifying it under --install (always run after install) closes that gap.
Acceptance Criteria
Out of Scope
- Replacing the symlink approach for
node_modules. Several harnesses (and several agents in this very session) considered symlinking node_modules from main checkout. The trade-off (canonical-path issues with some packages, git-worktree assumptions) doesn't justify it for MVP; full local install is more robust.
- Build-flag matrix beyond
--install / --build-all. Granular flags like --build-themes, --build-threads are deferred unless empirical need surfaces.
- Auto-detection of "do I need build-all" based on ticket scope. Heuristic-based auto-bootstrap is a separate ergonomic concern; explicit flags are sufficient for the MVP.
- Cross-harness applicability. This ticket scope is Claude Code worktrees specifically (per
AGENTS_STARTUP.md §5). Antigravity / Gemini CLI use shared-checkout patterns and don't need this script.
Avoided Traps
- Always-on install. Rejected. Many tickets (docs-only, like PR #10348) don't need node_modules. Forcing an install on every bootstrap is friction without payoff.
- Single mega-flag like
--full. Rejected. Naming explicit capabilities (--install, --build-all) lets agents pick the minimum-viable bootstrap for the task class.
- Symlink node_modules from main checkout. Rejected. Explicitly considered this session and denied at the harness security layer; even if permitted, canonical-path resolver semantics introduce risk for some packages.
- Coupling with
--link-data. Rejected. --link-data is data-substrate concern (Memory Core SQLite); --install is dependency-substrate concern. Independent flags compose; coupling creates implicit-skip surprise.
Related
ai/scripts/bootstrapWorktree.mjs — script being extended.
AGENTS_STARTUP.md §5 — doc to update.
- #10339 — empirical-anchor ticket where this gap surfaced (PR #10350 implementation hit the missing-
node_modules blocker).
- #10095 — original worktree-substrate ticket establishing the bootstrap pattern.
- #10224 —
.neo-ai-data symlink unification (companion --link-data flag established here).
Origin Session ID: 48197e2e-3e95-47eb-9eb8-bbb032948845
Retrieval Hint: query_raw_memories(query='bootstrapWorktree npm install build-all worktree dependencies dist parse5 node_modules')
Context
Per @tobiu's session-end direction (2026-04-26): worktrees created by Claude Code (
.claude/worktrees/<name>/) start withoutnode_modulesand without prerequisite build artifacts (e.g.,dist/parse5.mjs).ai/scripts/bootstrapWorktree.mjsalready handles the gitignoredai/mcp/server/*/config.mjscopies and the optional.neo-ai-data/symlink, but stops short of making the worktree truly "test-ready" or "SDK-consuming-script-ready" out of the box.The Problem
When picking up a ticket in a fresh worktree that requires running unit tests or invoking SDK-consuming scripts, agents currently hit a multi-step manual bootstrap:
node ai/scripts/bootstrapWorktree.mjs --link-data— configs + data symlinknpm install— node_modulesnpm run bundle-parse5— build prerequisite for unit-test config (not always obvious it's needed)npm run build-all— bundled dist artifactsSteps 2-4 are not codified anywhere agents can discover them. Empirically observed during #10339 implementation: ticket-intake passed, branch-before-code created, then test runner failed with
Cannot find module '.../dist/parse5.mjs'. Each unfamiliar agent re-derives the chain.The Architectural Reality
bootstrapWorktree.mjsis the canonical entry point perAGENTS_STARTUP.md §5 Worktree Bootstrap (Claude Code). Adding npm-install + optional build steps there means:--link-data,--force) accommodates new opt-in flags cleanly.The trade-off is install-time cost:
npm installtakes ~17s on this machine (808 packages installed against an existing local cache). For frontend workflows,npm run build-allis heavier (~minutes). Hence opt-in flags rather than always-on.The Fix
Extend
ai/scripts/bootstrapWorktree.mjswith two new opt-in flags:--install— runsnpm installifnode_modules/does not already exist in the worktree. Idempotent: skip when present. Empirical anchor: ~17s for the install path observed in this session.--build-all— runsnpm run build-all(ornpm run bundle-parse5as a lighter subset) for frontend-affecting tickets. Implies--install. Idempotent: skip ifdist/parse5.mjsalready exists AND the worktree is up-to-date with origin/dev (timestamp check).Recommended composition: agents pick up backend/MCP tickets with
--install; agents pick up frontend tickets with--build-all. UpdateAGENTS_STARTUP.md §5to document the per-task-class invocation guidance.Also: surface the
bundle-parse5requirement explicitly. Currently it's a hidden test-runner prerequisite — codifying it under--install(always run after install) closes that gap.Acceptance Criteria
bootstrapWorktree.mjsaccepts--installflag; idempotently runsnpm installwhennode_modules/is absent in the worktree.bootstrapWorktree.mjsaccepts--build-allflag; implies--install; runsnpm run build-all.copied: ...style).bundle-parse5is run automatically as part of--install(or surfaced as a separate--bundle-test-prereqsflag — design decision deferred to implementation).AGENTS_STARTUP.md §5 Worktree Bootstrap (Claude Code)updated with per-task-class invocation guidance (which flag to use for backend vs frontend tickets).--install(this session),--build-allcost measured at implementation time.--link-dataflow).Out of Scope
node_modules. Several harnesses (and several agents in this very session) considered symlinkingnode_modulesfrom main checkout. The trade-off (canonical-path issues with some packages, git-worktree assumptions) doesn't justify it for MVP; full local install is more robust.--install/--build-all. Granular flags like--build-themes,--build-threadsare deferred unless empirical need surfaces.AGENTS_STARTUP.md §5). Antigravity / Gemini CLI use shared-checkout patterns and don't need this script.Avoided Traps
--full. Rejected. Naming explicit capabilities (--install,--build-all) lets agents pick the minimum-viable bootstrap for the task class.--link-data. Rejected.--link-datais data-substrate concern (Memory Core SQLite);--installis dependency-substrate concern. Independent flags compose; coupling creates implicit-skip surprise.Related
ai/scripts/bootstrapWorktree.mjs— script being extended.AGENTS_STARTUP.md §5— doc to update.node_modulesblocker)..neo-ai-datasymlink unification (companion--link-dataflag established here).Origin Session ID:
48197e2e-3e95-47eb-9eb8-bbb032948845Retrieval Hint:
query_raw_memories(query='bootstrapWorktree npm install build-all worktree dependencies dist parse5 node_modules')