8000 GitHub - gugahoi/wt: Git worktree manager with fzf pickers and tmux/Rex sessions · GitHub
[go: up one dir, main page]

Skip to content
gugahoiPublic

About

Git worktree manager with fzf pickers and tmux/Rex sessions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

wt

wt is a Git worktree manager for the terminal. It picks branches, GitHub issues, and pull requests with fzf, creates worktrees on demand, and opens each one in its own tmux, Zellij, or Rex session, or with a command of your own.

Install

brew install gugahoi/tap/wt

Or download the binary for your platform (macOS or Linux, arm64 or amd64) from the latest release and put wt on your PATH.

wt is a single binary with fzf built in. It runs git, and tmux, Zellij, or Rex to open sessions. wt issue and wt pr log in to GitHub with GH_TOKEN, or with gh if it's installed and logged in.

Usage

wt - Git Worktree Manager with tmux, Zellij and Rex integration

Usage:
  wt                  Interactively select a branch to switch to (creating worktree if needed)
                      - Press [Ctrl-x] inside the selection menu to delete the worktree and branch
                        (local deletions run in the background; remote-only entries require confirmation)
  wt issue [number]   Pick an open GitHub issue (newest first), or take the numbered one, and switch to (or create)
                      a <number>-* branch for it
  wt pr [number]      Pick an open GitHub pull request (ready first, then drafts; newest first), or take the
                      numbered one, and switch to its branch
                      - Press [Ctrl-t] inside either picker to switch between issues and pull requests
  wt clone <url> [dir] Clone a repository as bare and set up worktrees
  wt rm | delete      Interactively select a worktree to remove (with a confirmation prompt)
  wt list             List all active worktrees
  wt -h | --help      Show this help documentation

GitHub (wt issue, wt pr):
  The repository is the one gh would use (GH_REPO, or the git remotes). The token comes from GH_TOKEN or
  GITHUB_TOKEN, or else from gh's login (gh auth login).

Multiplexer (WT_MULTIPLEXER=auto | tmux | zellij | rex | command):
  auto, the default, opens worktrees in the first multiplexer wt runs inside: tmux ($TMUX), Zellij ($ZELLIJ),
  then Rex ($REX_SESSION, confirmed with the Rex server); otherwise in tmux, creating or attaching its
  session. tmux or Zellij inside Rex picks them; set WT_MULTIPLEXER=rex for Rex. A picked multiplexer that
  fails is reported, never swapped for another, and the worktree it was opening is kept.
  tmux     One session per branch, named after it; the same branch in two repositories shares one.
  zellij   One session per worktree, labelled <repo>-<branch>-<path hash> cut to at most 24 bytes, fewer
           when Zellij's socket folder is long, so the socket path fits; a renamed session is no longer
           reused. Switching sessions from inside Zellij, and opening a command (even outside Zellij), need
           zellij 0.44 or later; a session created for a command has it in its first tab from 0.45.1, and
           a shell tab first before.
  rex      Needs rex (without it, auto picks tmux even inside Rex). One session per worktree,
           labelled <repo>-<branch>-<path hash>; a renamed session is no longer reused.
           When several Rex apps are connected, wt asks which one to show the worktree in;
           Esc cancels without creating a worktree. REX_CLIENT selects an app by label or ID
           (see `rex client ls`) without asking; set it when running without an interactive terminal.
  command  Runs WT_OPEN_COMMAND with sh, in the worktree and wt's terminal, with WT_WORKTREE (its path),
           WT_BRANCH, WT_SESSION (a <repo>-<branch>-<path hash> label) and WT_COMMAND (the command to run
           there, empty to open a shell) set. Never picked by auto.
  Deleting a worktree leaves its session running, and a worktree recreated at the same path reuses it.

Commands ($XDG_CONFIG_HOME/wt/config.json, or ~/.config/wt/config.json):
  {"default_command": "claude", "keymaps": {"ctrl-a": "claude", "ctrl-o": "opencode"}}
  Enter opens the picked worktree with default_command, and a key in keymaps (an fzf key name) with its
  command, in the pickers of wt, wt issue and wt pr; wt clone opens with default_command. In tmux, Zellij
  and Rex a command runs with /bin/sh -c in the worktree, in a new window (in Zellij, tab) of the
  worktree's session, or in the first window of a new one; with no command, wt opens a shell, reusing the
  session. WT_MULTIPLEXER=command passes it in WT_COMMAND. Enter, Esc, Ctrl-C, Ctrl-G, Ctrl-X and Ctrl-T
  can't be mapped.

Setup (git config wt.setupCommand):
  git config wt.setupCommand 'pnpm install' sets a command wt runs in every worktree of the repository it
  creates (wt, wt issue and wt pr), before opening it; --global sets it for every repository, wt clone
  included, and an empty value in a repository turns a global one off. It runs with /bin/sh -c in the
  worktree and wt's terminal, with WT_WORKTREE and WT_BRANCH set. When it fails, wt reports it and keeps
  the worktree unopened; a worktree that exists already isn't set up again. On a pull request's branch,
  an install command runs that branch's install scripts.

Other multiplexers

WT_MULTIPLEXER=command opens worktrees with any tool that has a command line. Pass the worktree through the variables, never by pasting it into the command, so that branch names stay data. WT_COMMAND is the command to open it with, a shell snippet for sh -c, or empty to open a shell; it's always set, so that an inherited one is never taken for it, and it's data too: run it as /bin/sh -c "$WT_COMMAND", never pasted into the command. The examples that don't use it open a shell whatever the command:

export WT_MULTIPLEXER=command

# a tmux window rather than a session, running the command when there is one
export WT_OPEN_COMMAND='tmux new-window -n "$WT_BRANCH" -c "$WT_WORKTREE" ${WT_COMMAND:+/bin/sh -c "$WT_COMMAND"}'

# a WezTerm workspace (a new window each time: wezterm cli can't switch to an existing one)
export WT_OPEN_COMMAND='wezterm cli spawn --new-window --workspace "$WT_SESSION" --cwd "$WT_WORKTREE"'

# a kitty tab (needs allow_remote_control in kitty.conf)
export WT_OPEN_COMMAND='kitten @ launch --type=tab --tab-title "$WT_BRANCH" --cwd "$WT_WORKTREE"'

Setting up in the background

wt waits for wt.setupCommand to finish before it opens the worktree, but only for its sh -c to exit, so a command that puts the setup in the background lets the worktree open straight away. set -m starts it in a process group of its own, which keeps it running when wt's terminal closes, as a tmux popup does when wt exits; nohup doesn't, for Node tools such as pnpm, which undo it. Its input is /dev/null, so that it never stops waiting on the terminal, and its output goes to a log in the worktree's git folder, where it isn't an untracked file:

git config wt.setupCommand 'set -m; pnpm install </dev/null > "$(git rev-parse --git-dir)/wt-setup.log" 2>&1 &'

# what it printed, from the worktree
cat "$(git rev-parse --git-dir)/wt-setup.log"

wt can't tell then whether the setup worked, and the worktree opens before it's finished: a command that needs it, such as a dev server, can start too early.

Development

go test ./...
go build

The tests need git; tmux, Zellij, and Rex are stubbed.

Releasing

git tag vX.Y.Z && git push origin vX.Y.Z

Or run the Release workflow from the Actions tab with a tag. It builds the binaries with scripts/build-release.sh, attaches them to the GitHub Release, and writes Formula/wt.rb in gugahoi/homebrew-tap with scripts/write-formula.sh.

About

Git worktree manager with fzf pickers and tmux/Rex sessions

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0