name: wt description: Manage git worktree isolation — create, list, remove, prune, and seed env files for worktrees with isolated databases, Docker services, and ports argument-hint: "[new|open|list|remove|prune|doctor|setup|env|init] [args...]" allowed-tools: Bash, Read, Write, Edit, Grep, Glob
wt — Git Worktree Isolation
You are managing git worktrees with isolated Postgres databases, per-worktree Docker services, and ports using the wt CLI.
Routing
Based on the first argument, perform one of the following:
init — First-time setup for a repository
The user wants to set up wt in their project for the first time. Follow these steps exactly:
Step 1: Discover the project
Search the repository to find:
- All
.envfiles (not.env.example):find . -name '.env' -not -path '*/node_modules/*' -not -path '*/.git/*' - All committed
.env.examplefiles with safe local defaults:find . -name '.env.example' -not -path '*/node_modules/*' -not -path '*/.git/*' - The
DATABASE_URLvalue to extract the base database name (path segment after the port, before?) - Any
REDIS_URLvalues and their base port/auth format - All services and their default ports — check
package.jsonscripts, Docker Compose files, framework config files - Per-worktree Docker services that should move into
dockerServices - The package manager in use (
pnpm,npm,yarn) — check for lockfiles
Step 2: Map env vars to patch types
For each .env file, examine every variable and classify:
| Variable contains | Patch type | Needs service? |
|---|---|---|
Postgres connection URL (postgresql://...) |
database |
No |
Redis connection URL (redis://...) |
url |
Yes (redis) |
| Just a port number | port |
Yes |
A URL containing a service port (http://localhost:3000/...) |
url |
Yes |
| Anything else (API keys, secrets, flags) | Skip — do not patch | — |
Step 3: Generate wt.config.json
Build the config file at the repository root:
{
"baseDatabaseName": "<extracted from DATABASE_URL>",
"baseWorktreePath": ".worktrees",
"portStride": 100,
"maxSlots": 50,
"services": [
{ "name": "<service>", "defaultPort": <port> },
{ "name": "redis", "defaultPort": <port from REDIS_URL or 6379> }
],
"dockerServices": [
{
"name": "redis",
"image": "redis:8-alpine",
"ports": [{ "service": "redis", "target": 6379 }]
}
],
"envFiles": [
{
"source": "<relative path to .env file>",
"seedFrom": "<optional relative path to .env.example>",
"patches": [
{ "var": "<VAR_NAME>", "type": "<database|port|url|branch>", "service": "<name>" }
]
}
],
"postSetup": ["<install command>"],
"autoInstall": true
}
Validation rules:
- Every
portandurlpatch must have aservicethat exists inservices patchesmay be omitted for seed-only env files- Every
dockerServices[].ports[].servicemust exist inservices - Every
envFiles[].seedFromshould be a committed example file with safe local defaults portStride*maxSlots+ max default port must be < 65535baseDatabaseNamemust match the actual DB name inDATABASE_URL- If using
dockerServices, Docker must be available locally - Do not use legacy
type: "redis"patches; usetype: "url"forREDIS_URL
Step 4: Install wt
# Detect package manager and install
pnpm add -D @tokenbooks/wt
Step 5: Update .gitignore
Add .worktree-registry.json if not already present.
Step 6: Add convenience scripts to root package.json
{
"scripts": {
"wt": "wt",
"wt:new": "wt new",
"wt:env": "wt env seed",
"wt:list": "wt list",
"wt:doctor": "wt doctor"
}
}
Step 7: Create .husky/post-checkout hook (if husky is installed)
#!/bin/bash
prev_head="$1"
new_head="$2"
is_branch="$3"
[ "$is_branch" = "0" ] && exit 0
git_common=$(git rev-parse --git-common-dir 2>/dev/null)
git_dir=$(git rev-parse --git-dir 2>/dev/null)
[ "$git_common" = "$git_dir" ] && exit 0
main_worktree=$(cd "$git_common/.." && pwd -P)
wt_bin="$main_worktree/node_modules/.bin/wt"
if [ ! -f "$wt_bin" ]; then
wt_bin=$(command -v wt 2>/dev/null || true)
fi
if [ -z "$wt_bin" ]; then
echo "Warning: wt CLI not found."
exit 0
fi
echo "Setting up worktree environment..."
"$wt_bin" setup "$(pwd -P)" --json 2>/dev/null && echo "Worktree ready!" || {
echo "Warning: Auto-setup failed. Run 'wt setup' manually."
exit 0
}
Make it executable: chmod +x .husky/post-checkout
Step 8: Smoke test
wt list # Should show "No worktree allocations found."
wt doctor # Should show "All checks passed."
wt env seed --dry-run # Should preview safe env default updates
wt new test/wt-smoke --no-install # Create a test worktree
wt list # Should show the allocation
wt remove .worktrees/test-wt-smoke # Clean up
wt prune --dry-run # Should show no Git-prunable worktrees
Present the results to the user.
open $1 — Open (or create) a worktree
Run:
wt open $1
Accepts a slot number (1) or branch name (feat/auth). If a branch isn't found in the registry, it creates a new worktree automatically.
Tip: use cd $(wt open $1) to jump into the worktree directory.
new $1 — Create a new worktree
Run:
wt new $1
If it fails, check wt doctor for diagnostics. Common issues:
- All slots occupied → run
wt auditto see which worktrees are merged and safe to remove, thenwt prune --merged(orwt remove) - Database connection failed → check that Postgres is running and
DATABASE_URLin root.envis correct
list — List all worktree allocations
Run:
wt list
remove [targets...]|--all — Remove one or more worktrees
Run:
wt remove $@
Accepts paths or slots, not branch names, including batch slot formats:
wt remove 1 2wt remove 1,2wt remove "1, 2"wt remove --all
If the user wants to keep the database, use --keep-db.
prune — Prune Git-prunable worktrees
Run:
wt prune $@
Use this when worktree directories were deleted manually and Git already marks them as prunable.
Flags:
--dry-runto preview what would be pruned--keep-dbto keep databases for matching managed allocations--mergedto also remove live worktrees whose branch is already merged into the base ref (audit-confirmed and clean only — never deletes uncommitted work). This is the "act on it" companion towt audit.
audit — Classify worktrees by merge state
Run:
wt audit $@
Use this when slots are full or the workspace is cluttered and you want to know which worktrees are finished and safe to delete. It classifies each worktree by how its branch relates to the base ref (origin/main, then main) and prints a copyable wt remove for the safe ones. Deletion safety is grounded in git (reachable from the base ref, or folded into a retained branch), not GitHub PR state; trees with uncommitted work are never suggested.
Flags:
--no-fetchto skip refreshingorigin/mainfirst--base <ref>to audit against a different base--ignore-dirty <paths...>to treat matching path fragments as never-real dirt--jsonfor machine-readable verdicts, e.g.wt audit --json | jq '.data[] | select(.verdict=="delete-merged")'
To act on it: copy the printed wt remove line, or run wt prune --merged to remove every audit-confirmed-safe worktree at once.
doctor — Diagnose issues
Run:
wt doctor
If issues are found, ask the user if they want to auto-fix:
wt doctor --fix
setup — Set up an existing worktree
Run:
wt setup $1
Use this when a worktree was created with plain git worktree add instead of wt new.
Variants:
wt setup --repair— re-allocate ports for an existing worktree (e.g. when one of its ports has been seized by another process). Use whenwt listorwt doctorreports stale allocations and you want to keep the worktree directory intact. Do NOT usewt removefor this — it deletes the worktree directory and uncommitted work. Repair preserves the directory, database, and untouched ports.wt setup --repair --dry-run— preview the reallocation without applying. Prints the proposed port changes and which docker services will be recreated.
env seed [path] — Seed safe env defaults
Run:
wt env seed $1
Use this in the root worktree or any branch worktree when .env.example files configured through envFiles[].seedFrom have gained new safe local-development variables. It creates missing configured .env targets from examples and appends only variables that are missing from existing targets. It never overwrites developer values.
Variants:
wt env seed --dry-run— preview files that would be created and vars that would be appended.wt env seed --json— output machine-readable results.
wt new and wt setup run this same seed pass automatically after copying env files from the main worktree and before applying slot-specific patches.
No arguments or unrecognized command
Show a brief help:
Available commands:
/wt init — Set up wt in a new repository (discovers env files, generates config)
/wt new <branch> — Create a worktree with isolated DB, Docker services, and ports
/wt open <slot|branch> — Open a worktree by slot or branch (creates if not found)
/wt list — List all worktree allocations
/wt audit — Classify worktrees by merge state; suggest which are safe to remove
/wt remove <targets...>|--all — Remove one or more worktrees and clean up resources
/wt prune [--dry-run] [--merged] — Prune Git-prunable (and, with --merged, audit-confirmed merged) worktrees
/wt doctor — Diagnose and fix environment issues
/wt setup [path] — Set up an existing worktree
/wt env seed [path] — Create/fill safe env defaults from examples