WT is an agent-first Git worktree manager for LLM agents. It lets several agents work concurrently on the same project through one unified worktree manager, regardless of which coding agent you use. Switch between Claude Code, Codex, Cursor, OpenCode, or another agent without changing the project's worktree workflow.
Each agent gets a named, isolated worktree while WT handles branch creation, project setup and teardown, slot allocation, port offsets, and safe cleanup. WT also works well for human-led parallel feature work.
Git worktrees solve the one-checkout-per-branch problem. WT also gives each worktree repeatable setup and teardown, a reserved slot, predictable port offsets, and a discoverable list of managed and unmanaged worktrees. That keeps several agents from competing over one checkout, one dependency setup, or one development port.
WT has one Node.js CLI and three supported distribution modes. All modes require Node.js 18 or newer and Git.
curl -fsSL https://github.com/absolutepraya/wt/releases/latest/download/install.sh | bashThe release-based installer downloads the latest stable release, verifies the SHA-256 manifest and the embedded CLI version, then installs atomically. It installs:
~/.local/bin/wt, the executable~/.config/wt/wt.sh, the Bash and Zsh wrapper~/.config/wt/wt.fish, the Fish wrapper~/.config/wt/install.json, standalone channel metadata
The installer adds managed wrapper blocks to Bash, Zsh, and Fish startup files. The executable is available immediately at ~/.local/bin/wt even if that directory is not yet in PATH. Future interactive shells that source the relevant rc or config file will load the integration. Bash login shells may not source ~/.bashrc automatically, so use your shell's normal login configuration or source the wrapper explicitly. For the current shell, add the directory to PATH and evaluate the shell initializer as shown below.
The installer checks the platform, Node.js, and Git before writing the destination files. If Node.js or Git is missing, it stops with an actionable message and does not install a partial CLI.
The standalone installer supports macOS and Linux. Windows users should use the npm installation, which supports the CLI and shell initializer on Windows.
npm install -g @absolutepraya/wt
wt --helpThis puts the wt executable in npm's global bin directory. It does not edit Bash, Zsh, Fish, or PowerShell profiles. Use npm to update it:
npm update -g @absolutepraya/wtnpm install -D @absolutepraya/wt
npx --no-install wt --helpThe consuming project's lockfile pins WT for agents and npm scripts. The local package does not edit shell profiles. Use npm to update it:
npm update -D @absolutepraya/wtThe global and local npm packages use the same bundled dist/wt.cjs artifact as the standalone release. npm installs support macOS, Linux, and Windows for the core commands.
git clone https://github.com/absolutepraya/wt ~/Documents/Projects/wt
cd ~/Documents/Projects/wt
npm ci
npm run build
node dist/wt.cjs --helpSource checkouts are updated through Git, for example with git pull --ff-only after reviewing the incoming changes. wt update does not modify a source checkout.
- Node.js 18 or newer
- Git 2.5 or newer, with worktree support
- macOS or Linux for the standalone installer
- macOS, Linux, or Windows for npm installations
Standalone files default to ~/.local/bin and ~/.config/wt. Set PREFIX or WT_CONFIG_DIR for a different standalone location. Project state is kept outside the repository at ~/.wt/<project-id>.json, with a matching lock path. No npm package installation creates or changes a project's shell profile.
wt shell-init prints the integration for the current shell. It does not edit any profile. The initializer is useful immediately after installation and when a shell uses a custom profile path.
eval "$(~/.local/bin/wt shell-init bash)"To load it in future shells, source the generated wrapper from a profile:
source ~/.config/wt/wt.sheval "$(~/.local/bin/wt shell-init zsh)"The Bash and Zsh initializer output is shell-compatible. A future Zsh can source the same wrapper:
source ~/.config/wt/wt.sh~/.local/bin/wt shell-init fish | sourceFor future Fish shells:
source ~/.config/wt/wt.fishInvoke-Expression (& wt shell-init powershell)Add that line to the PowerShell profile yourself if it should load in future sessions. WT never edits a PowerShell profile automatically.
The shell wrapper consumes WT's __cd__:<path> navigation sentinel for wt new --cd and wt cd. A child process cannot change the working directory of its parent shell, so running a raw executable as a subprocess cannot navigate the calling shell. Coding agents should use wt new without --cd, then use the absolute worktree path printed by WT for subsequent commands.
In a Git repository, create .wt/config.toml once if the project is not already configured:
mkdir -p .wt
cat > .wt/config.toml <<'EOF'
worktree_path = ".worktrees"
port_offset_interval = 100
max_slots = 9
EOF
wt newwt --version, -V print the installed WT version
wt --help, -h show top-level help
wt new create a worktree from origin/main
wt new [name] choose a worktree name
wt new -b user/feature choose the branch name
wt new --from feature-x base on an existing remote branch
wt new --no-setup skip configured setup commands
wt new --skip-setup alias for --no-setup
wt new --cd navigate the interactive shell after creation
wt ls list managed and unmanaged Git worktrees
wt list alias for ls
wt cd print the current or main worktree path
wt cd <name> print a named worktree path
wt rm <name> run teardown and remove the worktree
wt remove <name> alias for rm
wt rm <name> --force bypass dirty, unmerged, and teardown failures
wt rm <name> --keep-branch remove the worktree but preserve its branch
wt update update a standalone installation
wt update --check check the latest stable release for standalone installs
wt shell-init bash print Bash integration
wt shell-init zsh print Zsh integration
wt shell-init fish print Fish integration
wt shell-init powershell print PowerShell integration
Run wt <command> --help or wt <command> -h for command-specific usage.
wt new stays in the current directory unless its shell wrapper receives
--cd. wt update is only a self-mutating command for a standalone
installation. For a standalone install, wt update --check checks the latest
stable release without changing files. For npm or source installs, it does not
check the release service. It only prints guidance to update through npm or
Git. Use npm update for npm installations and Git for a source checkout.
Configuration is discovered upward from the current directory at <repo>/.wt/config.toml:
worktree_path = ".worktrees"
port_offset_interval = 100
max_slots = 9
name_strategy = "cities" # or "word_pairs"
branch_template = "{user}/{name}"
default_base = "origin/main"
setup = [
"pnpm install --frozen-lockfile",
"cp .env.example .env.local",
"bash scripts/start-infra.sh",
]
teardown = [
"docker compose -p ${WT_WORKSPACE_NAME} down",
"docker network prune -f",
]worktree_path must remain inside the repository. Each non-main worktree gets the first free slot from 1 through max_slots and a port base of slot * port_offset_interval. default_base defaults to origin/main. Setup and teardown arrays run in order from the worktree directory through the platform shell.
Every configured setup and teardown command receives these values without modifying the parent process environment:
| Variable | Example | Purpose |
|---|---|---|
WT_ROOT_PATH |
/home/you/code/myrepo |
Main worktree root |
WT_WORKSPACE_NAME |
rotterdam |
Worktree name |
WT_WORKSPACE_PATH |
/home/you/code/myrepo/.worktrees/rotterdam |
Absolute worktree path |
WT_BRANCH |
you/rotterdam |
Live branch name |
WT_SLOT |
3 |
Allocated slot |
WT_PORT_BASE |
300 |
Slot times port_offset_interval |
For example, a service using port 5432 can bind to 5432 + WT_PORT_BASE in its setup script.
WT stores one JSON state file per project under ~/.wt. It records the project root and managed slot entries, including the name, branch, relative path, base ref, remote tracking state, creation time, and a generation token. State writes are validated and replaced atomically. A project lock serializes slot allocation and destructive state changes.
wt newfetches the configured base, allocates a slot, creates the Git worktree, persists state, and then runs setup.- If setup fails or is interrupted, WT rolls back the newly created worktree and branch while preserving replacement state if another operation has taken ownership.
wt newis safe to run concurrently. Slot and name allocation are protected by the project lock.wt rmrefuses to remove the worktree containing the current directory.wt rmchecks the live branch and worktree identity again after teardown, so a replacement cannot be removed accidentally.- Dirty worktrees and branches with unmerged commits require confirmation.
--forcebypasses those checks.--keep-branchremoves only the worktree. - A worktree known to Git but not to WT appears as unmanaged in
wt ls; remove it with Git rather thanwt rm. - A stale or incompatible state entry is reported and is not silently destroyed.
package.json is the release version source of truth. CI injects that version into dist/wt.cjs, then uses the same bytes for npm and standalone distribution. A stable release has the tag vX.Y.Z and these exact assets:
wt
wt.sh
wt.fish
install.sh
absolutepraya-wt-X.Y.Z.tgz
checksums.txt
The checksum manifest covers the other five assets. The installer and wt update accept only stable vX.Y.Z releases, validate the expected release URLs, verify every downloaded checksum, and check the Node shebang and embedded version before replacement. The standalone installer stages its files, runs a direct --version and --help smoke on the installed executable, and rolls back if installation or that smoke fails. wt update uses its existing transactional replacement behavior for the standalone executable, wrappers, and metadata, with rollback on replacement failure; it does not currently run the post-install smoke. See docs/RELEASING.md for Trusted Publishing and release recovery.
Python-based standalone users on the 0.3.x line should run the new installer once:
curl -fsSL https://github.com/absolutepraya/wt/releases/latest/download/install.sh | bashThe installer replaces the old standalone executable and wrappers with the Node-based release after validation. It requires Node.js 18 or newer and Git. No WT_REF setting is needed for ordinary installs. Start a new shell, or refresh the current shell using the shell-init examples above, then confirm with wt --version.
This repository ships an Agent Skill at skills/wt/SKILL.md. It teaches agents when to use WT instead of raw Git worktree commands and how to preserve project safety.
Install the skill with the Vercel Skills CLI:
npx skills add absolutepraya/wt --skill wt
npx skills add absolutepraya/wt --skill wt --global --agent codexAgents should use wt new without --cd. The successful output contains the worktree path to use for subsequent commands because a child process cannot change the agent host's working directory.
git clone https://github.com/absolutepraya/wt
cd wt
npm ci
npm test
npm run check
npm run pack:check
npm run smoke:npm
bash -n install.sh
bash scripts/check-installer.sh
git diff --checkThe CI matrix runs Node 18, 20, 22, and 24 on Ubuntu, macOS, and Windows. POSIX installer tests run on Unix runners; Windows validates the cross-platform Node package and shell initializer.