Skip to content

Latest commit

 

History

244 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

worktree-tool

worktree-tool logo

CI License: Apache-2.0

A native GUI for managing git worktrees, built in Rust with GPUI (Zed's GPU-accelerated UI framework).

Website, tutorials, and examples →

Lists every worktree of a repository with its branch, status (dirty files, ahead/behind vs upstream), and offers create / remove / prune operations plus quick actions (open in terminal, show in file manager, copy path). Keyboard-first.

worktree-tool showing three worktrees with clean, dirty, and ahead statuses

Install

Prebuilt packages for every platform are attached to each GitHub Release (built by CI on native runners):

Platform Package
macOS (universal arm64 + x86_64) …-macos-universal.dmg — open and drag Worktree Tool onto Applications (a plain .app zip is attached too)
Linux x86_64 / aarch64 …-linux-<arch>.tar.gz — extract the binary; runtime deps are libxcb, libxkbcommon(+x11) and a Vulkan stack (standard on any desktop)
Windows x86_64 …-windows-x86_64.zip — extract and run worktree-tool.exe
FreeBSD x86_64 …-freebsd-x86_64.tar.gz — runtime needs libxcb/libxkbcommon from ports and LD_LIBRARY_PATH=/usr/local/lib

The macOS build is ad-hoc signed, not notarized — on first launch Gatekeeper may ask you to confirm via right-click → Open. When launched from Finder the app starts at the path picker (there is no terminal cwd to detect); when run from a terminal it auto-detects the repository from the working directory.

To package locally: scripts/package-macos.sh 0.1.0 produces dist/Worktree Tool.app and the zip.

Platform support

Platform Status
macOS (Apple silicon / Intel) built, tested, and manually verified
Linux (X11 / Wayland) compiles and unit-tested via CI; rendering uses Vulkan through blade-graphics, linking needs libxcb, libxkbcommon, libxkbcommon-x11, libstdc++
Windows compiles and unit-tested via CI (MSVC toolchain)
FreeBSD compiles via CI (GPUI gates its X11/Wayland backend to linux + freebsd); least-tested platform

CI (.github/workflows/ci.yml) runs clippy, tests, and a release build on macOS, Linux, Windows, and FreeBSD on every push once a remote is added. For local cross-checks without target hardware: cargo zigbuild --target x86_64-unknown-linux-gnu --lib (also x86_64-pc-windows-gnu, x86_64-unknown-freebsd) — every crate compiles cross-platform; only the final Linux binary link needs native X11 libraries.

Requirements

  • Stable Rust toolchain
  • git on your PATH
  • macOS: Xcode command line tools (xcode-select --install) for the Metal backend
  • Linux: the X11/xkbcommon dev packages above plus a Vulkan-capable driver stack

Usage

Run from inside any git repository — the app detects the repo from the current working directory:

cd ~/git/myrepo
cargo run --release

For step-by-step tutorials (first worktree, terminal setup, cleanup) and example workflows (hotfix mid-feature, PR review checkouts, parallel test runs), see the website.

Shortcuts

Key Action
n / cmd-n New worktree
/ Focus search
r / cmd-r Refresh
up / down Move selection
enter Open selected worktree's detail view
t Open in terminal
backspace / delete Remove selected worktree
esc Clear search / close dialog / back to worktree list

Detail view (per worktree):

Key Action
1 / 2 / 3 Switch section: Working Copy ↔ History ↔ Branches
up / down Move file selection (diff pane focused: move hunk cursor)
tab Toggle file list ↔ diff pane
s Stage / unstage selected file (diff pane focused: stage hovered hunk)
S Stage all remaining changes
d Discard selected file's changes (confirmation)
c Commit staged changes via your editor
g Continue the paused merge / rebase / cherry-pick / revert
K Skip the current step (paused rebase / cherry-pick)
A Abort the paused operation, restoring the pre-operation state
t Open worktree in terminal
r Refresh working copy
esc Back to worktree list

History section (2 from the detail view):

Key Action
up / down Move commit selection (files pane focused: move file selection)
tab Toggle commit list ↔ commit files
y Copy the selected commit's full hash to the clipboard
x Check out the selected commit (detached; refused while the working copy has changes)
p Cherry-pick the selected commit onto this branch
v Revert the selected commit (creates a revert commit)
R Interactive rebase from the selected commit to HEAD — pick/drop/fixup rows in the dialog
w Open a new worktree at the selected commit
L Load 500 more commits
r / t / esc Refresh / terminal / back — same as the Working Copy section

Branches section (3 from the detail view):

Key Action
up / down Move the cursor in the active list (branches or stashes)
tab / s Toggle between the branch list and the stash list
enter / x Switch to the selected branch (refused on a dirty working copy)
m Merge the selected branch into the current branch
R Rebase the current branch onto the selected branch
d Delete the selected branch (refuses the current branch)
n Create a new branch at HEAD
M Rename the selected branch
y Copy the selected branch name to the clipboard
z Stash the working copy's changes (tracked + untracked)
p / a Pop (apply + drop) / apply the selected stash
D Drop the selected stash
f Fetch all remotes (with prune)
u Push the current branch (sets upstream on first push)
l Pull the current branch (fast-forward only)
F Force-push the current branch with lease — press twice to confirm
r / t / esc Refresh / terminal / back — same as the Working Copy section

Remote-tracking branches (origin/…) are listed after the locals; switching and deleting refuse them, and merging/rebasing from them works. A conflicted merge or rebase pauses (see Working Copy above): resolve and press g in the Working Copy section, or A to back out.

Working Copy

Press enter on a worktree to drill into it. Changes are grouped into Conflicts, Staged, Unstaged, and Untracked; the diff pane shows the selected file's unified diff. Stage or unstage with s (all at once with S), and discard a file's unstaged changes or an untracked file with d — always with a confirmation. Discarding the unstaged part never touches staged changes.

With the diff pane focused, / move a cursor between the file's hunks and s stages just the hovered hunk (git apply --cached — the worktree file is never touched). Binary and untracked files stage whole-file only.

Press c to write a commit: the app opens your editor exactly like git commit does, resolving it in git's own order — $GIT_EDITOR, core.editor, $VISUAL, $EDITOR, then a platform default. Save a message to commit; empty the message to abort. Conflicted files show their raw content — resolve them in your own editor, then press s to mark them resolved.

A conflicted merge, rebase, cherry-pick, or revert pauses instead of backing out: a banner names the operation (with rebase progress, e.g. "rebasing 2/5"), and the paused state is real git state — other git clients see it too. Resolve the files in your own editor, stage with s, then g continues with the stored message (no editor round trip). K skips the current step of a rebase or cherry-pick; A aborts and restores the pre-operation state. While paused, mutating actions in the other sections (branch switch, history checkout) refuse until you continue or abort.

Settings

The Settings button (toolbar) lists the terminals detected on this machine; clicking one persists the choice immediately. The config file lives at an XDG path on every platform:

$XDG_CONFIG_HOME/worktree-tool/settings.toml   # e.g. ~/.config/worktree-tool/settings.toml
# worktree-tool settings
# terminal: one of the ids below (or unset for auto-detect)
terminal = "iterm"

Terminal resolution order: settings.toml$TERMCMD env var (app name, Zed convention) → first detected terminal.

Report a bug (Settings → Report a bug) opens a prefilled GitHub issue in your browser. It includes only the app version and platform — nothing else is collected, and you review it before submitting. CLI terminals launch with the worktree as their working directory; Windows Terminal gets an explicit -d flag because its profiles override the inherited directory.

Supported terminals (auto-detected; the settings dialog only lists installed ones):

Platform Terminals, in auto-detect preference order
macOS Terminal, iTerm2, WezTerm, Ghostty, Alacritty, Kitty, Warp, Hyper
Linux / BSD xdg-terminal-exec, GNOME Terminal, Konsole, Xfce Terminal, foot, Tilix, Kitty, Ghostty, Alacritty, WezTerm, xterm
Windows Windows Terminal, PowerShell (7), Windows PowerShell, Command Prompt, Alacritty, WezTerm, Ghostty

Development

cargo build        # first build takes a few minutes (shader compilation)
cargo test         # unit + git integration tests
cargo clippy -- -D warnings

Building for any target — native or cross (Windows .exe from macOS, Linux via Docker, FreeBSD, any Rust triplet) — is wrapped by:

scripts/build-target.sh <target>   # host | macos-universal | x86_64-pc-windows-gnu | …

See docs/BUILDING.md for the full per-platform guide and the measured cross-compilation matrix.

Note: text inputs accept raw key events; IME/marked-text input is not supported in v1.

License

Apache-2.0 — see LICENSE.

About

A native GPUI (Rust) GUI for managing git worktrees — macOS, Linux, Windows, FreeBSD

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages