Workspace
Keybinds
Every default keybind in Verde, plus how to remap or disable each binding in verde.json.
Default keybinds
These are the defaults, read from
packages/desktop/src/app/keybinds.zig. Override any of them under keybinds
in your Verde config — see Remapping below.
App
| Combo | Action |
|---|---|
Ctrl+Shift+P / Cmd+Shift+P |
Command palette |
Ctrl+W / Cmd+W, Alt+X |
Close the focused pane |
Ctrl+Shift+W / Cmd+Shift+W |
Close the current workspace (reopen from the command palette) |
Ctrl+Shift+Space |
Toggle the experimental Companion (when enabled in Settings) |
Ctrl+Shift+R / Cmd+Shift+R, F5 |
Refresh / reload app |
Alt+O |
Open the default project |
Ctrl+Shift+O |
Open in external editor |
Sidebar & panes
| Combo | Action |
|---|---|
Ctrl+S / Cmd+S |
Toggle the sidebar (visible ↔ icon) |
Ctrl+Shift+S |
Toggle the sidebar's hidden mode |
Ctrl+Shift+B |
Toggle the embedded browser pane |
Ctrl+R / Cmd+R |
Reload the active browser tab (browser pane only) |
Tab |
Inside a chat pane, focus the prompt box |
Ctrl+Tab |
Focus the next pane in sidebar order |
Ctrl+Shift+Tab |
Focus the previous pane in sidebar order |
Ctrl+1 … Ctrl+9, Ctrl+0 |
Focus a pane in the current workspace by sidebar order |
Ctrl+Shift+1 … Ctrl+Shift+9, Ctrl+Shift+0 |
Jump to a row in the global Active section by displayed order |
Alt+1 … Alt+9, Alt+0 |
Jump between workspaces by sidebar order |
Alt+↑ / Alt+↓ |
Cycle to the previous / next workspace |
Pane cycling wraps at either end. When a pane is zoomed, cycling switches the zoomed pane without restoring the split layout.
Focus
| Combo | Action |
|---|---|
Ctrl+Left |
Focus the pane or horizontal strip item to the left |
Ctrl+Right |
Focus the pane or horizontal strip item to the right |
Ctrl+Up |
Focus the pane or vertical strip item above |
Ctrl+Down |
Focus the pane or vertical strip item below |
Ctrl+H/J/K/L are intentionally unbound by default. Set the corresponding |
|
keybinds.workspace.focus_left/down/up/right values in verde.json to opt in. |
Alt+arrow combos are no longer focus aliases — Alt+↑ / Alt+↓ now cycle
between workspaces (see the sidebar table above).
Swap (rearrange the tiling)
| Combo | Action |
|---|---|
Ctrl+Shift+H |
Swap focused pane with the left one |
Ctrl+Shift+L |
Swap focused pane with the right one |
Ctrl+Shift+K |
Swap focused pane with the one above |
Ctrl+Shift+J |
Swap focused pane with the one below |
Resize (grow)
| Combo | Action |
|---|---|
Alt+Shift+← |
Grow the focused pane left |
Alt+Shift+→ |
Grow the focused pane right |
Alt+Shift+↑ |
Grow the focused pane up |
Alt+Shift+↓ |
Grow the focused pane down |
Zoom
| Combo | Action |
|---|---|
Alt+Z |
Zoom the focused pane to fill the workspace; toggle again to restore |
Workspace splits
Workspace splits have no direct default keybinds. With prefix mode enabled,
Ctrl+B, then t creates a new chat and Ctrl+B, then Shift+T creates a
separate top-level terminal pane. The v and - prefix chords create tiled
splits of the configured default pane type (chat or terminal);
Shift+V and Shift+- create the other type.
You can also use the pane header buttons: C| / C- for chat vertical /
horizontal and T| / T- for terminal vertical / horizontal, or bind any
split action directly under keybinds.workspace.
Terminal (inside a focused terminal pane)
| Combo | Action |
|---|---|
Ctrl+Alt+T / Cmd+Alt+T |
New terminal tab |
Ctrl+Shift+R / Cmd+Shift+R |
Rename the active terminal tab |
Ctrl+Shift+PageUp |
Previous terminal tab |
Ctrl+Shift+PageDown |
Next terminal tab |
Ctrl+Alt+↑ / Cmd+Alt+↑ |
Focus the terminal split above |
Ctrl+Alt+↓ / Cmd+Alt+↓ |
Focus the terminal split below |
Ctrl+Alt+← / Cmd+Alt+← |
Focus the terminal split left |
Ctrl+Alt+→ / Cmd+Alt+→ |
Focus the terminal split right |
Ctrl+- / Ctrl+= |
Per-terminal zoom out / in |
Chat transcript scrolling
| Combo | Action |
|---|---|
↑ |
Scroll up one line |
↓ |
Scroll down one line |
PageUp |
Scroll up one page |
PageDown |
Scroll down one page |
Transcript scrolling is direct — no inertia or velocity decay. When input stops, the view stops. Do not expect a multi-frame glide.
Prefix mode (tmux-style)
Prefix mode is off by default. When enabled, pressing the prefix chord
(Ctrl+B by default) arms Verde for one keypress: the next key resolves
against the prefix table below instead of reaching the focused pane. While
armed, a one-line status bar appears along the bottom (PREFIX esc cancel Ctrl+B send prefix w workspace nav ? keybinds); press ? to open the full cheat sheet of
every second key — including your own command scripts — without dropping the
chord. Esc cancels,
an unbound key is swallowed, and pressing the prefix twice sends the literal
chord to the focused terminal (tmux send-prefix).
Every built-in command has a default seat in the prefix table, so turning it on exposes the whole command surface without remapping anything:
{ "keybinds": { "prefix": true } }Change the prefix chord with a string (which also enables prefix mode), or use the object form for full control:
{
"keybinds": {
"prefix": {
"enabled": true,
"key": ["Ctrl+A", "Ctrl+B"],
"defaults": true,
"bindings": {
"c": "new_thread",
"g": { "command": "lazygit", "in": "pane" },
"Shift+3": { "action": "workspace.select.3" },
"z": null
}
}
}
}key— one accelerator or an array. Any of them arms the prefix.defaults— set tofalseto drop the built-in table and start empty.bindings— keyed by the second key's accelerator ("x","Shift+X","Ctrl+Left","Comma"). A string value is an action name;nullremoves a default;{ "command": "..." }runs a shell script. Addin(oropen) to choose where it runs:inWhat happens omitted / backgroundDetached sh -lcin the project directory, with the project path as$1(same as customopen.defaultactions). TUIs like lazygit will not show a pane.terminalTypes the command into the focused terminal. Falls back to paneif a terminal is not focused.paneOpens a new terminal pane whose process is the command. horizontal/split_horizontalHorizontal tiled split of the focused pane, then runs the command there. vertical/split_verticalVertical tiled split, then runs the command there. floatingOpens a floating quick terminal running the command. tabNew tab in the focused terminal dock. Falls back to paneif a terminal is not focused.Aliases:
new_pane/new→pane;split/horizontal→split_horizontal;float/quick→floating;current/focused→terminal;detached→background.
Configured direct shortcuts work alongside prefix mode. Modifier state is exact:
Ctrl+B then x is different from Ctrl+B then Ctrl+X, so release Ctrl
before the second key unless the binding uses it.
Workspace menu
prefix w opens the herdr-style NAVIGATE workspace menu. The status bar
switches to » NAVIGATE esc back Up Prev workspace Down Next workspace Tab Next pane ….
Running any bound action closes the menu immediately; an unbound key leaves it
open so you can choose again. Press Esc to close it without running anything.
Defaults: Up/Down previous/next workspace, Tab/Shift+Tab next/previous
pane, h j k l focus, c new thread, v / - split the configured default
pane type, Shift+V / Shift+- split the other type, x close, z zoom,
p command palette, 1–0 select workspace, ? cheat sheet.
The table is overridable exactly like bindings, under "navigate":
{ "keybinds": { "prefix": { "navigate": { "Up": null, "g": { "command": "lazygit" } } } } }Default prefix table
After Ctrl+B |
Action |
|---|---|
? |
prefix.keybinds (cheat sheet, stays armed) |
w |
prefix.navigate (one-shot workspace menu) |
p |
command_palette |
t / Shift+T |
new_thread / new_terminal |
r |
refresh |
o / e |
open / open_editor |
Space |
companion |
s / Shift+S |
sidebar / sidebar_hidden |
b |
browser |
` |
terminal.toggle |
q |
workspace.toggle_quick_pane |
x / Shift+X |
workspace.close / workspace.close_current |
z |
workspace.toggle_maximize |
i |
workspace.focus_prompt |
c |
workspace.add (new workspace) |
Shift+C |
workspace.split_chat_horizontal |
v / - |
Default pane split, vertical / horizontal |
Shift+V / Shift+- |
Alternate pane split, vertical / horizontal |
h j k l, arrows |
workspace.focus_* |
Shift+H/J/K/L |
workspace.move_* |
Ctrl+H/J/K/L, Ctrl+arrows |
workspace.grow_* |
n / Shift+N |
workspace.pane_next / pane_previous |
[ / ] |
workspace.previous / next |
Shift+[ / Shift+] |
workspace.active_previous / active_next |
1 … 9, 0 |
workspace.pane_select.1 … 10 |
Shift+1 … Shift+0 |
workspace.select.1 … 10 |
Ctrl+1 … Ctrl+0 |
workspace.active_select.1 … 10 |
Shift+Up / Shift+Down |
chat_up / chat_down |
PageUp / PageDown |
chat_page_up / chat_page_down |
m / Shift+M |
chat.model_picker / chat.run_config |
Ctrl+T / Shift+W |
terminal.new_tab / terminal.close |
, |
terminal.rename_tab |
Ctrl+PageUp / Ctrl+PageDown |
terminal.tab_previous / tab_next |
Alt+arrows |
terminal.split_* |
Alt+Shift+arrows |
terminal.focus_* |
Terminal and chat actions only apply while a pane of that kind is focused, exactly like their direct shortcuts.
Prefix action names
Action names mirror the remapping keys below, joined with . for nested
groups: refresh, open, open_editor, new_thread, new_terminal, workspace.add, command_palette,
companion, sidebar, sidebar_hidden, browser, chat_up, chat_down,
chat_page_up, chat_page_down, chat.model_picker, chat.run_config,
terminal.toggle, prefix.keybinds, prefix.navigate, and terminal.<key>
for every terminal binding. The dynamic split names are workspace.split_default_*
and workspace.split_alternate_*, alongside every workspace.<key>. Positional actions take a
1-based ordinal: workspace.select.N, workspace.pane_select.N,
workspace.active_select.N.
Remapping
Override any binding under keybinds in your verde.json. On Unix it is under
$XDG_CONFIG_HOME/verde or ~/.config/verde; on Windows it is under
%APPDATA%\Verde. Add "$schema": "https://verdeai.dev/config.schema.json" at
the root of that file for editor autocomplete of every keybind and prefix
action. Use a string for one shortcut, or a string array for multiple
shortcuts on the same action:
Ctrl+T and Ctrl+Shift+T are unbound by default. To opt back into those
direct shortcuts, use new_thread and workspace.split_terminal_horizontal
as shown below.
{
"keybinds": {
"new_thread": "CommandOrControl+T",
"browser": "Ctrl+Shift+B",
"companion": "Ctrl+Shift+Space",
"workspace": {
"split_terminal_horizontal": "CommandOrControl+Shift+T",
"close_current": "CommandOrControl+Shift+W",
"focus_up": "Ctrl+K",
"focus_down": "Ctrl+J",
"focus_left": "Ctrl+H",
"focus_right": "Ctrl+L",
"pane_previous": "Ctrl+Shift+Tab",
"pane_next": "Ctrl+Tab",
"active_select": ["Ctrl+Shift+1", "Ctrl+Shift+2", "Ctrl+Shift+3", "Ctrl+Shift+4", "Ctrl+Shift+5", "Ctrl+Shift+6", "Ctrl+Shift+7", "Ctrl+Shift+8", "Ctrl+Shift+9", "Ctrl+Shift+0"],
"pane_select": ["Ctrl+1", "Ctrl+2", "Ctrl+3", "Ctrl+4", "Ctrl+5", "Ctrl+6", "Ctrl+7", "Ctrl+8", "Ctrl+9", "Ctrl+0"],
"previous": "Alt+Up",
"next": "Alt+Down",
"move_left": "Ctrl+Shift+H",
"move_right": "Ctrl+Shift+L",
"move_up": "Ctrl+Shift+K",
"move_down": "Ctrl+Shift+J",
"toggle_maximize": "Alt+Z",
"close": ["CommandOrControl+W", "Alt+X"],
"select": ["Alt+1", "Alt+2", "Alt+3", "Alt+4", "Alt+5", "Alt+6", "Alt+7", "Alt+8", "Alt+9", "Alt+0"]
},
"terminal": {
"new_tab": "CommandOrControl+Alt+T",
"close": "CommandOrControl+Shift+W",
"rename_tab": "CommandOrControl+Shift+R",
"tab_previous": "CommandOrControl+Shift+PageUp",
"tab_next": "CommandOrControl+Shift+PageDown",
"focus_up": "CommandOrControl+Alt+Up",
"focus_down": "CommandOrControl+Alt+Down",
"focus_left": "CommandOrControl+Alt+Left",
"focus_right": "CommandOrControl+Alt+Right"
}
}
}workspace.pane_select is positional: the first shortcut focuses the first pane
shown under the current workspace in the sidebar, the second shortcut focuses
the second pane, and so on.
workspace.active_select follows the sorted order currently shown in the
sidebar's global Active section, including rows from other workspaces.
Disabling a binding
Set the binding to null, an empty string, or an empty array to disable it:
{
"keybinds": {
"terminal": {
"toggle": null,
"split_up": null,
"split_down": null,
"split_left": null,
"split_right": null
}
}
}Binding keys reference
The keybinds config uses the same accelerator grammar as the desktop defaults. The top-level keys group actions by surface; the inner values are one shortcut or an array of shortcuts.
| Group | Keys (subset) |
|---|---|
| top | refresh, open_default, open_editor, new_thread, command_palette, companion, toggle_sidebar, toggle_sidebar_hidden, toggle_browser, toggle_terminal |
| chat | chat_up, chat_down, chat_page_up, chat_page_down |
workspace |
split_chat_vertical, split_chat_horizontal, split_terminal_vertical, split_terminal_horizontal, toggle_maximize, close, close_current, focus_left, focus_right, focus_up, focus_down, focus_prompt, pane_previous, pane_next, active_select, pane_select, move_*, grow_*, select, previous, next |
terminal |
new_tab, close, rename_tab, tab_previous, tab_next, split_up, split_down, split_left, split_right, focus_up, focus_down, focus_left, focus_right |
prefix |
enabled, key, defaults, bindings, navigate — see Prefix mode |
Keybinds are loaded on startup, on app refresh (F5, Ctrl+Shift+R, or
prefix then r), and whenever verde.json changes on disk. Refresh is
app-owned even when a terminal TUI is focused. See Configuration &
state for the hosted verde.json JSON Schema
(https://verdeai.dev/config.schema.json) and where state lives.