Fuzzy-switch to any git branch across all your repos — from anywhere.
twig scans the git repos under your project directories, lists every branch
(local and remote) with fzf, then checks
out the branch you pick — creating a git worktree
if it isn't already checked out — and drops you into a dedicated
tmux session for it.
No more cd-ing between repos, stashing changes to switch branches, or losing
your place. Every branch gets its own worktree and its own tmux session.
- One picker for every repo — branches across all your projects in a single fzf list.
- Worktree-per-branch — switching branches never disturbs your working tree; each branch lives in its own directory under
~/.twig/worktrees/. - Session-per-branch — each branch opens in a named tmux session, so your layout and running processes persist.
- Local + remote branches — remote-only branches are checked out on demand; duplicates are hidden.
- Create branches on the fly —
twig newbranches off your repo's default branch (fetched first) and opens it. - tmux plugin — bind the picker to a key and drive everything without leaving tmux.
twig shells out to the following, which must be on your PATH:
Building from source requires Go 1.26+.
go install github.com/trkl-dev/twig@latestThis installs the twig binary to $(go env GOPATH)/bin (typically
~/go/bin). Make sure that directory is on your PATH:
export PATH="$PATH:$(go env GOPATH)/bin"Or build from a checkout:
git clone https://github.com/trkl-dev/twig.git
cd twig
go build ./... # or: go install .twigDiscovers every repo under your project directories, lists all
their branches in an fzf picker, and — when you select one — checks it out into a
worktree (if needed) and opens a tmux session named <repo> » <branch>.
The picker shows two columns:
REPO BRANCH (r = remote, wt = worktree)
Branch display suffixes:
| Suffix | Meaning |
|---|---|
(wt) |
branch already checked out in a worktree |
(r) |
remote-only branch (no local counterpart) |
(r), wt |
remote-only branch that has a worktree |
When a local branch and its matching origin/<name> both exist, the remote entry
is hidden.
twig newPick a repo, type a name for the new branch, and twig:
- Determines the repo's default base branch (
origin/HEAD, falling back toorigin/main,origin/master, the current branch, thenHEAD). - Fetches that base concurrently while you type.
- Validates the branch name with
git check-ref-format. - Creates the branch off the base in a new worktree — or switches to it if a
branch by that name already exists locally or on
origin. - Opens a tmux session for it.
By default twig scans these directories for repos (walking up to 5 levels deep):
$HOME/Projects$HOME/dotfiles
These are defined in cmd/root.go (ProjectDirs and MaxDepth). Adjust them to
match your layout and rebuild.
Worktrees are created under:
~/.twig/worktrees/<repo>/<branch>
Slashes in branch names are replaced with dashes (e.g. feat/login →
feat-login).
| Variable | Effect |
|---|---|
TWIG_DEBUG |
Set to any non-empty value to enable slog debug logging (timings, discovery, and a performance summary). |
TMUX |
Detected automatically. Inside tmux, twig uses switch-client and fzf's popup; outside, it attaches and draws a bordered fzf. |
twig ships as a TPM-compatible tmux
plugin so you can launch the pickers from a keybinding.
Add to your tmux.conf:
set -g @plugin 'trkl-dev/twig'Then press prefix + I to install.
| Key | Action |
|---|---|
prefix + g |
Pick a branch across repos (fzf popup) |
prefix + N |
Create a new branch (fzf popup) |
prefix + K |
Pick session(s) to kill (tab = multi) |
The plugin looks for the binary at $HOME/go/bin/twig. Override it with:
set -g @twig_binary '/custom/path/twig'WalkDir finds .git dirs → concurrent `git branch -a` (with worktree detection)
→ filter/dedup → fzf → ensureWorktree (checkout or create) → openTmux (create/attach)
- Discovery walks each project directory with
fs.WalkDir, treating any directory containing a.gitdirectory as a repo (worktree.gitfiles are skipped so worktrees aren't listed as separate repos). - Branch listing runs
git branch -aper repo in parallel, using a git format string to detect which branches have active worktrees. - Worktree handling reuses an existing worktree if the branch is already
checked out; otherwise it creates one (remote branches get
-b <local> <remote-ref>). - tmux creates a detached session (name-sanitized so
.and:become-), then switches to it if you're inside tmux or attaches if you're not.
See AGENTS.md for a deeper architecture reference.
See LICENSE.