A tiny CLI that collects your git worktrees into one central directory and creates them from the latest default branch with readable random names. The directory name and branch name match, so commands can refer to a worktree by that name. Inspired by the worktree flow in the GitHub Copilot app.
go install github.com/fannheyward/wk@latestRequires git on your PATH.
For wk 0 / wk 1 / wk 2 directory switching, add this Zsh function to ~/.zshrc:
wk() {
if [[ $# == 1 && ${1-} == <-> ]]; then
local wk_dir
wk_dir=$(command wk "$@") && builtin pushd -- "$wk_dir"
else
command wk "$@"
fi
}Reload the configuration with source ~/.zshrc.
The function calls the pushd builtin to switch directories and save the
previous directory on the stack. Use popd to return. command wk calls the
binary. Without the function, wk <index> prints the selected path.
Worktrees created by wk live under a global root, grouped by repo:
<root>/<repo>/<random-name>/It also recognizes the directory layout currently created by Codex:
<root>/<4-char-id>/<repo>/- root defaults to
~/worktrees; override with theWK_ROOTenvironment variable. - The directory name is a random
adjective-noun(e.g.brave-otter) and the new branch uses the same name, so the directory and branch always match. Commands refer to a worktree by its directory name. - Codex worktrees use the four-character ID (e.g.
329b) as the name accepted bywk pathandwk rm. Their branch names are independent from that ID. wk newcontinues to create only the first layout; Codex compatibility does not change existing creation behavior.
Run inside any git repository.
# Create a worktree from the latest origin/<default-branch>
wk new
# fetches origin, then creates <root>/<repo>/<random-name>
wk new --name feature-one
# creates <root>/<repo>/feature-one on branch feature-one
# List this repo's wk and Codex worktrees (index, name, branch, path)
wk ls
wk ls --verbose # include dirty/upstream/ahead/behind status
wk ls --all # across all repos; REPO column replaces the index
# Switch to a numbered worktree (requires shell integration above)
wk 1
wk 2
wk 0 # return to the source repo
# Print a worktree's absolute path (handy for pushd)
pushd "$(wk path brave-otter)"
pushd "$(wk path 329b)" # Codex worktree
# Remove a worktree directory (its branch is kept)
wk rm brave-otter
wk rm brave-otter --force # also remove when there are uncommitted changesWhen this repo has listed worktrees, the source repo appears first at index 0.
Worktree indices start at 1 and follow the displayed list order.
With no listed worktrees, wk ls prints no worktrees and wk 0 has no target.
wk ls --all shows REPO instead of the index column, also in verbose mode.
wk <index> uses the current repo's list and cannot be combined with --all.
Indices are recalculated on each call and may change when worktrees are added
or removed.
wk path <name> still resolves names, including numeric names.
wk is intentionally stateless: no config file, no registry. The source of
truth is the filesystem plus git's own worktree records. See docs/adr/ for the
architecture decisions and docs/GLOSSARY.md for terminology.
wk newmust run inside a git repo. It tries togit fetchfor the freshest start point, but works offline too: on fetch failure it warns and falls back to an existing remote-tracking or local default branch.wk new --name <name>lets you choose the directory and branch name at creation time. Names are single path segments and must also be valid git branch names.wk ls,wk path, andwk rmrecognize both directory layouts.wk rmkeeps the branch so work can be recovered; it relies on git's dirty check and refuses to delete uncommitted changes without--force.