wt

star 2

Manage git worktree isolation — create, list, remove, prune, and seed env files for worktrees with isolated databases, Docker services, and ports

Tokenbooks By Tokenbooks schedule Updated 6/5/2026

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 .env files (not .env.example): find . -name '.env' -not -path '*/node_modules/*' -not -path '*/.git/*'
  • All committed .env.example files with safe local defaults: find . -name '.env.example' -not -path '*/node_modules/*' -not -path '*/.git/*'
  • The DATABASE_URL value to extract the base database name (path segment after the port, before ?)
  • Any REDIS_URL values and their base port/auth format
  • All services and their default ports — check package.json scripts, 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 port and url patch must have a service that exists in services
  • patches may be omitted for seed-only env files
  • Every dockerServices[].ports[].service must exist in services
  • Every envFiles[].seedFrom should be a committed example file with safe local defaults
  • portStride * maxSlots + max default port must be < 65535
  • baseDatabaseName must match the actual DB name in DATABASE_URL
  • If using dockerServices, Docker must be available locally
  • Do not use legacy type: "redis" patches; use type: "url" for REDIS_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 audit to see which worktrees are merged and safe to remove, then wt prune --merged (or wt remove)
  • Database connection failed → check that Postgres is running and DATABASE_URL in root .env is 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 2
  • wt remove 1,2
  • wt 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-run to preview what would be pruned
  • --keep-db to keep databases for matching managed allocations
  • --merged to 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 to wt 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-fetch to skip refreshing origin/main first
  • --base <ref> to audit against a different base
  • --ignore-dirty <paths...> to treat matching path fragments as never-real dirt
  • --json for 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 when wt list or wt doctor reports stale allocations and you want to keep the worktree directory intact. Do NOT use wt remove for 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
Install via CLI
npx skills add https://github.com/Tokenbooks/wt --skill wt
Repository Details
star Stars 2
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator