Shortcuts
Learn six shortcuts first. The rest builds on them.
- Split side by side with D
- Split top and bottom with D
- Move between panes with ← ↓ ↑ →
- Close the focused pane with W
- New tab with T
- Open Settings with ,
Pane movement is ⌘⌥ and the direction you want to go. Prefer vim's keys? Four lines in your config move it:
keybind = nav_left=ctrl+h
keybind = nav_down=ctrl+j
keybind = nav_up=ctrl+k
keybind = nav_right=ctrl+l[ and ] step through the panes in order instead, wrapping at both ends. Open drawers are in the ring, so focus never cycles out of one without a way back.
Close one surface at a time
Each close shortcut takes one thing. W closes the focused pane or drawer, the last pane takes the tab with it, and the last tab takes the window. W closes the tab whatever it holds, W closes the window, and W closes the workspace.
A close that would end a running program asks first and names where it runs, including a collapsed drawer or Scratch.
Move around your workspaces
A window holds several workspaces, each with its own tabs. S docks the sidebar that lists them, and collapses it again. T opens a workspace with no config entry, starting in your home folder.
1 through 9 select a workspace, and [ and ] step through them in sidebar order. That pair moved the active tab through v1.4.0. Moving a tab along the bar is [ and ] now.
A jumps to the agent in this window that has waited longest for you, switching workspace and tab to reach it. Each press after that steps to the next waiting agent, wrapping at the end. The command palette lists it as Jump to Waiting Agent.
← past the leftmost pane moves focus into the
docked sidebar, and → comes back out. The
focus_sidebar action reaches it from anywhere once you give it a chord: it
ships with none.
Coming from Ghostty
These are Ghostty's chords. Open ZenTerm after Ghostty and your hands already know where things are.
Two places ZenTerm keeps its own answer. The bracket pair steps tabs here, the way it does in Safari and the rest of the Mac, where Ghostty spends it on panes. That inverts the whole family: tabs take [ and ], panes the shifted pair.
⌃⌘F stays unbound. Ghostty spells fullscreen that way as well as ⏎, but ⌃⌘F is macOS's own native-fullscreen chord and Fill Screen is a maximize, so answering it would promise a space switch it does not make.
Ghostty's ⌃⇥ tab cycling is not bound either, because ]
already is. Add keybind = next_tab=ctrl+tab if you want it back.
Find any command
Press P and type what you want. The command palette lists each action with its shortcut beside it, so it doubles as a reference while you learn. P opens the workspace picker.
⏎ creates a Git worktree over a picker row or a focused sidebar row, and ⌫ removes one over a picker row for a worktree. Anywhere else the keys reach the program in a pane. Over a picker row for a worktree whose folder is already gone, marked removed, ⌫ closes its workspace instead.
A link in the terminal needs a ⌘-click to open. Hold ⌘ and the link underlines and becomes clickable. A plain click does nothing, because a terminal is full of text that only looks like a link.
Read back through a pane
S puts the focused pane in scroll mode. The pane header reads SCROLL and shows how far below the viewport the buffer runs, a band marks the row you are on, and what you type stops at the app.
Scroll mode is a mode because the keys it wants belong to the shell. You use
j, k, ctrl+d and ctrl+u inside your programs, so ZenTerm cannot hold them
as chords. Borrowing them for the length of a read is the trade.
| Keys | What they do |
|---|---|
j k or ↑ ↓ | Move the cursor a row. The buffer scrolls once the cursor hits an edge |
h l or ← → | Move a column |
w b e | Move by word |
W B E | Move by WORD, whitespace-delimited, so foo.bar is one where w sees three |
0 ^ $ | The start of the row, the first thing on it that is not whitespace, the end |
{ } | Move by paragraph, which in a terminal is one command's output |
f F t T | Find a character on the row, forward or back, landing on it or beside it |
; , | Do that find again, or back the other way |
H M L | The top, middle, and last written row on screen |
ctrl+d ctrl+u | Half a screen through the buffer |
ctrl+f ctrl+b or space | A full page |
gg G | Top and bottom of the buffer |
* | Find the word under the cursor in the rest of the buffer |
esc q i | Leave |
Every motion takes a count, so 12j moves twelve rows and 3} skips three blocks
of output. 0 is the start of the row on its own and a digit once a count is
underway, which is vim's own rule: without it 10j would jump to column 0 and
step once.
ctrl+d and ctrl+u carry the cursor with them. The cursor walks
half a screen down the buffer and the view takes as much of that as it can, so the
band parks mid-screen while the text runs past it. Where the view runs out of
buffer the cursor makes the rest of the trip, which is the only way to reach the
last half page by paging.
Your own chords still work inside the mode, so T and pane navigation are never swallowed. The mode ends on its own when focus moves, the pane closes, you change tab, a tool float, the palette, the picker or Settings opens, or you switch to another window.
With a tool float open, S and F read the float's buffer instead of the pane behind it. The card wears the header while they are up, and closing the card ends the mode. Clearing the screen, the prompt jumps and the screen-to-file chords reach a float too.
Select and copy what you read
v starts a selection at the cursor and V takes whole rows. Motions grow it,
y copies it and pulses what it took, and esc hands the selection back without
leaving the mode. With nothing selected, y waits for the second y that names
whole rows, so 3yy copies three.
A selection follows its text. Scrolling grows it by the rows that arrive, and resizing the pane re-finds it where the rewrap put it. It goes when the row you started on leaves the screen, which is as far as the terminal core can read.
Search the scrollback
F opens a find bar along the bottom of the focused pane and searches its whole scrollback, however far back it runs. Matches highlight as you type and the bar counts them. If what you typed sits in history, the pane scrolls to it while you type.
The bar opens on whatever you have selected, so a word you can see costs no
retyping. A mouse selection counts and so does a v selection made in scroll
mode. E searches the selection alone, and does nothing
when there is no selection.
Press Return and the keys go back to the pane, leaving you in scroll mode on the
match, where n and N step through the rest and v, V and y copy what you
found. Stepping is those keys rather than a chord, so search_next and
search_previous ship with no shortcut. Give them one if you want to step from
anywhere.
The count reads in the order you see, so match 1 is the one nearest the top of your scrollback. Stepping does not wrap.
The bar and a live prompt never share the screen, so leaving scroll mode any way at all takes the bar down with it. Close the bar and you land back where you opened it. Typing past the last match does the same, so you are never parked on something that stopped matching.
Move the viewport without the mode
For when you want a look rather than a read.
Home and End go to the ends of the buffer, Page Up and Page Down move a screen at a time, and ↑ and ↓ walk between the prompts your shell marked. The page and prompt chords repeat while you hold them, and all of them work on a focused drawer too.
The prompt jumps take Ghostty's shifted spelling and not its bare ⌘↑ and ⌘↓. macOS claims that pair on most Macs, so the keypress never arrives. Bind them if yours are free. Prompt marks come from shell integration, so a shell that sets none leaves the jumps with nothing to find.
Work on the screen itself
- Clear the screen, and the scrollback with it, using K
- Select the whole buffer, ready for ⌘C, using A
- Scroll back to the selection with J
- Paste what you have selected with V
- Write the screen to a file with J
V types your selection back into the pane. Either
kind counts, a mouse selection or a v selection from scroll mode, and ⌘V still
pastes the clipboard.
K leaves a full-screen program alone: vim and its kind draw on a second screen with no scrollback to clear.
The write has two other endings. J copies the path instead and J opens the file. The file is written either way, so the three differ only in where the path goes. Reach for it when a wall of output is easier to grep than to read.
A comes from Edit → Select All. A menu shortcut reaches
a text field and a pane both, which a keybind cannot. Two things follow: any
keybind or tool float key: landing on ⌘A is refused with a notice, and
select_all=none cannot hand the chord back to your program. Bind
select_all to another chord and it works over a pane like anything else.
Clear a notice
ZenTerm posts a notice when something you cannot see needs you, or when a long command finishes there. That covers a background tab, a collapsed drawer, Scratch and a tool float, so a closed drawer posts one even in the tab you are already in. The notice names the tab it came from and the drawer or tool it belongs to, and Switch opens it.
N takes the oldest, so presses walk down the stack, and N takes the lot. A notice holding the keyboard also answers Return and Esc directly. Looking at the surface answers its notice too, so visiting a tab clears what that tab puts on screen and a collapsed drawer goes on asking.
Whether a notice waits to be answered or clears itself is attention-toast and
completion-toast in your
config, both sticky by default, and
toast-duration sets how long anything that clears itself stays up.
Change the font size
= and - step the font, and
0 returns to the font-size in your
config. All three apply to every pane in every
tab and window, so your panes stay in step.
Take a shortcut away
Point an action at none and the chord reaches your program instead:
keybind = clear_screen=noneK then goes to whatever runs in the pane. Settings does the same thing: open Shortcuts, select the row, and press Delete. Moving an action to another chord frees the old one the same way.
An action can hold more than one chord. Add a second keybind line for it and
both work: = and ⌘+ both increase the font size out of the
box.
Hide a toolbar button
Settings under Appearance hides any of the footer toolbar's built-in buttons,
and hide-toolbar-buttons does it from the config. The shortcut and the palette
entry stay live either way. A hidden bottom drawer, right drawer or Scratch
button comes back while its shell runs something out of sight, and goes again
when it finishes. A tool float takes toolbar:false for the same reason: the
toolbar button goes and the chord stays.
The full set
The keybind reference has every default shortcut, grouped by category. Remap most of them in Settings under Shortcuts, and any of them in your config. The font size, reload, Select All, update check and issue report chords live in the config only.