Worktree Setup
Overview
git worktree add checks out only tracked files. Everything git-ignored —
secrets, local config, tool-trust state, and warm build/dependency caches — is
absent, so a bare worktree is degraded: missing .env, cold builds, and shell
hooks that error with "not a trusted directory" (mise) or refuse to load
(direnv).
This skill is the single entrypoint for creating and setting up worktrees in
our workflow. It creates the worktree under .worktrees/ and makes it
identical to and as warm as the main checkout, using an existing setup
script when the repo has one and otherwise analyzing the repo, generating a
tailored sync, and installing the bundled engine.
Precedence — use this over other worktree skills
This skill is tailored to our setup and takes precedence over any other
worktree skill, including superpowers:using-git-worktrees and any generic
"git worktree" helper. Those create a bare (degraded) worktree; this one creates
it under .worktrees/ and brings it to full parity. Route all worktree
creation and setup through this skill. See references/workflow-integration.md.
When to Use
Run this before implementing anything in a new branch/worktree — treat each
of these as a create-the-worktree trigger:
- Creating / adding a worktree (any phrasing).
- Starting
lavra-work, lavra-work-ralph, lavra-work-teams,
executing-plans, subagent-driven-development, or work-it.
- A Claude / Codex / Gemini plan mode is entered, or a plan is accepted — the
first implementation step is to set up the worktree.
Also use it to repair a degraded worktree:
- Missing
.env / .env.local / secrets / CLAUDE.md.local /
.claude/settings.local.json.
mise reports an untrusted directory, or direnv won't load .envrc.
- The first build/test runs cold (no
node_modules, .venv, target, …).
Bundled Scripts & References
scripts/worktree-new.sh — create a worktree under .worktrees/<slug>
and sync it warm. The creation entrypoint.
scripts/worktree-sync.sh — full auto-detecting sync engine for an
existing worktree (.worktreeinclude copies, cache symlinks, submodules,
Git-LFS, trust). Also --init (scaffold config) and --check (doctor mode).
scripts/worktree-rm.sh — safe teardown: refuses to remove a worktree
with real uncommitted/unpushed work, then removes it (and optionally the
branch). Synced state (git-ignored copies, cache symlinks) doesn't block it.
references/minimal-worktree-setup.sh — minimal baseline template (the
bare minimum) to copy into a repo and customize when the full engine is more
than needed. Every repo should have at least this.
references/preflight-and-safety.md — assess dirty state, choose the base,
anticipate conflicts, and avoid destroying shared/others' work.
references/what-to-sync.md — catalog of what to copy vs. symlink, by
ecosystem.
references/workflow-integration.md — triggers and precedence details.
tests/smoke.sh — regression test for the scripts (create/sync/check/init/rm).
Create + sync in one step (defaults: branch off HEAD, source = main worktree):
<skill-dir>/scripts/worktree-new.sh <branch> # create .worktrees/<slug> + sync
<skill-dir>/scripts/worktree-sync.sh --check # doctor: report parity gaps
<skill-dir>/scripts/worktree-sync.sh --init # scaffold .worktreeinclude/.worktree-sync
<skill-dir>/scripts/worktree-rm.sh <branch> # safe teardown when done
<skill-dir>/scripts/worktree-sync.sh --dry-run # preview a sync of the current worktree
<skill-dir>/scripts/worktree-sync.sh # apply
The engine copies the git-ignored files named in .worktreeinclude
(Claude Code's native file — .gitignore syntax at the repo root; only files
that match a pattern and are git-ignored are copied; a differing destination
file is not overwritten without --force). Honoring the same file gives
CLI/agent-created worktrees the parity Claude provides natively for
--worktree/subagent worktrees. When no .worktreeinclude exists, a curated
default set of secret/config files is copied instead. The engine also
symlinks known cache/dependency dirs (warm; --copy-caches / --no-caches),
populates submodules (git submodule update --init --recursive) and
Git-LFS content (git lfs checkout) so they aren't empty/pointer files,
re-runs mise trust / direnv allow, and applies an optional .worktree-sync
manifest for extras the native file can't express (link, plus run — which
executes arbitrary shell commands, same trust as a Makefile target). It only
ever touches git-ignored entries for copies, so it never clobbers tracked files.
Workflow
1. Pre-flight & safety (assess before creating anything)
You are usually not alone in this repo — other agents/people may have
worktrees, uncommitted work, and in-flight branches. Treat all of it as
precious. Full detail in references/preflight-and-safety.md.
2. Look for an existing setup mechanism (prefer it)
Search the repo before building anything, in order:
- Scripts:
scripts/, bin/, repo root — names matching *worktree*,
*bootstrap*, *setup*, *sync*, postcreate*, init*.
- Task runners:
Makefile, justfile, Taskfile.yml, mise.toml
[tasks], package.json scripts (setup/bootstrap/postinstall),
.devcontainer/ postCreateCommand.
- Docs:
CONTRIBUTING.md, README, docs/.
If one exists: read it, then run it correctly (right cwd, args/env). If it
creates the worktree, let it; otherwise create the worktree (step 3) and run the
repo's sync. Fill gaps it leaves (step 5) without duplicating it.
3. Create the worktree under .worktrees/
Always place worktrees in <repo>/.worktrees/<slug>:
<skill-dir>/scripts/worktree-new.sh <branch> [base-ref]
This creates the branch (or checks out an existing one), ensures .worktrees/
is git-ignored, and runs the sync. Equivalent manual form:
git worktree add -b <branch> .worktrees/<slug> HEAD followed by the sync.
4. Analyze the repo (only if no setup script exists)
Enumerate what the worktree is missing and classify it (full catalog in
references/what-to-sync.md):
- List git-ignored state:
git -C <main> ls-files --others --ignored --exclude-standard --directory.
- Detect tooling:
mise/.mise.toml, direnv/.envrc,
asdf/.tool-versions; package managers (npm/pnpm/yarn/bun, uv/poetry/pip,
cargo, go, gradle/maven); frameworks.
| Category |
Examples |
Action |
Where it goes |
| Secrets / env |
.env, .env.*, .envrc, .npmrc w/ tokens |
copy |
.worktreeinclude |
| Local config |
CLAUDE.md.local, .claude/settings.local.json, *.local |
copy |
.worktreeinclude |
| Tool trust |
.mise.toml, .envrc |
run mise trust / direnv allow |
automatic |
| Caches / deps |
node_modules, .venv, target, vendor, .gradle, .next |
symlink (warm) |
auto-detected |
| Data / large artifacts |
DB dumps, media, model weights |
ask the user |
.worktree-sync link |
Note: ~/.claude/settings.local.json is in $HOME, already shared by all
worktrees — only the project-level .claude/settings.local.json needs copying.
5. Generate the config (only if no setup script exists)
- Write
.worktreeinclude at the repo root listing the git-ignored files to
copy (.gitignore syntax). This is Claude Code's native file, so Claude
honors it for the worktrees it creates and worktree-sync.sh honors it too:.env
.env.local
.claude/settings.local.json
config/secrets.json
- Install a script for the parts
.worktreeinclude can't do (warm caches,
trust, reinstall): copy the full scripts/worktree-sync.sh engine into the
repo, or adopt references/minimal-worktree-setup.sh as a baseline. Preserve
the executable bit.
- Write
.worktree-sync (optional) only for extras the engine's
auto-detection misses — non-standard cache dirs and post-sync commands:link .cache/playwright
run pnpm install # reconcile deps against this branch's lockfile
- Wire it to run automatically where possible: register the engine as a
Claude Code
WorktreeCreate hook, or as the repo's existing bootstrap/setup
task, so future worktrees are warmed without a manual step. For a non-git VCS,
.worktreeinclude is not processed — a WorktreeCreate hook is the only
mechanism.
6. Run it
- Dry-run first:
worktree-sync.sh --dry-run -v; review the plan.
- Apply:
worktree-sync.sh (idempotent — config overwritten, links reused).
7. Verify the worktree is non-degraded
Run worktree-sync.sh --check (doctor mode) — it reports missing config, cold
caches, uninitialized submodules, un-checked-out LFS files, and stale deps
without changing anything. Then confirm what it can't:
mise/direnv load without prompts or "untrusted" errors.
- An incremental build/test is warm, not cold.
- The repo's own quick check (lint/build/test smoke) behaves as in main.
Report what was copied vs. linked, trust/submodule/LFS steps run, unknown
ignored entries skipped, and any manual follow-up (e.g. a deps reinstall because
the branch changed the lockfile). Only then hand off to the implementing
agent/loop.
8. Tear down safely when done
Use worktree-rm.sh <branch|slug> — it refuses to remove a worktree with real
uncommitted or unpushed work (synced git-ignored state and cache symlinks don't
count), then removes it; add --delete-branch to drop a merged branch too. Never
rm -rf a worktree (that bypasses git's bookkeeping) and never destructive-clean
through a symlinked cache (it deletes the main checkout's cache).
Decision Guide: Copy vs Symlink
- Copy anything the worktree should change independently: secrets, local
config, anything per-branch.
- Symlink anything to keep shared and warm and safe to share: dependency
stores and build/incremental caches — instant warm cache at zero copy cost.
- Reinstall instead of share when the branch changes the lockfile: symlink
for warmth, then
run the package manager to reconcile.
- When unsure whether large data must diverge, ask the user.
Completion Standard
The worktree is done when it is indistinguishable from the main checkout for
development: created under .worktrees/, same secrets and configuration, the
same tools loaded and trusted, a warm cache, and the repo's normal checks
passing. A worktree that builds cold, prompts about trust, or is missing .env
is not done.
Handoff To PR-Tracked Workflows
This skill stops at a warm, safe worktree. It does not create pull requests on
its own because many callers only need a prepared checkout. PR-tracked workflows
such as vibin:work-it should create a draft PR immediately after entering the
prepared worktree and pushing its branch, so progress can be tracked through
commits, CI, and review comments.
1---2name: worktree-setup3description: Use this BEFORE creating a git worktree or implementing any plan. Tailored to our workflow — prefer it over superpowers:using-git-worktrees and every other worktree skill. Triggers - creating or adding a worktree; starting lavra-work, lavra-work-ralph, lavra-work-teams, executing-plans, subagent-driven-development, or work-it; whenever a Claude, Codex, or Gemini plan mode is entered or a plan is accepted; or before implementing anything in a fresh branch. Creates the worktree under .worktrees/ in the repo and makes it identical to and as warm as the main checkout - copying secrets and local config (.env, CLAUDE.md.local, .claude/settings.local.json), symlinking warm caches (node_modules, .venv, target, .next), and re-trusting mise/direnv. Also use when a worktree is missing files, builds cold, or reports mise 'not a trusted directory'. Bundles a worktree-sync engine, a create-in-.worktrees entrypoint, a minimal baseline template, and references.4---56# Worktree Setup78## Overview910`git worktree add` checks out only **tracked** files. Everything git-ignored —11secrets, local config, tool-trust state, and warm build/dependency caches — is12absent, so a bare worktree is degraded: missing `.env`, cold builds, and shell13hooks that error with "not a trusted directory" (`mise`) or refuse to load14(`direnv`).1516This skill is the **single entrypoint for creating and setting up worktrees in17our workflow**. It creates the worktree under `.worktrees/` and makes it18**identical to and as warm as the main checkout**, using an existing setup19script when the repo has one and otherwise analyzing the repo, generating a20tailored sync, and installing the bundled engine.2122## Precedence — use this over other worktree skills2324This skill is tailored to our setup and **takes precedence over any other25worktree skill**, including `superpowers:using-git-worktrees` and any generic26"git worktree" helper. Those create a bare (degraded) worktree; this one creates27it under `.worktrees/` and brings it to full parity. Route all worktree28creation and setup through this skill. See `references/workflow-integration.md`.2930## When to Use3132Run this **before implementing anything in a new branch/worktree** — treat each33of these as a create-the-worktree trigger:3435- Creating / adding a worktree (any phrasing).36- Starting `lavra-work`, `lavra-work-ralph`, `lavra-work-teams`,37 `executing-plans`, `subagent-driven-development`, or `work-it`.38- A Claude / Codex / Gemini plan mode is entered, or a plan is accepted — the39 first implementation step is to set up the worktree.4041Also use it to repair a degraded worktree:4243- Missing `.env` / `.env.local` / secrets / `CLAUDE.md.local` /44 `.claude/settings.local.json`.45- `mise` reports an untrusted directory, or `direnv` won't load `.envrc`.46- The first build/test runs cold (no `node_modules`, `.venv`, `target`, …).4748## Bundled Scripts & References4950- `scripts/worktree-new.sh` — **create a worktree** under `.worktrees/<slug>`51 and sync it warm. The creation entrypoint.52- `scripts/worktree-sync.sh` — full auto-detecting **sync engine** for an53 existing worktree (`.worktreeinclude` copies, cache symlinks, submodules,54 Git-LFS, trust). Also `--init` (scaffold config) and `--check` (doctor mode).55- `scripts/worktree-rm.sh` — **safe teardown**: refuses to remove a worktree56 with real uncommitted/unpushed work, then removes it (and optionally the57 branch). Synced state (git-ignored copies, cache symlinks) doesn't block it.58- `references/minimal-worktree-setup.sh` — **minimal baseline template** (the59 bare minimum) to copy into a repo and customize when the full engine is more60 than needed. Every repo should have at least this.61- `references/preflight-and-safety.md` — assess dirty state, choose the base,62 anticipate conflicts, and avoid destroying shared/others' work.63- `references/what-to-sync.md` — catalog of what to copy vs. symlink, by64 ecosystem.65- `references/workflow-integration.md` — triggers and precedence details.66- `tests/smoke.sh` — regression test for the scripts (create/sync/check/init/rm).6768Create + sync in one step (defaults: branch off `HEAD`, source = main worktree):6970```bash71<skill-dir>/scripts/worktree-new.sh <branch> # create .worktrees/<slug> + sync72<skill-dir>/scripts/worktree-sync.sh --check # doctor: report parity gaps73<skill-dir>/scripts/worktree-sync.sh --init # scaffold .worktreeinclude/.worktree-sync74<skill-dir>/scripts/worktree-rm.sh <branch> # safe teardown when done75<skill-dir>/scripts/worktree-sync.sh --dry-run # preview a sync of the current worktree76<skill-dir>/scripts/worktree-sync.sh # apply77```7879The engine **copies** the git-ignored files named in **`.worktreeinclude`**80(Claude Code's native file — `.gitignore` syntax at the repo root; only files81that match a pattern *and* are git-ignored are copied; a differing destination82file is not overwritten without `--force`). Honoring the same file gives83CLI/agent-created worktrees the parity Claude provides natively for84`--worktree`/subagent worktrees. When no `.worktreeinclude` exists, a curated85default set of secret/config files is copied instead. The engine also86**symlinks** known cache/dependency dirs (warm; `--copy-caches` / `--no-caches`),87populates **submodules** (`git submodule update --init --recursive`) and88**Git-LFS** content (`git lfs checkout`) so they aren't empty/pointer files,89re-runs `mise trust` / `direnv allow`, and applies an optional `.worktree-sync`90manifest for extras the native file can't express (`link`, plus `run` — which91executes arbitrary shell commands, same trust as a Makefile target). It only92ever touches git-ignored entries for copies, so it never clobbers tracked files.9394## Workflow9596### 1. Pre-flight & safety (assess before creating anything)97You are usually **not alone in this repo** — other agents/people may have98worktrees, uncommitted work, and in-flight branches. Treat all of it as99precious. Full detail in `references/preflight-and-safety.md`.100101- **Current state:** `git status --short --branch` and `git worktree list`. If102 the current checkout is dirty, that is safe — creating a worktree never103 touches it — but its uncommitted changes will **not** appear in the new104 worktree (it starts from a committed ref). If you need them there, carry them105 deliberately (commit, or `git stash push -u` then `git stash apply` in the106 worktree, or a `git diff HEAD` patch). Never silently drop or "tidy" changes107 you did not create.108- **Choose the base deliberately:** for fresh work, `git fetch` and base on109 `origin/main` (not a stale local `main`); to continue work, base on `HEAD`; to110 build on someone's branch, base on `origin/<their-branch>`.111- **Anticipate conflicts now, not later:** check how the base diverges from the112 integration branch and what other branches touch, so a rebase/cherry-pick is113 planned, not a surprise:114 ```bash115 git fetch origin116 git rev-list --left-right --count HEAD...origin/main # behind / ahead117 git log --oneline HEAD..origin/main # what landed since118 ```119 If your base is behind `origin/main` or overlaps an active branch's files,120 state the expected rebase/conflict cost up front.121- **Shared state is shared:** the object store, refs, stash, config, and hooks122 are common to all worktrees. Avoid destructive/global commands123 (`reset --hard`, `clean -fdx`, `worktree remove --force`, `branch -D`,124 force-push, `stash clear`) unless confirmed and tightly scoped — they can125 destroy others' work. Decide the branch/slug for the new worktree.126127### 2. Look for an existing setup mechanism (prefer it)128Search the repo before building anything, in order:129- **Scripts:** `scripts/`, `bin/`, repo root — names matching `*worktree*`,130 `*bootstrap*`, `*setup*`, `*sync*`, `postcreate*`, `init*`.131- **Task runners:** `Makefile`, `justfile`, `Taskfile.yml`, `mise.toml`132 `[tasks]`, `package.json` `scripts` (`setup`/`bootstrap`/`postinstall`),133 `.devcontainer/` `postCreateCommand`.134- **Docs:** `CONTRIBUTING.md`, `README`, `docs/`.135136If one exists: **read it**, then run it correctly (right cwd, args/env). If it137creates the worktree, let it; otherwise create the worktree (step 3) and run the138repo's sync. Fill gaps it leaves (step 5) without duplicating it.139140### 3. Create the worktree under `.worktrees/`141Always place worktrees in `<repo>/.worktrees/<slug>`:142143```bash144<skill-dir>/scripts/worktree-new.sh <branch> [base-ref]145```146147This creates the branch (or checks out an existing one), ensures `.worktrees/`148is git-ignored, and runs the sync. Equivalent manual form:149`git worktree add -b <branch> .worktrees/<slug> HEAD` followed by the sync.150151### 4. Analyze the repo (only if no setup script exists)152Enumerate what the worktree is missing and classify it (full catalog in153`references/what-to-sync.md`):154- **List git-ignored state:**155 `git -C <main> ls-files --others --ignored --exclude-standard --directory`.156- **Detect tooling:** `mise`/`.mise.toml`, `direnv`/`.envrc`,157 `asdf`/`.tool-versions`; package managers (npm/pnpm/yarn/bun, uv/poetry/pip,158 cargo, go, gradle/maven); frameworks.159160| Category | Examples | Action | Where it goes |161|---|---|---|---|162| Secrets / env | `.env`, `.env.*`, `.envrc`, `.npmrc` w/ tokens | **copy** | `.worktreeinclude` |163| Local config | `CLAUDE.md.local`, `.claude/settings.local.json`, `*.local` | **copy** | `.worktreeinclude` |164| Tool trust | `.mise.toml`, `.envrc` | **run** `mise trust` / `direnv allow` | automatic |165| Caches / deps | `node_modules`, `.venv`, `target`, `vendor`, `.gradle`, `.next` | **symlink** (warm) | auto-detected |166| Data / large artifacts | DB dumps, media, model weights | **ask** the user | `.worktree-sync` `link` |167168Note: `~/.claude/settings.local.json` is in `$HOME`, already shared by all169worktrees — only the project-level `.claude/settings.local.json` needs copying.170171### 5. Generate the config (only if no setup script exists)1721. **Write `.worktreeinclude`** at the repo root listing the git-ignored files to173 copy (`.gitignore` syntax). This is Claude Code's native file, so Claude174 honors it for the worktrees it creates and `worktree-sync.sh` honors it too:175 ```gitignore176 .env177 .env.local178 .claude/settings.local.json179 config/secrets.json180 ```1812. **Install a script** for the parts `.worktreeinclude` can't do (warm caches,182 trust, reinstall): copy the full `scripts/worktree-sync.sh` engine into the183 repo, or adopt `references/minimal-worktree-setup.sh` as a baseline. Preserve184 the executable bit.1853. **Write `.worktree-sync`** (optional) only for extras the engine's186 auto-detection misses — non-standard cache dirs and post-sync commands:187 ```188 link .cache/playwright189 run pnpm install # reconcile deps against this branch's lockfile190 ```1914. **Wire it to run automatically** where possible: register the engine as a192 Claude Code `WorktreeCreate` hook, or as the repo's existing bootstrap/setup193 task, so future worktrees are warmed without a manual step. For a non-git VCS,194 `.worktreeinclude` is not processed — a `WorktreeCreate` hook is the only195 mechanism.196197### 6. Run it198- Dry-run first: `worktree-sync.sh --dry-run -v`; review the plan.199- Apply: `worktree-sync.sh` (idempotent — config overwritten, links reused).200201### 7. Verify the worktree is non-degraded202Run `worktree-sync.sh --check` (doctor mode) — it reports missing config, cold203caches, uninitialized submodules, un-checked-out LFS files, and stale deps204without changing anything. Then confirm what it can't:205- `mise`/`direnv` load without prompts or "untrusted" errors.206- An incremental build/test is warm, not cold.207- The repo's own quick check (lint/build/test smoke) behaves as in main.208209Report what was copied vs. linked, trust/submodule/LFS steps run, unknown210ignored entries skipped, and any manual follow-up (e.g. a deps reinstall because211the branch changed the lockfile). Only then hand off to the implementing212agent/loop.213214### 8. Tear down safely when done215Use `worktree-rm.sh <branch|slug>` — it refuses to remove a worktree with real216uncommitted or unpushed work (synced git-ignored state and cache symlinks don't217count), then removes it; add `--delete-branch` to drop a merged branch too. Never218`rm -rf` a worktree (that bypasses git's bookkeeping) and never destructive-clean219through a symlinked cache (it deletes the **main** checkout's cache).220221## Decision Guide: Copy vs Symlink222223- **Copy** anything the worktree should change independently: secrets, local224 config, anything per-branch.225- **Symlink** anything to keep shared and warm and safe to share: dependency226 stores and build/incremental caches — instant warm cache at zero copy cost.227- **Reinstall instead of share** when the branch changes the lockfile: symlink228 for warmth, then `run` the package manager to reconcile.229- When unsure whether large data must diverge, **ask the user**.230231## Completion Standard232233The worktree is done when it is indistinguishable from the main checkout for234development: created under `.worktrees/`, same secrets and configuration, the235same tools loaded and trusted, a warm cache, and the repo's normal checks236passing. A worktree that builds cold, prompts about trust, or is missing `.env`237is not done.238239## Handoff To PR-Tracked Workflows240241This skill stops at a warm, safe worktree. It does not create pull requests on242its own because many callers only need a prepared checkout. PR-tracked workflows243such as `vibin:work-it` should create a draft PR immediately after entering the244prepared worktree and pushing its branch, so progress can be tracked through245commits, CI, and review comments.