Worktree
AI dev infrastructure framework for Claude Code. /dotclaude:bootstrap authors CLAUDE.md + docs/ + .claude/ tuned to your project. Per-domain: design (showpiece), coding, planning, testing, data, ai-workflow.
npx -y skills add vindm/dotclaude --skill worktreeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Set up worktree-per-feature discipline for a project where several AI sessions (or humans + agents) work concurrently and collide in one checkout. Writes a thin `worktree:` config block that the plugin's CONSUMED main-checkout hook reads (no rendered per-project hook copy), plus a project-specific worktree lifecycle skill — calibrated by interview (which repo, what's exempt, how a fresh worktree gets configured) and PROVEN by a live smoke worktree before handoff. Invoke /dotclaude:worktree when parallel sessions are real or planned.
SKILL.md
11.1 KB, as published. Nobody here has run it
/dotclaude:worktree — parallel-session isolation kit
You are setting up worktree-per-feature discipline: every substantive edit to
the policed repo happens in a dedicated git worktree, enforced by a blocking
PreToolUse hook. Read ../../principles/worktree-discipline.md FIRST — it
carries the doctrine and the five hard-won lessons this flow encodes; this
file is the procedure.
The hook is CONSUMED, not rendered. The plugin ships one debugged
check-main-checkout-edit.sh (in hooks/scripts/, wired always-on) that reads
a worktree: block from the project's dotclaude.yml and NO-OPs when there is
none. So this flow does NOT copy a hook into the project — it writes the config
the consumed hook reads. No per-project hook copy, no drift, and a project
tunes its policing in one data file.
The deliverable is not files — it is a proven install: the worktree:
config the consumed hook reads correctly, a smoke worktree that built the
project for real, and an explicit restart + live-fire handoff.
Phase 1 — Read the project's concurrency shape
Before any question:
-
Repo topology — is the project root the repo, or does the policed repo sit below it?
git rev-parse --show-toplevel 2>/dev/null for d in */; do git -C "$d" rev-parse --show-toplevel 2>/dev/null; done git worktree list 2>/dev/nullMultiple sibling repos → ask which one(s) carry the collision risk (usually the one being actively developed, not read-only references/snapshots).
-
Parallel-session evidence — lock files (
.session_lock,*.lockat repo root), CLAUDE.md sections about session coordination, git history mentions of collisions/clobbered work, scheduled/background agents. This calibrates urgency and whether a lease protocol already exists to narrow. -
Git-ignored per-machine files (lesson 2 — the fresh-worktree breakers):
git -C <repo> status --ignored --porcelain | grep '^!!'Filter to files/dirs the build actually needs:
.env*,config/*pointers,node_modules, credential stores. For each, note the likely recipe: copy a committed*.exampletemplate / symlink from main / regenerate / skip. -
Markdown-as-code signal (lesson 1): does the repo carry markdown the system executes —
policies/,workflows/, prompt libraries, agent instructions,.claude/kits? If yes, those paths must NOT be exempt. -
Verify command — how the project proves itself (from
package.jsonscripts, Makefile, CI config, README): the build/test/render command the smoke run (Phase 5) will execute, and the close-protocol gates.
Phase 2 — Interview
Open interview.md (same directory). 4-5 questions, adaptive — skip what
Phase 1 answered. Non-skippable even when scan feels conclusive: W2 (exempt
list / markdown-as-code) — it is a judgment call only the user can make.
Phase 3 — Read the principle
../../principles/worktree-discipline.md — in particular the
universal/project-specific split (what the worktree: config carries vs what
you author) and the five lessons (each maps to a concrete step below).
Phase 4 — Author the config + the lifecycle skill
Config (write the worktree: block to dotclaude.yml)
The consumed hook reads these keys; you do NOT render or wire a hook. Write (or
merge) a worktree: block into the project root's dotclaude.yml:
worktree:
policedRepo: <repo path relative to the project root; "." when root IS the repo>
namePrefix: <repo>-wt- # unless the user prefers otherwise
exempt: # main-checkout paths that stay freely editable
- "docs/*"
- "README.md"
- "LICENSE*"
setup: # fresh-worktree recipe, shown in the block message
- "cp config/instance.example.yaml <wt>/config/instance.yaml"
skillPath: .claude/skills/worktree/SKILL.md
exempt— the interviewed list, matched against the repo-relative path (*spans directory separators). NEVER include*.mdunless the user explicitly confirmed no markdown is executed (markdown-as-code, lesson 1).setup— the per-machine-files recipe (lesson 2), one line each;<wt>stands for the worktree dir in the block message.- The stray-worktree guard (lesson 5) and the escape hatch are built into the consumed hook — no per-project authoring.
- Merge into an existing
dotclaude.yml(from another elicitation) — never clobber theartifacts:/fileSize:keys.
Skill (in .claude-staging/skills/worktree/SKILL.md)
The project's lifecycle skill — author it (this one is project-specific by nature). Sections, each filled with THIS project's real commands:
- Create + configure:
git -C <repo> worktree add ../<prefix><slug> -b feat/<slug>+ the setup recipe (one line per per-machine file, real paths). Then (lesson 5) author a capture + assert step: pull the worktree's ABSOLUTE path fromgit -C <repo> worktree list --porcelaininto a variable, assert it (test -d "$WT/<build-marker>"), and tell the agent to use that literal path for every later write — never recompose../<prefix><slug>by eye. Include the path-discipline note:../resolves against the-C <repo>dir (not the shell cwd), write tools need an absolute path, and the harness resets cwd between tool calls. - Verify: the project's verify command + expected output.
- Close: the project's gates → commit (with any project-specific
pre-commit review the repo's conventions demand) → merge etiquette →
git worktree remove→ branch cleanup. Include the derived-artifacts "drop the noise" step with the EXACT paths Phase 5's smoke run recorded. - Escape hatch: the
allow-main-editsconvention, ask-first. - Shared resources lease (only if Phase 1/interview surfaced out-of-repo shared state): the narrowed lock protocol from the principle doc.
No wiring step
The consumed hook is wired once in the plugin's hooks/hooks.json (always-on,
NO-OP without a worktree: block). Do NOT add a local hook to the project's
.claude/settings.json — a project-level hook copy is exactly the drift this
model removes. The worktree: block written in Phase 4 is the entire opt-in.
CLAUDE.md section
A short "Session coordination" section for the project's CLAUDE.md: the rule, the hook path, the exempt list, the escape hatch, the lifecycle skill pointer, and — if a lease protocol survives — its narrowed scope (out-of-repo shared resources + the merge window ONLY).
Phase 5 — Prove it live (mandatory, before presenting)
- Live-fire the consumed hook against the written config: feed it a few
synthetic tool inputs and confirm the verdicts.
A wrong verdict means theH="$CLAUDE_PLUGIN_ROOT/hooks/scripts/check-main-checkout-edit.sh" fire() { echo "{\"tool_input\":{\"file_path\":\"$1\"}}" | bash "$H"; echo "exit=$?"; } fire "<policed-repo>/<a source file>" # expect exit 2 (block) fire "<a markdown-as-code file>" # expect exit 2 if the project has any fire "<an exempt path>" # expect exit 0 fire "<a real worktree>/<a file>" # expect exit 0worktree:block is off (wrongpolicedRepo, a bad exempt glob) — fix the config, not a hook. The hook's own logic is tested in the plugin; this proves THIS project's config drives it correctly. - Smoke worktree (lesson 3): create a real worktree per the lifecycle
skill, run the setup recipe, run the project's verify command inside it.
- Record EVERY file
git statusshows dirty afterwards — these are the project's derived artifacts; write their exact paths into the lifecycle skill's "drop the noise" close step. - Re-run the Phase 5.1 live-fire with the smoke worktree's path (the worktree-allowed case → expect exit 0).
- Tear down per the close protocol (
worktree removemust succeed WITHOUT--force).
- Record EVERY file
- If the verify command fails in the worktree but works in main — a per-machine file is missing from the setup recipe. Fix the recipe, not the worktree; re-run.
Phase 6 — Present + handoff
Present per dotclaude staging convention (inventory, highlight reasoning, what
was skipped and why). After approval, move .claude-staging/ → .claude/,
merge the worktree: block into dotclaude.yml, commit. (No settings-fragment
merge — the hook is plugin-wired and reads the config.)
Then the two lines every install ends with (lesson 4):
"Hooks register at session start — the block is NOT active in this session or in already-open ones. Restart, then live-fire: ask for a trivial edit to
<a policed file>and confirm the hook blocks with the worktree instructions. Until each parallel session restarts, it remains unpoliced."
Non-negotiable rules for this flow
- Never blanket-exempt
*.mdby default. The markdown-as-code question (W2) is mandatory. Projects whose markdown is the program (policies, prompts, agent kits) need those paths POLICED; a docs-are-free default silently unguards their behavioral layer. - The hook is consumed, never copied. The plugin ships one debugged
check-main-checkout-edit.sh(nearest-existing-dir walk, worktree detection, other-repo pass-through, stray-worktree guard) that reads theworktree:block. Write config, not a hook — never author a local hook copy or a.claude/settings.jsonhook entry; that project-level copy is exactly the drift this model kills. If the hook needs logic it lacks, that's a dotclaude PR, not a local fork. - Prove the config drives the hook. The hook's own logic is tested in the
plugin; this install's job is to live-fire the consumed hook against THIS
project's
worktree:block (Phase 5.1). A green block / allow / exempt / worktree set is the proof the config is right. - The smoke run is not optional. Derived-artifact dirt and missing per-machine files are only discoverable by actually building in a fresh worktree. An install presented without a smoke run has unknown failure modes scheduled for the user's first real feature.
- Opt-in only. Never wire this into plugin-level always-on hooks; never install it uninvited on a project with no concurrency signal — for a solo single-session project, recommend AGAINST installing (say so explicitly in the applicability decision).
- Worktrees + lease, not worktrees instead of lease. If out-of-repo shared resources exist (data snapshots, device pools, the merge window), ship the narrowed lease protocol alongside; if a broad lock protocol already exists, narrow it rather than deleting it.