dev-worktrees
Overview
Creates an isolated git worktree with dependency install, port allocation (when dev-setup scripts are present), and baseline test verification.
Works in two modes — the steps after worktree creation are identical in both:
- Create mode: branch does not exist yet → creates worktree + branch, then sets up
- Setup mode: worktree already exists (created manually or by another tool) → enters it and runs setup only (deps + ports + tests)
Announce at start: "I'm using the dev-worktrees skill to set up an isolated workspace."
Branch Name
Branch: $ARGUMENTS
If the branch name above is empty: derive it from context (implementation plan, task description) or ask the user:
"What branch name should I use? (e.g.
feature/auth,fix/login-bug)"
Use the branch name exactly as provided — do not sanitize or replace / with - or any other character. Branch names with slashes (e.g. feature/auth) create nested directories in the worktree folder, which is handled in the Create Worktree step with mkdir -p.
Worktree Directory Selection
Follow this priority order exactly — do NOT skip steps or invent paths:
Read
.claude/dev-setup.json→worktrees_dirkey- If key present in file: use that value. Stop here. Do not ask.
Check if
.worktrees/exists in project root → use itCheck if
worktrees/exists in project root → use it- If both exist:
.worktrees/wins — use it without asking.
- If both exist:
Check
CLAUDE.mdfor a worktree directory preference:grep -i "worktree.*dir" CLAUDE.md 2>/dev/nullIf a preference is found: use it. Do not ask.
Ask user — recommend
.worktrees/as the default:.worktrees/— project-local, hidden (recommended)~/.config/worktrees/<project-name>/— global (no gitignore check needed; directory auto-created bygit worktree add)
Never invent a directory (e.g. sibling pattern, --branch-name suffix) without going through this priority order first.
Safety Check (project-local dirs only)
ALWAYS run before creating the worktree — do NOT skip this step:
git check-ignore -q <worktrees-dir>
Do not manually read .gitignore. Use git check-ignore -q.
If NOT ignored: add to .gitignore and commit before proceeding:
echo "<worktrees-dir>/" >> .gitignore
git add .gitignore
git commit -m "chore: add <worktrees-dir> to .gitignore"
Create Worktree
Before creating, check for an existing branch or worktree:
git worktree list | grep "<branch>" # non-empty → worktree already exists
git branch --list "<branch>" # non-empty → branch exists, no worktree yet
- Worktree already exists → setup mode: extract its path from
git worktree list,EnterWorktreeto it, then proceed directly to Install Dependencies. Skip the Safety Check andgit worktree addentirely — the worktree is already there. - Branch exists, no worktree →
git worktree add <full-path>/<branch> <branch>(no-b) - Neither exists →
git worktree add <full-path>/<branch> -b <branch>
project=$(basename "$(git rev-parse --show-toplevel)")
# Create intermediate directories if branch name contains slashes
mkdir -p "$(dirname "<full-path>/<branch>")"
git worktree add <full-path>/<branch> [-b] <branch>
After the worktree is created, use the EnterWorktree tool to set Claude's working directory to <full-path>/<branch>. Do NOT use cd in Bash — it does not persist between tool calls and subsequent steps (install, tests) will silently run in the wrong directory.
<full-path>/<branch> is:
- Local:
<worktrees-dir>/<branch> - Global:
~/.config/worktrees/<project>/<branch>
Use the branch name as-is for the folder name. Do not replace / with - or any other character.
Install Dependencies
Auto-detect and run from the new worktree directory:
| Manifest | Command |
|---|---|
package.json |
detect from lockfile (see below) |
Cargo.toml |
cargo build |
go.mod |
go mod download |
requirements.txt |
pip install -r requirements.txt |
pyproject.toml |
poetry install |
| None found | skip — note "No dependency manifest found" |
Node.js lockfile → package manager (check in this order):
| Lockfile | Manager |
|---|---|
bun.lockb |
bun install |
pnpm-lock.yaml |
pnpm install |
yarn.lock |
yarn install |
package-lock.json or none |
npm install |
Remember the detected manager — use it for the baseline test command too.
Port Allocation (conditional)
Search for dev-wt-ports.sh in these dirs (relative to project root):
tools/dev/, scripts/, bin/, devtools/
If NOT found:
"No dev-setup scripts found — skipping port allocation. Run /dev-setup to add port isolation support."
Continue to the next step. Do NOT stop.
If found (SCRIPT_DIR = that directory):
First check whether .wt-ports.env already exists and has content in the worktree root:
[[ -s "<worktree-path>/.wt-ports.env" ]]
- Non-empty
.wt-ports.envfound → skip allocation, note "ports already allocated" in report. Do NOT re-allocate — that would break any servers currently using those ports. - Missing or empty → allocate:
bash <SCRIPT_DIR>/dev-wt-ports.sh <worktree-full-path> <branch>
Do NOT call dev-allocate-ports.sh directly — always call dev-wt-ports.sh.
Then verify .wt-ports.env exists and is non-empty in the worktree root.
Baseline Test Verification
Auto-detect and run from the new worktree directory:
| Manifest | Command |
|---|---|
package.json |
<package-manager> test (use same manager detected for install: npm/yarn/pnpm/bun) |
Cargo.toml |
cargo test |
pyproject.toml / requirements.txt |
pytest |
go.mod |
go test ./... |
| None found | skip — note "No test framework detected" |
- Pass: record test count
- Fail: report failures, ask "Proceed anyway or investigate first?"
Do NOT skip this step. Baseline tests are always run.
Report
Worktree ready at <full-path>
Ports allocated: API_WT_PORT=<n>, WEB_WT_PORT=<n>, ... (if ports allocated)
Tests passing (<N> tests, 0 failures) (if tests ran)
Ready to implement <feature-name>
When done: run /merge-checks before merging
Quick Reference
| Situation | Action |
|---|---|
Config has worktrees_dir |
Use it — do not ask |
.worktrees/ exists |
Use it (verify ignored) |
worktrees/ exists |
Use it (verify ignored) |
Both .worktrees/ and worktrees/ exist |
.worktrees/ wins |
| Neither exists | Check CLAUDE.md → ask user |
| Dir not ignored | Add to .gitignore + commit first |
| Worktree already exists | Setup mode: EnterWorktree → deps → ports → tests (no git worktree add) |
.wt-ports.env already has content |
Skip port allocation — note "already allocated" |
| No dev-setup scripts | Skip port allocation, continue |
| Tests fail | Report + ask before proceeding |
Common Mistakes
- Using
cdinstead ofEnterWorktree—cdin Bash does not persist; install and tests run in the wrong directory - Skipping the branch existence check —
git worktree add -b <branch>fails if the branch already exists - Inventing a directory — always follow priority order, never assume a sibling pattern
- Reading .gitignore manually — always use
git check-ignore -q <dir> - Calling dev-allocate-ports.sh directly — always call
dev-wt-ports.sh <path> <branch> - Skipping baseline tests — always run, always ask if they fail
- Replacing
/in branch name — use the branch name exactly as-is for the folder