agentsclimarketplace

Worktree

Skill vindm/dotclaude/plugins/core/skills/worktree

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.From its SKILL.md

Install
npx -y skills add vindm/dotclaude --skill worktree

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

3 things to look at

  • reads credentialsReads from 1 credential source: `.env*`.
  • 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.
  • runs commandsInstructs the agent to run 8 commands, including `git rev-parse --show-toplevel 2>/dev/null` and 7 more.

SKILL.md

11.1 KB, ~2.7k tokens by cl100k_base, 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:

  1. 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/null
    

    Multiple sibling repos → ask which one(s) carry the collision risk (usually the one being actively developed, not read-only references/snapshots).

  2. Parallel-session evidence — lock files (.session_lock, *.lock at 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.

  3. 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 *.example template / symlink from main / regenerate / skip.

  4. 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.

  5. Verify command — how the project proves itself (from package.json scripts, 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 *.md unless 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 the artifacts: / 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:

  1. 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 from git -C <repo> worktree list --porcelain into 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.
  2. Verify: the project's verify command + expected output.
  3. 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.
  4. Escape hatch: the allow-main-edits convention, ask-first.
  5. 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)

  1. Live-fire the consumed hook against the written config: feed it a few synthetic tool inputs and confirm the verdicts.
    H="$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 0
    
    A wrong verdict means the worktree: block is off (wrong policedRepo, 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.
  2. 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 status shows 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 remove must succeed WITHOUT --force).
  3. 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

  1. Never blanket-exempt *.md by 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.
  2. 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 the worktree: block. Write config, not a hook — never author a local hook copy or a .claude/settings.json hook 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.
  3. 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.
  4. 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.
  5. 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).
  6. 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.

What ships with it: 1 file

3.4 KB alongside SKILL.md

Keep looking

Skills are one crate of 625,605. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.