Skip to content

sahil87/wt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

113 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wt

Part of the shll toolkit — see all projects there.

Latest release Downloads Stars

A small CLI that wraps git worktree with opinionated defaults: worktrees are created as siblings of the main repo (<repo>.worktrees/<name>/), names are memorable random adjective-noun pairs, and a shell wrapper makes cd-into-worktree from a menu actually work. Designed for the parallel-edit workflow where each branch (or each AI session) gets its own checkout.

Install

curl -fsSL https://shll.ai/install | sh -s -- wt

Installs wt (plus the shll meta-CLI) via Homebrew, handling tap trust automatically. To install the entire shll toolkit instead:

curl -fsSL https://shll.ai/install | sh

Why wt?

  • Sibling layout, not clutter — worktrees go in <repo>.worktrees/<name>/, never inside the main repo.
  • Memorable names — random adjective-noun pairs (lively-otter, bold-fox) instead of feature-1, feature-2.
  • Real cd from a menu — the shell wrapper lets wt open actually change your shell's directory (something a plain binary can't do).
  • Per-worktree init — each new worktree runs an init script (default fab sync, override via WORKTREE_INIT_SCRIPT) so it's ready to use immediately.

Other ways to install

Manual (requires Go and just):

git clone https://github.com/sahil87/wt
cd wt
just local-install   # builds bin/wt and copies to ~/.local/bin/wt

For the "Open here" menu option to actually cd your current shell, add the wrapper to your shell profile:

eval "$(wt shell-init zsh)"     # in ~/.zshrc
eval "$(wt shell-init bash)"    # in ~/.bashrc

💡 Have other shll tools? shll shell-install handles all of their shell integrations and autocompletions at once.

For the full install guide — every path, the shell wrapper, and cross-tool setup — see the install guide.

Usage

A typical first session:

$ wt create
Created: ../wt.worktrees/lively-otter
  Branch: lively-otter (from main)

$ wt list
Worktrees for: wt
Location: /Users/you/code/wt.worktrees

  Name          Branch         Path
* (main)        main           wt/
  lively-otter  lively-otter   wt.worktrees/lively-otter/

$ wt open lively-otter        # menu → "Open here" cd's your shell
$ wt delete lively-otter      # removes worktree (and optionally the branch)

Command reference

Command Summary
wt create [branch] (alias wt new) Create a worktree on a new branch (random name, or the named positional). Key flags: --checkout <branch> (existing branch), --base <ref>, --reuse, --name/-n, --non-interactive.
wt list (alias wt ls) List all worktrees with name, branch, and path. Add --status for dirty/unpushed indicators; --path and --json for scripting.
wt open [name|path] Open a worktree — or any directory — in a detected app (editor, terminal, file manager). No arg opens the current context; --app/-a skips the app menu.
wt go [name] Pick a worktree (menu or by name) and cd there via the shell wrapper. --open launches the selection instead (menu with --open prompt).
wt delete [names...] (alias wt rm) Delete one or more worktrees with optional branch cleanup.
wt init Run the worktree init script (default fab sync, override via WORKTREE_INIT_SCRIPT).
wt shell-init <shell> Print a shell wrapper function (zsh or bash) for eval in your shell profile.
wt skill Print the agent usage bundle — a static, one-page markdown briefing for an agent operating wt (offline, embedded, versioned with the binary).

Run wt <command> --help for inline flag details. For every flag and exit code, see the auto-generated command reference; for the --base start-point rules and the wt open launcher matrix, see the workflows guide.

wt create --base — branch start-point

--base <ref> controls the start-point when wt creates a new branch (maps to git worktree add -b <branch> <path> <start-point>). Behavior depends on whether the branch already exists:

Scenario --base Behavior
New branch (doesn't exist locally or remotely) provided Branch created from --base ref
New branch omitted Branch created from HEAD (default)
Positional names an existing branch (local or remote) either Error (exit 2): the positional only creates new branches — use --checkout <branch>
With --checkout <branch> provided Error (exit 2): --base sets a new branch's start-point; --checkout targets an existing branch
Exploratory (no branch arg) provided Exploratory branch created from --base ref
Exploratory omitted Branch created from current HEAD (default)
With --reuse (worktree exists) provided --reuse takes precedence; --base has no effect
Invalid ref provided Error exit; no worktree or branch created

To put a worktree on an existing branch (local or remote), opt in explicitly with --checkout <branch> — e.g. wt create --checkout sockets-v2. A remote-only branch is fetched first; a branch that exists nowhere is an error pointing you back at the positional/--base form.

The ref is validated via git rev-parse --verify before worktree creation, so invalid refs produce a clear error rather than a partial failure.

wt open and wt go — launcher and selector

The two commands split along two axes — selection (which directory) and action (navigate vs. launch). Each menu lives in exactly one verb: wt go owns the "which worktree?" menu, wt open owns the "which app?" menu. Compose them with wt go --open:

Invocation Worktree menu? App menu? Result
wt go yes no cd to selection
wt go frosty-fox no no cd directly
wt go --open prompt yes yes launch selection in chosen app
wt go --open code yes no launch selection in VS Code
wt open no yes launch current dir (worktree root / repo root / cwd)
wt open <name|path> no yes launch that dir
wt open --app code no no launch current dir in VS Code

wt open is the canonical directory launcher in the toolkit (hop delegates to it too): no arg opens the current context, a name resolves against this repo's worktrees (requires a git repo), and a path opens literally — git context doesn't matter. The app menu lists the apps wt detected on your machine (editors, terminals, file managers) plus an "Open here" option that cds your current shell into the target — that one needs the shell wrapper (see Gotchas).

Picking a worktree and launching it, with two worktrees on disk:

$ wt go --open prompt
Select worktree to open:
  1) main (main)
  2) lively-otter (feature/spinner) (default)
  3) bold-fox (fix/race-condition)
  0) Cancel

Choice [2]: 2
Open in:
  1) Open here
  2) VSCode (default)
  3) Cursor
  4) Ghostty
  5) Terminal.app
  6) Finder
  7) Copy path
  0) Cancel

Choice [2]:

Pick 1 to cd your shell into the worktree, 26 to launch it in a detected app, or 7 to copy the absolute path to your clipboard.

Gotchas

  • wt open can't cd without the shell wrapper. A child process can't change its parent shell's directory — that's a Unix constraint, not a wt bug. eval "$(wt shell-init zsh)" (or bash) installs a shell function that wraps the binary so the "Open here" menu option actually works.
  • The wt create positional never checks out an existing branch. Naming a branch that already exists (locally or on the remote) is an error (exit 2) — checkout of an existing branch is an explicit opt-in via --checkout <branch>. --reuse takes precedence over --base.
  • Worktrees survive cd into deleted directories. If you delete a worktree from outside (rm -rf), run git worktree prune in the main repo to clean up git's bookkeeping.

About

Git worktree CLI for parallel-edit workflows — sibling layout and shell-integrated navigation

Topics

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages