---
title: Keybindings
description: Every key the TUI listens to — list, sidebar, filter, confirm overlay, link prompts.
---
# Keybindings
The full key map for `gwm`'s ratatui interface. Press `?` at any time for the same table as an in-app overlay.

> **The keymap is fully configurable.** Every binding below is a
> **default** — the `[tui.keys]` block in `.gwm.toml` rebinds any
> list-view action, including multi-key chords like `g g`. The `?`
> help overlay is keymap-driven, so it always renders the bindings you
> actually resolved, not these defaults. See [Keymap & command
> palette](/tui/keymap-and-palette) and
> [Configuration → `[tui.keys]`](/configuration/gwm-toml#tuikeys).
>
> **Modal keys are rebindable too.** The keys inside each overlay below are
> defaults of typed verbs under `[tui.keys.modal.<context>]`
> ([#219](https://github.com/kbrdn1/gwm-cli/issues/219)). The same physical key
> can mean different things per modal (`Enter` is `submit` in the create form
> but `activate` in the delete-confirm modal). `Ctrl+C`, the list view's
> contextual `Esc` / `Enter`, and the PTY overlay's emergency `Esc` stay
> hard-coded by design. See [Keymap & command
> palette](/tui/keymap-and-palette#rebindable-modal-keys).
> **Keymap redesign (v0.10)** — [#290](https://github.com/kbrdn1/gwm-cli/issues/290)
> reshuffled the list-view bindings into logical chords and added several
> verbs (pull / push, rename, exit-to-worktree, branch / worktree-name yanks,
> mux pane, user macros). The table below is the resolved default set printed by
> `gwm tui keys`. Pre-#290 `[tui.keys]` slugs (`git_tui`, `review`, `yank`,
> `open`, `open_menu`, …) still load through backward-compat aliases, so an
> existing override keeps working.
## list view (default)
| `↑` / `k` | previous worktree (`up`) — scrolls the sidebar when it has focus |
| `↓` / `j` | next worktree (`down`) — scrolls the sidebar when it has focus |
| `gg` | jump to the first worktree (`top`) |
| `G` / `End` | jump to the last worktree (`bottom`) |
| `n` | new worktree (`create`; form: type → issue → description) · gated by the [TOFU trust ledger](/configuration/trust-ledger) — refuses with a status-bar hint on untrusted `.gwm.toml` |
| `c` | rename the selected worktree (`edit_worktree`; form pre-filled from the current branch) — renames the local branch, the remote branch if it exists, and moves the worktree directory, all off-thread |
| `d` | delete selected (`delete`; confirm `y` · countdown when `D` is armed — see [confirm-overlay](/tui/confirm-countdown)) |
| `D` | toggle "delete branch on remove" (`delete_branch`) |
| `b` | re-run bootstrap on the selected worktree (`bootstrap`), off-thread (the statusbar spinner animates while it runs; the Report view opens when it finishes) · same [trust gate](/configuration/trust-ledger) as `n` |
| `s` | sync the selected worktree onto its upstream (`sync`) — fetch + rebase, off-thread (statusbar spinner); refuses a dirty tree / missing upstream / conflicts |
| `p` | git pull the selected worktree's branch (`pull`), off-thread (progress in the status bar) |
| `P` | git push the selected worktree's branch (`push`), off-thread |
| `f` | refresh the worktree list (`refresh`) |
| `F` | refresh the GitHub issue / PR status (`fetch_github`) — off-thread `gh` fetch, statusbar spinner |
| `e` | quit the TUI and print the selected path to stdout (`exit_to_worktree`) — enables `cd "$(gwm)"` shell patterns |
| `o` | open a native `$SHELL` in an embedded [PTY overlay](/tui/open-dispatch) at the worktree (`terminal_pty`) |
| `O` | open a native `$SHELL` fullscreen, suspending the TUI (`terminal_fullscreen`) |
| `l` | launch the configured [`[git_tui]`](/tui/launchers) command in an embedded [PTY overlay](/tui/launchers#the-embedded-pty-overlay-l--r) (`lazygit_pty`) |
| `L` | launch the configured [`[git_tui]`](/tui/launchers) command fullscreen (`lazygit_fullscreen`) |
| `r` | launch the configured [`[review]`](/tui/launchers) command in a [PTY overlay](/tui/launchers#the-embedded-pty-overlay-l--r) (`review_pty`) — AI / web reviewer over `git diff base..head` |
| `R` | launch the configured [`[review]`](/tui/launchers) command fullscreen (`review_fullscreen`) |
| `t` | open the selected worktree in a new tmux / zellij pane (`mux_pane`) — falls back to a status-bar hint when no multiplexer is detected |
| `h` | run the user-configured [`[tui.macro1]`](/configuration/gwm-toml#tuimacro1-and-tuimacro2) command (`macro_one`) |
| `H` | run the user-configured [`[tui.macro2]`](/configuration/gwm-toml#tuimacro1-and-tuimacro2) command (`macro_two`) |
| `y` | yank the selected worktree's **branch name** to the clipboard (`yank_branch_name`) |
| `Y` | yank the selected worktree's **path** to the clipboard (`yank_path`) — pbcopy / wl-copy / xclip / xsel / clip |
| `w` | yank the selected worktree's **slug / name** to the clipboard (`yank_worktree_name`) |
| `B` | open menu for the linked issue / PR (`browse_links`; `i` issue, `p` pr → spawns browser) |
| `.` | open the gwm documentation in the default browser (`open_docs`) |
| `i` | link prompt (`link`) — choose `i` or `p`, then digits, to attach an issue / PR |
| `V` | toggle the details sidebar (`toggle_sidebar`) — on a narrow terminal it stacks under the table instead of hiding |
| `S` | toggle the sidebar Details mode (`toggle_sidebar_mode`) — `commits` ↔ `stashes` — see [stashes mode](/tui/sidebar#stashes-mode) |
| `Space` | cycle the sidebar layout (`cycle_sidebar_layout`) — `auto` (width-driven) → `side-by-side` → `stacked` |
| `v` | toggle the sidebar position left ↔ right (`toggle_sidebar_position`; side-by-side layout only) |
| `Tab` | swap focus between the worktree list and the sidebar (`focus_swap`) |
| `1` | focus the worktrees pane (`focus_worktrees`) |
| `2` | open (if hidden) and focus the status pane (`focus_status`) |
| `3` | open the Command Logs overlay (`command_logs`) — scrollable transcript of the commands gwm ran |
| `4` | open the [Settings panel](#settings-panel-4) (`config_panel`) — edit theme / worktree / TUI knobs and **all keymaps**, with a per-row source column |
| `x` | open the [exec picker overlay](#exec-picker-overlay-x) (`exec_overlay`) — pick a [`[exec.profiles]`](/configuration/gwm-toml#exec) profile and run it in a [PTY overlay](/tui/launchers#the-embedded-pty-overlay-l--r) on the selected worktree |
| `X` | open the [clean overlay](#clean-overlay-x) (`clean_overlay`) — preview and reclaim build artifacts in the selected worktree (safety countdown before deleting) |
| `/` | open the [fuzzy filter](/tui/filter) bar (`filter`; `Enter` confirms · `Esc` clears) |
| `:` | open the [command palette](/tui/keymap-and-palette#command-palette) (`command_palette`) |
| `Enter` | show selected path in status bar |
| `?` | help overlay (`help`) |
| `q` | quit (`quit`) |
| `Esc` | clear a sticky filter if any, otherwise quit |
## confirm-delete overlay
The overlay shows two selectable buttons, `[ Confirm ]` / `[ Cancel ]`,
with focus defaulting to **Cancel** — the safe choice for a destructive
action, so a stray `Enter` cancels rather than deletes. The classic
`y` / `n` shortcuts still work regardless of focus.
| `←` / `h` | focus `[ Confirm ]` (`focus_confirm`) |
| `→` / `l` | focus `[ Cancel ]` (`focus_cancel`) |
| `Tab` | toggle focus between the two buttons (`toggle_focus`; defaults to Cancel) |
| `Enter` | activate the focused button (`activate`; Confirm → delete · Cancel → dismiss) |
| `y` | confirm (`confirm`; classic) or arm the countdown (when `D` is armed — see [countdown](/tui/confirm-countdown)) |
| `y` again | during an armed countdown, **disarms** it without firing |
| `n` / `Esc` | cancel (`cancel`) |
While the safety countdown is armed an animated spinner sits beside the
progress bar as a live loader.
## create / rename overlay
Both the New Worktree form (`n`) and the rename form (`c`) share the same
`[tui.keys.modal.create]` verbs:
| `Tab` | next field (`next_field`) |
| `BackTab` (`Shift+Tab`) | previous field (`prev_field`) |
| `↑` / `←` / `h` | previous worktree type (`prev_type`; on the type field) |
| `↓` / `→` / `l` | next worktree type (`next_type`; on the type field) |
| `Enter` | submit and bootstrap / rename (`submit`; subject to the [TOFU trust gate](/configuration/trust-ledger)) |
| `Esc` | cancel (`cancel`) |
If the repo's `.gwm.toml` isn't trusted, `Enter` lands the form's status bar on a refuse message instead of running the bootstrap — the worktree directory is **not** created in that case, so you can fix the trust state in another terminal (`gwm bootstrap` from CLI, or set `GWM_ALLOW_BOOTSTRAP=1` and relaunch) and retry. See [Configuration → TOFU trust ledger](/configuration/trust-ledger#tui-behaviour) for the exact wording and full decision tree.
## settings panel (`4`)
`4` opens the in-TUI Settings panel. Tabs (`Tab` / `Shift+Tab`) split it into
`Theme`, `Worktree`, `TUI`, `Keys` and the read-only `All` resolved-config
view. `L` flips the edit layer between the project `.gwm.toml` and the
user-global config; the layer selector decides which file an edit writes.
| `Tab` / `BackTab` | next / previous tab |
| `↑` / `↓` | select a field / binding (scrolls on the `All` tab) |
| `L` | toggle the edit layer (project ↔ global) |
| `Space` / `Enter` | activate: cycle a choice, edit a value, or **rebind a key** |
| `Esc` / `q` | close |
### Keys tab — live keymap editor
The `Keys` tab lists **every** rebindable binding: the global list-view
actions (`[global]`) and every modal verb grouped by context
(`[modal.<context>]`), each with its current key(s) and a `default` / `user` /
`repo` source badge. Select a binding and press the activate key (`Space` /
`Enter`) to capture a new key — the key column becomes a `[ … ]` input:
| any key | record it into the binding |
| `Enter` | commit a multi-stroke global chord (modal verbs auto-commit on the first key) |
| `Backspace` | drop the last captured stroke (global chord) |
| `Esc` | cancel the capture, leaving the binding unchanged |
The capture writes the binding as a TOML array to the targeted layer
(`[tui.keys]` for a global action, `[tui.keys.modal.<context>]` for a modal
verb), validates it (a conflict / prefix-collision aborts the write and leaves
the previous binding live), and reloads the keymap so the new key works
immediately. An empty capture (`Enter` with nothing recorded — global only)
unbinds the action. `Esc`, `Enter`, `Backspace` and `Ctrl+C` can't themselves
be assigned via capture — hand-edit `.gwm.toml` for those (see
[`[tui.keys]`](/configuration/gwm-toml#tuikeys)).
## issue / PR link prompt (`i`)
The first stage (`[tui.keys.modal.link.choose_target]`) is a navigable
issue-or-PR chooser; the second (`[tui.keys.modal.link.input_number]`) takes the
number.
| target choice | `j` / `↓` | next target (`next`) |
| target choice | `k` / `↑` | previous target (`prev`) |
| target choice | `i` | select issue (`issue`) |
| target choice | `p` | select PR (`pr`) |
| target choice | `Enter` | confirm the target (`accept`) |
| target choice | `Esc` | cancel (`cancel`) |
| number input | digits | type the issue / PR number |
| number input | `Enter` | commit the link (`submit`) |
| number input | `Esc` | cancel (`cancel`) |
## issue / PR open menu (`B`)
| `j` / `k` / `↓` / `↑` | move between issue and PR (`toggle`) |
| `i` | open the linked issue in the browser (`issue`) |
| `p` | open the linked PR in the browser (`pr`) |
| `Enter` | open the highlighted target (`accept`)|
| `Esc` / `q` | dismiss (`close`) |
## exec picker overlay (`x`)
Lists the `[exec.profiles.*]` names; `Enter` resolves the highlight to its
`command` array and runs it — **with no shell** — in an embedded PTY overlay
rooted at the selected worktree (the same overlay `l` / `r` use). Refuses to
open with a status-bar hint when no `[exec.profiles]` are configured. Unlike
the CLI `gwm exec --workspace`, the overlay runs the profile in the **single**
selected worktree (one PTY cannot fan out).
| `j` / `↓` | next profile (`next`) |
| `k` / `↑` | previous profile (`prev`) |
| `Enter` | run the highlighted profile (`accept`)|
| `Esc` | cancel (`cancel`) |
## clean overlay (`X`)
Previews the reclaimable build artifacts in the selected worktree and deletes
them on confirmation. The scan is gated by the **exact** safety check
`gwm clean --yes` uses — only directories git treats as ignored **and** holding
no tracked files are counted; anything else is listed as *skipped* and never
touched. The picker always opens on a `(default)` choice — the set `gwm clean`
resolves with no `--profile` (the built-in `target` / `node_modules` / `dist` /
`build`, or `[clean.profiles.default]` when defined) — followed by any
configured `[clean.profiles]`; `j` / `k` cycle them, re-scanning each time. The
confirm key arms the same safety countdown as
the [delete-confirm overlay](/tui/confirm-countdown) (driven by
`[tui] confirm_countdown_secs`); a second confirm or `Esc` disarms it, and the
reclaim fires automatically when the countdown elapses.
> The scan runs **synchronously** when the overlay opens, so opening it on a
> very large `target/` can briefly block the UI while the sizes are computed.
> Moving the scan onto the off-thread spine (#231) is a follow-up.
| `j` / `↓` | next profile (`next`) |
| `k` / `↑` | previous profile (`prev`) |
| `y` / `Enter` | arm / fire the reclaim (`confirm`) |
| `n` / `Esc` | cancel / disarm (`cancel`) |
## help overlay (`?`)
Keys render as coloured **badges** (the same chip style as the bottom
statusline) with themed section headers, so a binding stands out from
its description. All colours follow the resolved `[theme]`.
| `Esc` / `q` / `?` / `Enter` | dismiss |
## v0.10 rebind summary
The [#290](https://github.com/kbrdn1/gwm-cli/issues/290) keymap redesign moved
several keys to make room for the new verbs. The biggest changes to relearn:
| `L` (link) | `i` | `L` now launches lazygit fullscreen; `i` is the issue/PR link prompt |
| `S` (sync) | `s` | lowercase mutating verb; `S` now toggles the sidebar Commits ↔ Stashes |
| `p` (toggle delete-branch) | `D` | `p` is now `pull`; `D` arms "delete branch on remove" |
| `O` (open menu) | `B` | `O` now opens a fullscreen terminal; `B` browses the issue/PR links |
| `o` (open dispatch) | `o` (terminal PTY) | `o` now opens an embedded `$SHELL` PTY overlay |
| `v` / `V` (sidebar toggle / layout) | `V` / `Space` | `V` toggles the sidebar, `Space` cycles layout |
| `y` (yank path) | `Y` | `y` now yanks the **branch name**; `Y` yanks the path; `w` yanks the slug |
| `R` (review) | `r` / `R` | `r` runs the review in a PTY overlay, `R` runs it fullscreen |
| _(none)_ | `c` | rename the selected worktree (`edit_worktree`) |
| _(none)_ | `e` | exit the TUI to the selected path (`exit_to_worktree`) |
| _(none)_ | `t` | open the worktree in a new tmux / zellij pane (`mux_pane`) |
| _(none)_ | `h` / `H` | run `[tui.macro1]` / `[tui.macro2]` |
Existing `[tui.keys]` overrides written with the old slugs (`git_tui`,
`review`, `yank`, `open`, `open_menu`, …) keep working through backward-compat
aliases — only the physical defaults moved.
## v0.6 rebind summary
Three keys moved when [#75 (configurable launchers)](https://github.com/kbrdn1/gwm-cli/issues/75) landed. Update muscle memory accordingly:
| `r` | `f` | `r` kept as **alias** for muscle memory, but the documented mnemonic is now `f` |
| `R` | `F` | freed `R` for the new review launcher; `F` does the GitHub refresh `R` used to do |
| _(none)_ | `R` | launch the configured `[review]` command (lumen / claude / codex / aider / gh / custom) |
If you wired any of these into a custom script (unlikely — they're TUI-only), nothing breaks; this is purely about the in-app overlay.