Skip to content
gwmgwmgwmv1.10.0
Git Worktree Managerv1.10.0

gwm

Manage your git worktrees anywhere, from the CLI or the TUI.

  • CLI + TUI
  • libgit2
  • .gwm.toml
  • TOFU trust
  • JSON + daemon
brew install kbrdn1/tap/gwm

gwm creates one isolated worktree per branch in a single command, following the <type>/#<issue>-<desc> convention, and prepares each one through a bootstrap described in .gwm.toml. One branch is one physical directory: its own target/, its own dependencies, its own local config. Nothing is stashed, nothing is rebuilt on every switch.

It is a single self-contained binary. Worktree operations run on vendored libgit2, so there is no shell-out to parse and no gwq to install first.

Terminal window
# Homebrew
brew install kbrdn1/tap/gwm
# Prebuilt archives, no Rust toolchain
cargo binstall gwm-cli
# From crates.io
cargo install gwm-cli

macOS · Linux · Windows · single self-contained binary · MIT OR Apache-2.0 · eleven install channels →

gwmTUI
The gwm TUI listing five worktrees of a repo, with the status sidebar showing the selected worktree's branch, diff, linked issue and recent commits
Five worktrees of one repo, their branch, their state, and the selected one broken out in the sidebar - branch, diff, linked issue, working tree, commits.

Bare gwm opens the list. Everything else is one key away: / filters, 2 focuses the sidebar, n creates, N writes the worktree’s note, L drops into lazygit, O opens it fullscreen at the worktree - a shell by default, your editor or a file browser if [tui.open] says so.

gwm › :Palette
The gwm command palette open over the worktree list, fuzzy-filtering the registered actions on the string work
Or address the same actions by name: : opens the palette, every list-view verb is in it, and every one of them is rebindable.

Every pane is documented in the TUI guide, from the keybindings to the command palette and the theme presets.

One command per worktree

gwm create feat 12 my-feature opens the feat/#12-my-feature branch, its worktree, and runs the repo’s bootstrap. gwm remove takes it all back down, with --dry-run if you want to look first.

gwm create feat 1 health-check --allow-bootstrapCLI
Terminal output: gwm init writes a .gwm.toml from the rust preset, then gwm create opens the feat/#1-health-check branch, its worktree, and prints the bootstrap report
From an empty repo to a bootstrapped worktree - and the bootstrap says exactly what it did, hook by hook.

Bootstrap that belongs to the repo

.gwm.toml describes branch conventions, file copies, regex guards, no-symlink invariants and lifecycle hooks. Everyone who clones gets the same worktrees, and a TOFU trust ledger asks before running anything.

gwm create feat 4 stripe-gatewayTrust
gwm printing the full bootstrap surface of an untrusted .gwm.toml - path, origin, hash, the copies and commands it would run - then asking to trust it
An untrusted .gwm.toml shows its whole surface - every copy, every command - before a single one runs.

The issue and the PR, in the worktree

A branch named feat/#42-… links itself to issue #42 with zero config, gh or glab fetches the live state, and the detected PR lands next to it - title, state, CI. It lives in git config, per branch, so it survives a move and is never committed.

gwm statusGitHub
The gwm sidebar showing an auto-linked issue and a gh-detected open pull request with its CI status
Issue auto-linked from the branch name, PR detected, CI running 8/9 - without leaving the list.

A TUI when the CLI is not enough

Bare gwm opens a ratatui interface: filter, status sidebar, embedded lazygit and shell overlays, a command palette, and a keymap you can rebind live from the settings panel.

gwm › zLayout
The gwm TUI in its side-by-side layout, the status sidebar on the left and the worktree list on the right
z cycles the layout auto → side-by-side → stacked, v flips the sidebar left ↔ right. Space marks rows instead, for a batch delete behind one confirm.

Built for scripts too

--format=json on list, doctor and path with frozen schemas, plus a JSON-RPC daemon with a subscribe stream. gwm statusline renders a one-line summary for tmux, starship or a zsh prompt.

gwm doctorCLI
gwm doctor output: eight checks, each passing, with the detail line under it
Same checks in --format=json, with a frozen schema and an exit code you can branch on.

Fleet chores across worktrees

gwm exec -- cargo test runs a command in every worktree with a per-worktree rollup, and gwm clean reports reclaimable build directories before deleting anything.

Which AI agent works where

Claude Code, Codex, opencode and Mistral Vibe are read from the session files they already write to disk - no process scan, Windows included - and land in an AGENT column, in the sidebar, and in an overlay on a. Pin a session by hand when detection can’t know.

gwm › aAgents
The gwm agent sessions overlay: one row per session with its agent, freshness, last activity and name
Active under five minutes, idle past it - and a session untouched for thirty days is not even scanned.

Colours are role-based, not hard-coded: focus, dirty, clean, branch and the rest each take a colour, and four presets ship in the binary.

preset = "claude-dark"Theme
The gwm TUI rendered with the claude-dark preset
preset = "catppuccin"Theme
The gwm TUI rendered with the catppuccin preset
preset = "gruvbox"Theme
The gwm TUI rendered with the gruvbox preset
preset = "tokyo-night"Theme
The gwm TUI rendered with the tokyo-night preset

Set one in .gwm.toml, override any single role on top of it - see Themes.

herdr is a terminal multiplexer, and herdr-plugin-gwm drives gwm from inside it: create, switch, remove, materialise a PR with gwm review, exec and clean across worktrees, plus gwm’s own TUI in a pane.

gwm stays the single source of truth. The plugin never creates a worktree on the herdr side - it adopts what gwm produced and closes the reflection when gwm removes it, so the two can’t drift apart.

Terminal window
herdr plugin install kbrdn1/herdr-plugin-gwm

herdr ≥ 0.7.4 · gwm on PATH · jq · fzf · macOS · Linux · MIT · every action, in detail →

Every page on this site is generated from the docs/ tree inside the repo - the same tree that travels with the code and the releases. The docs and the binary they describe cannot drift apart.