|
| 1 | +# wt |
| 2 | + |
| 3 | +A fast CLI for managing git worktrees. One command to create a branch, set up the worktree, and `cd` into it. |
| 4 | + |
| 5 | +```bash |
| 6 | +wtb feature-x # creates branch + worktree and cd's into it |
| 7 | +``` |
| 8 | + |
| 9 | +Git worktrees let you work on multiple branches simultaneously without stashing or cloning, but the built-in commands are verbose. `wt` stores all worktrees in `~/.local/share/wt/<repo>/<branch>` and lets you jump between them from anywhere. It also includes optional Docker integration to spin up isolated containers per worktree, with built-in support for running [Claude Code](https://claude.ai/code) inside them. |
| 10 | + |
| 11 | +## Quick Start |
| 12 | + |
| 13 | +### Prerequisites |
| 14 | + |
| 15 | +- **OCaml >= 4.14** and **opam** (OCaml package manager) |
| 16 | +- **Git** |
| 17 | +- **Docker** (optional, for containerized development) |
| 18 | + |
| 19 | +If you don't have OCaml installed: |
| 20 | + |
| 21 | +```bash |
| 22 | +# macOS |
| 23 | +brew install opam |
| 24 | +opam init |
| 25 | +eval $(opam env) |
| 26 | + |
| 27 | +# Ubuntu/Debian |
| 28 | +sudo apt install opam |
| 29 | +opam init |
| 30 | +eval $(opam env) |
| 31 | +``` |
| 32 | + |
| 33 | +### Install |
| 34 | + |
| 35 | +```bash |
| 36 | +git clone https://github.com/cristeahub/wt.git |
| 37 | +cd wt |
| 38 | +opam install . --deps-only |
| 39 | +./install.sh |
| 40 | +``` |
| 41 | + |
| 42 | +The install script will: |
| 43 | + |
| 44 | +1. Build the project with `dune build` |
| 45 | +2. Install the `wt` binary to `~/.local/bin/` |
| 46 | +3. Copy Docker files to `~/.local/share/wt/docker/` |
| 47 | +4. Optionally add the `wtb` shell function and tab completion to your `.zshrc` |
| 48 | + |
| 49 | +Make sure `~/.local/bin` is in your `PATH`: |
| 50 | + |
| 51 | +```bash |
| 52 | +export PATH="$HOME/.local/bin:$PATH" |
| 53 | +``` |
| 54 | + |
| 55 | +## Usage |
| 56 | + |
| 57 | +### Create or navigate to a worktree |
| 58 | + |
| 59 | +```bash |
| 60 | +wt b feature-x # creates branch + worktree, prints path |
| 61 | +wtb feature-x # same, but also cd's into it (requires shell function) |
| 62 | +``` |
| 63 | + |
| 64 | +If a worktree for the branch already exists (in any repo), `wt b` navigates to it. Otherwise it creates a new branch and worktree from the current repo. |
| 65 | + |
| 66 | +When the same branch name exists in multiple repos, an interactive picker appears: |
| 67 | + |
| 68 | +``` |
| 69 | +Branch 'feature-x' exists in multiple repos: |
| 70 | +
|
| 71 | +> myapp -> /home/you/.local/share/wt/myapp/feature-x |
| 72 | + mylib -> /home/you/.local/share/wt/mylib/feature-x |
| 73 | +
|
| 74 | +(arrow keys navigate, Enter select, q cancel) |
| 75 | +``` |
| 76 | + |
| 77 | +### Delete a worktree |
| 78 | + |
| 79 | +```bash |
| 80 | +wt d feature-x # removes worktree, keeps the branch |
| 81 | +wt db feature-x # removes worktree AND deletes the branch |
| 82 | +``` |
| 83 | + |
| 84 | +### List all worktrees |
| 85 | + |
| 86 | +```bash |
| 87 | +wt list |
| 88 | +``` |
| 89 | + |
| 90 | +``` |
| 91 | +myrepo: |
| 92 | + feature-x -> /home/you/.local/share/wt/myrepo/feature-x |
| 93 | + bugfix_auth -> /home/you/.local/share/wt/myrepo/bugfix_auth |
| 94 | +
|
| 95 | +other-repo: |
| 96 | + main -> /home/you/.local/share/wt/other-repo/main |
| 97 | +``` |
| 98 | + |
| 99 | +## Shell Integration |
| 100 | + |
| 101 | +The `wtb` function wraps `wt b` and cd's into the result: |
| 102 | + |
| 103 | +```bash |
| 104 | +wtb() { local dir=$(wt b "$1" | tail -1); [ -d "$dir" ] && cd "$dir"; } |
| 105 | +``` |
| 106 | + |
| 107 | +The installer adds this to `.zshrc` with zsh-specific tab completion. For bash, add the function to `.bashrc` manually. Tab completion autocompletes from: |
| 108 | + |
| 109 | +- Git branches in the current repo |
| 110 | +- Existing worktree branch names from `~/.local/share/wt/` |
| 111 | + |
| 112 | +## Docker Integration |
| 113 | + |
| 114 | +`wt` can run isolated Docker containers per worktree, useful for running development tools in a consistent environment. |
| 115 | + |
| 116 | +### Setup |
| 117 | + |
| 118 | +```bash |
| 119 | +wt docker build # build the base image (Ubuntu 24.04 + Python, Node, Rust, Go) |
| 120 | +``` |
| 121 | + |
| 122 | +> **Note:** The included Dockerfile is an opinionated example that ships with PostgreSQL, multiple Python versions, Node.js, Rust, Go, and Claude Code. It's meant as a starting point — customize `~/.local/share/wt/docker/Dockerfile` (or the source `docker/Dockerfile`) to match your actual development needs. |
| 123 | +
|
| 124 | +### Per-worktree containers |
| 125 | + |
| 126 | +```bash |
| 127 | +wtb feature-x # navigate to worktree |
| 128 | +wt docker start # start a container for this worktree |
| 129 | +wt run npm install # run any command inside the container |
| 130 | +wt docker shell # open an interactive shell |
| 131 | +wt docker stop # stop the container |
| 132 | +``` |
| 133 | + |
| 134 | +Each worktree gets its own named container (`wt-<repo>-<branch>`). The worktree directory is mounted at `/workspace`. Containers are reused across sessions. |
| 135 | + |
| 136 | +### All Docker commands |
| 137 | + |
| 138 | +| Command | Description | |
| 139 | +| ------------------ | ------------------------------------ | |
| 140 | +| `wt docker build` | Build the base Docker image | |
| 141 | +| `wt docker start` | Start container for current worktree | |
| 142 | +| `wt docker stop` | Stop the container | |
| 143 | +| `wt docker shell` | Open interactive shell in container | |
| 144 | +| `wt docker status` | Show container status | |
| 145 | +| `wt docker rm` | Remove a stopped container | |
| 146 | +| `wt docker list` | List all wt containers | |
| 147 | +| `wt run <cmd>` | Run a command in the container | |
| 148 | + |
| 149 | +### Claude Code in containers |
| 150 | + |
| 151 | +The Docker image includes [Claude Code](https://claude.ai/code). To authenticate: |
| 152 | + |
| 153 | +```bash |
| 154 | +wt login # auto-extracts token from macOS Keychain, or prompts for manual entry (Linux) |
| 155 | +``` |
| 156 | + |
| 157 | +Then from any worktree: |
| 158 | + |
| 159 | +```bash |
| 160 | +wt run claude # start Claude Code |
| 161 | +wt run claude -y # start with --dangerously-skip-permissions |
| 162 | +``` |
| 163 | + |
| 164 | +Each worktree gets an isolated Claude session. The token is saved to `~/.local/share/wt/token` and injected via `CLAUDE_CODE_OAUTH_TOKEN`. |
| 165 | + |
| 166 | +## How it works |
| 167 | + |
| 168 | +### Storage layout |
| 169 | + |
| 170 | +``` |
| 171 | +~/.local/share/wt/ |
| 172 | +├── docker/ |
| 173 | +│ ├── Dockerfile |
| 174 | +│ └── entrypoint.sh |
| 175 | +├── sessions/ # per-worktree Claude config |
| 176 | +│ └── <repo>/<branch>/ |
| 177 | +├── token # Claude OAuth token (mode 0600) |
| 178 | +└── <repo>/ |
| 179 | + ├── feature-x/ # worktree directories |
| 180 | + └── feature%2Fauth/ # slashes in branch names are percent-encoded |
| 181 | +``` |
| 182 | + |
| 183 | +### Design decisions |
| 184 | + |
| 185 | +- **Centralized storage** - All worktrees live under `~/.local/share/wt/` regardless of where you invoke `wt`, so you can navigate to any branch from any directory. |
| 186 | +- **Non-destructive by default** - `wt d` only removes the worktree; the git branch is preserved. Use `wt db` to remove both. |
| 187 | +- **Container reuse** - Docker containers persist between sessions. `wt docker start` reuses an existing container if one exists. |
| 188 | +- **Session isolation** - Each worktree gets its own Claude configuration directory, so sessions don't interfere with each other. |
| 189 | + |
| 190 | +### Dependencies |
| 191 | + |
| 192 | +- [minttea](https://github.com/leostera/minttea) - TUI framework (Elm architecture) for the interactive repo picker |
| 193 | + |
| 194 | +## Building from source |
| 195 | + |
| 196 | +```bash |
| 197 | +opam install . --deps-only # install OCaml dependencies |
| 198 | +dune build # compile |
| 199 | +dune exec wt -- --help # run without installing |
| 200 | +./install.sh # build + install to ~/.local/bin/wt |
| 201 | +``` |
| 202 | + |
| 203 | +## License |
| 204 | + |
| 205 | +MIT License. See [LICENSE](LICENSE) for details. |
0 commit comments