feat(install): user-level symlink install — stop copying the engine into projects - #15
Conversation
… symlinks Stop copying the engine into consuming projects. The Workflow tool also resolves user-level ~/.claude/workflows/, so the pipeline commands now auto-create (and self-repair) symlinks there pointing at the plugin's engine; plugin updates propagate through the link and version drift becomes impossible. Where symlinks are unavailable the preflight falls back to a user-level copy that re-syncs on engine-version drift. - rewrite /setup as a doctor/repair command: diagnose links (ok/stale/ dangling/copy/missing), recreate them, ESM-validate the plugin engine, and interactively remove legacy per-project copies (which shadow the user-level engine) - give all 7 pipeline commands one byte-identical self-repairing preflight; drop the drift AskUserQuestion flow; only a stale legacy project copy still stops a command - stamp engineVersion into pipeline-state.json and warn (non-blocking) when a resume runs a newer engine than the one that wrote the state - update banner scriptPath, plugin description, QUICKSTART (upgrade note, troubleshooting), both READMEs, and the engine reference docs - add tests/command-preflight.test.mjs (preflight byte-identity, user- level markers, no project-path refs outside legacy detection) and extend config-and-state tests for the engineVersion stamp
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (8 files — incremental)
Resolved: The SUGGESTION about Previous Review Summaries (2 snapshots, latest commit 12619ca)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 12619ca)Status: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (11 files — incremental)
Previous issue resolved: The WARNING about bare Fix these issues in Kilo Cloud Previous review (commit ee93964)Status: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (23 files)
Reviewed by deepseek-v4-pro · Input: 28.7K · Output: 5.6K · Cached: 180.5K Review guidance: REVIEW.md from base branch |
…S detection and three-tier symlink/copy fallback The setup command and all 7 pipeline-command preflights now support Windows alongside Linux/macOS. Previously the repair block used a bare 'ln -sfn' with the cp fallback described only in prose — an agent executing the block literally failed on Windows without symlink privilege (the exact issue raised in the PR #15 review), and there was no OS or symlink-capability detection on the install surface. The auto-repair is now a three-tier cascade applied byte-identically across all seven pipeline commands (the byte-identity test stays green): 1. ln -sfn — Linux/macOS + Git-Bash on Windows with Developer Mode 2. powershell New-Item -ItemType SymbolicLink — native Windows attempt, tried only where ln fails but symlink privilege exists; $ErrorActionPreference='Stop' makes any failure fall through to the copy tier 3. cp — universal fallback (Windows without Developer Mode), auto-resyncs on engine-version drift setup.md becomes a cross-platform doctor: it reports the OS (uname -s) and symlink capability up front, runs the same three-tier repair, re-checks which mode took effect, and gives explicit Windows Developer-Mode guidance. - preflight adds OS + symlink-capability probes; all 7 commands gain Bash(uname:*) and Bash(powershell:*) permissions - setup.md: bare ln block replaced with the inline three-tier block (closes the review thread on setup.md:30) + OS/symlink diagnostics + Windows guidance - command-preflight.test.mjs: new markers (uname/powershell/New-Item), two new required permissions, and setup-doctor assertions that the powershell + cp fallback tiers are inline (regression guard for the review fix); the project-path filter now also treats $USERPROFILE/.claude/workflows as user-level - QUICKSTART troubleshooting + plugin README note the three-tier repair Validated on a Windows Git Bash host without Developer Mode: both the ln and powershell tiers are rejected and the cp fallback lands cleanly (exit 0). 189 tests green across 12 files; validate:versions OK. (The pre-existing build-drift.test.mjs failure in schemas.mjs is unrelated and reproduces on clean main.)
…ability probe The symlink-capability preflight added in 12619ca runs 'd=$(mktemp -d); ln -s "$d" "$d/t" ...; rm -rf "$d"', but mktemp and rm were not in the 7 pipeline commands' allowed-tools — only ln was (already granted). If Claude Code enforces allowed-tools against inline !-preflight executions, the probe would fail on every invocation. setup.md is unaffected (unrestricted Bash). - all 7 pipeline commands: append Bash(mktemp:*) and Bash(rm:*) - command-preflight.test.mjs: add both to the required-permission set (regression guard) Addresses the review thread on design-feature.md:4. 189 tests green.
What
Replaces the per-project engine install with a user-level symlink install. The pipeline commands now auto-create (and self-repair) symlinks in
~/.claude/workflows/pointing at the plugin's${CLAUDE_PLUGIN_ROOT}/workflows/…files — nothing is copied into consuming projects anymore, plugin updates propagate instantly through the link, and engine-version drift becomes structurally impossible. Where symlinks are unavailable (e.g. Windows without developer mode) the same preflight falls back to a user-level copy that auto-re-syncs on version drift.Why
The old
/setupflow copied the 340KB generated engine bundle (+2 docs) into every project's.claude/workflows/, required a manual re-run after every plugin update, and polluted consumer repos with derived files. The Workflow tool also resolves user-level~/.claude/workflows/(seedocs/dynamic-workflows.md), which makes the per-project copy unnecessary.Changes
commands/setup.md→ doctor/repair command: diagnoses each managed target (SYMLINK-OK / STALE / DANGLING / PLAIN-COPY / MISSING), recreates the links (ln -sfn,cpfallback), ESM-validates the plugin engine (no delete-on-failure anymore), reports versions, and interactively removes legacy pre-1.5.0 project copies — which shadow the user-level engine.ln||cprepair; the old STOP + AskUserQuestion drift flow is deleted;pipeline-status's soft variant folded in). The only remaining STOP is a legacy project copy whoseengine-version:differs from the plugin's.flushPipelineStatestampsengineVersionintopipeline-state.json; the resume path logs a non-blocking skew warning and setsresult._resumeEngineSkewwhen a newer engine hydrates older state. Pre-1.5.0 state files (no field) stay silently resumable.scriptPath, plugin.json description.tests/command-preflight.test.mjs— asserts preflight byte-identity across all 7 commands, user-level/repair markers, no project-path references outside legacy-detection lines, required Bash permissions, and setup-is-a-doctor invariants.config-and-stateextended for theengineVersionstamp (and its backward-compat absence).190 tests green;
validate:build,validate:versions,validate:agents, and the ESM check all pass.Reviewer notes
~/.claude/workflows/by name and follows symlinks. This needs a one-time manual verification in a live session (3-step spike: user-level plain file → symlink → project-vs-user precedence). If symlinks turn out not to be followed, the copy fallback already wired into the preflight becomes the primary path (drop thereadlink/target lines) — still zero project files.npm run release -- 1.5.0(single bump site, rebuilds + re-pins the marketplace) after the spike passes — the dist and marketplace pin are never hand-edited.