pwt: Power Worktrees
One branch per worktree, one port per server, one stable workflow. For humans and AI agents working in parallel.
brew install jonasporto/pwt/pwt
Why pwt
- Work in parallelMultiple projects, or parallel changes within the same project. No stashing, no branch juggling.
- One stable workflowKeep one editor open, swap branches underneath it.
- No local conflictsAutomatic per-worktree ports and predictable dev servers.
- Project-aware automationSetup, servers, and custom commands defined per project in a Pwtfile.
- Background jobsReal detached daemons with logs, exit codes, and wait primitives.
- Agent-readyPorcelain output, stable exit codes, and
pwt skillfor AI-driven workflows.
See it in action
pwt create: port allocated, setup hook run, .env in place.pwt use: one stable path for your editor, branches swap underneath.pwt ports: every project on the machine, one registry.pwt jobs: background work with an exit you can wait on.One setup, every agent
Claude Code, Codex, Cursor and the rest each create worktrees their own way, and each has its own answer for the setup problem: a copy file here, a hook there, nothing at all in most. Define it once in a Pwtfile and every tool lands on the same ready checkout, with its own port, its own database and its own generated config.
- You own the definitionWhat "a ready worktree" means lives in your repository, versioned, not in four tool-specific config formats that drift apart.
- Ports across projectsAllocation is machine-wide, so two agents in two different repositories never get handed the same port.
- One inventory
pwt list,pwt portsandpwt jobsshow everything in flight, whoever created it. - Nothing to interceptWhen a tool creates a worktree on its own,
pwt adoptregisters it after the fact: port, metadata and setup, no rework.
Quick start
cd ~/projects/myapp
pwt init # Initialize project
pwt add feat/user-auth # Create worktree from branch
pwt feat/user-auth # Jump to a worktree
pwt server --bg # Start its dev server, detached
pwt list # List worktrees with git status
Install
# Homebrew
brew install jonasporto/pwt/pwt
# npm
npm i -g @jonasporto/pwt
# curl
curl -fsSL https://raw.githubusercontent.com/jonasporto/pwt/main/install.sh | bash
Pwtfile: project hooks
Think Makefile, but for the worktree lifecycle. pwt stays project-agnostic; your Pwtfile defines what setup, servers, and health mean for your stack.
PORT_BASE=5001
setup() {
pwtfile_copy ".env.local"
pwtfile_symlink ".cache"
./scripts/setup
}
server() {
case "${1:-start}" in
start) exec env PORT="$PWT_PORT" ./scripts/dev ;;
stop) ./scripts/dev-stop ;;
esac
}
Stable gateway
Each worktree gets its own port, and one stable project URL routes to whichever worktree you're testing:
pwt gateway up --port 5999
pwt gateway use feat/user-auth
open "$(pwt gateway url)"
Built for agents too
Driving pwt from an AI agent or a script? pwt skill prints the agent guide:
machine-readable output (list --porcelain, state --json), a stable
exit-code table, and wait primitives (pwt server wait, pwt jobs wait)
that replace poll loops. See also llms.txt.
From the blog
-
Is CLI ergonomics still a thing?
We type fewer commands than a year ago; the prompts got longer. What still goes into a shell is a reaction to something on screen, and that is where a CLI earns its keep.
-
zsh: no such file or directory, and source ~/.zshrc will not fix it
A shell function kept calling a binary I had deleted, and re-sourcing the rc file could not heal it, because the broken function intercepts its own repair. The mechanics, the one-line escape (unfunction), and what a tool that installs wrapper functions owes you.
-
I released the fix. My terminal ran the version from three releases ago.
npm -g does not install globally: it installs into the current node version, nvm puts that directory first on PATH, and your shell quietly answers with whatever lives there. How to see which copy of a CLI is really running, and why npx pkg@latest is the one probe nothing can shadow.
-
I timed every command in my CLI on a 95-worktree project
Four commands took over ten seconds. The fix was not making the work faster, it was taking the work off the read path. Includes the two instruments that lied to me and the command that is still slow today.
Documentation
- ConceptsWhat a worktree is here, and when pwt beats raw
git worktree. - CommandsEvery command's own
--help, generated from the binary. - Navigation
cd, aliases, partial names, multi-project. - PwtfileHooks, helpers and the
PWT_*variables. - For agentsThe guide
pwt skillprints. - FAQDesign decisions and the questions behind them.