for cloud alternative - pier gives every agent session its own VM on your AWS account.
Git worktrees, ready for your agents. One shell function, no fluff.
wt feature-x creates a worktree under ~/worktrees/<repo>/, drops you into
it, and runs your repo's setup script in the background: env files copied,
dependencies installing. You (or the agent you're about to work with) start on
a branch that already works.

Why
Worktrees are the way to run parallel work: a branch per task, a branch
per agent, no stashing, no waiting for node_modules to reshuffle. But raw
git makes each one a chore:
git worktree add ../myrepo-feature-x -b feature-x
cd ../myrepo-feature-x
cp ../myrepo/.env .
cp ../myrepo/apps/api/.env.local apps/api/
npm install # ...wait
With wt:
wt feature-x
No daemon, no binary, no config file. One sourceable shell function you can read before trusting.
Install
brew install kerem-kaynak/tap/wt
then add the line brew prints to your ~/.zshrc or ~/.bashrc (wt has to be
sourced, since it cds your shell, which no binary can do). Without brew:
git clone https://github.com/kerem-kaynak/wt.git ~/wt
echo 'source ~/wt/wt.sh' >> ~/.zshrc
Requires git; the GitHub CLI (gh) only for wt -p. Works in zsh and bash.
Set up
Two optional environment variables, set in your shell rc next to the source
line:
| Variable | What | Default |
|---|---|---|
WT_ROOT |
where worktrees live | ~/worktrees |
WT_SETUP |
setup script path, relative to the repo root | .wt-setup.sh |
Then give each repo a setup script, so its worktrees come up ready to run:
Write it yourself. Save an executable
.wt-setup.shat the repo root (or whereverWT_SETUPpoints). Start fromexamples/wt-setup.sh.Or let your agent write it. wt ships with a Claude Code skill. Copy it into
~/.claude/skills/(or your repo's.claude/skills/) and ask your agent to "set up wt for this repo". It finds the env files and install steps your repo needs and writes.wt-setup.shfor you.cp -r "$(brew --prefix)/share/wt/skills/wt-setup-script" ~/.claude/skills/
Repos without a setup script still work: wt warns and leaves the worktree
bare.
The setup script
A fresh worktree is a clean checkout: no .env files, no node_modules,
none of the untracked local files your app needs. Your setup script is where
your repo fixes that, and writing it is your job; wt just runs it.
After creating a worktree, wt runs the first of these that exists, in the
background:
- the path in
$WT_SETUP, resolved relative to the repo root .wt-setup.shat the repo root
The script runs with the new worktree as its working directory and one
argument: the path to the main checkout. Typical job: copy untracked local
files from the main checkout, then install dependencies. It logs to
<worktree>.setup.log next to the worktree, and you get a desktop
notification (macOS or Linux) when it finishes or fails. Watch it live with
wt log <match>.
Usage
Run it from anywhere inside a repo (including from another worktree):
wt <new-branch> [base] create a branch off base (default: origin's default branch)
wt -b <branch> check out an existing branch
wt -p <n> check out PR #n
wt ls list this repo's worktrees
wt cd <match> jump to the worktree matching <match> (substring, case-insensitive)
wt main jump back to the main checkout
wt log <match> follow a worktree's setup log
wt rm <match> remove a worktree and delete its branch
To hop into a worktree you saw in wt ls, use wt cd with any part of its
name; wt ls reminds you of this after the listing. Tab completion comes
along when you source wt: wt <Tab> offers the subcommands, and wt cd,
wt log, and wt rm complete this repo's worktree names. In zsh, wt has to
be sourced after compinit has run (oh-my-zsh and most plugin managers do
that for you).
wt rm is careful: it refuses while setup is still running, git worktree remove refuses on uncommitted changes, and the branch is only deleted after
the worktree is gone.
Worktrees are named after the branch with / flattened to -
(feat/login becomes ~/worktrees/myrepo/feat-login), PR checkouts as
pr-<n>.
How it compares
Good worktree managers exist; wt's niche is being the smallest one whose worktrees come up ready to work in. Against the tools you'd most likely evaluate instead:
- gwq (Go) manages worktrees across all
your repos ghq-style, with a fuzzy finder, tmux integration, a status
dashboard, and
copy_files/setup_commandshooks in TOML. As a binary it can't move your shell:gwq cdopens a new shell by default, and changing the current one means enabling its shell-integration layer. - phantom (Node) covers post-create
file copying and commands via
phantom.config.json, plus fzf, tmux, and an MCP server so agents can drive it. You enter worktrees through a subshell (phantom shell) rather than acd. - wtp (Go) is the closest in spirit:
.wtp.ymlhooks copy.envfiles, symlinknode_modules, and run installs after create. Navigation works once you addeval "$(wtp shell-init zsh)"to your rc. - Worktrunk (Rust; also installs as
wt) goes much further: an agent per worktree, LLM commit messages, CI status inwt list, a one-command squash-merge flow. A full workbench, with the footprint of one.
Two deliberate differences:
- wt is the shell integration, not a binary behind one. A child process
can't
cdits parent shell, which is why each tool above ships a wrapper function, eval hook, or subshell on top of the binary. wt skips the binary: it's ~100 sourced lines, sowt feature-xlands your actual shell in the new worktree. And instead of a TOML/JSON/YAML schema, configuration is two environment variables and one script. - Setup never blocks your prompt. gwq, phantom, and wtp run their
post-create hooks in the foreground: creation finishes when
npm installdoes. wt backgrounds the setup script, logs to<worktree>.setup.log, and notifies you when it's done, so you (or your agent) start working immediately. And because setup is a plain script rather than config keys, it can do anything your repo needs. wt even ships a Claude Code skill that inspects your repo and writes the script for you.
Comments