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 what's focused 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:

config
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.

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.

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.

KeysWhat 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 eMove by word
W B EMove 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 TFind 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 LThe top, middle, and last written row on screen
ctrl+d ctrl+uHalf a screen through the buffer
ctrl+f ctrl+b or spaceA full page
gg GTop and bottom of the buffer
*Find the word under the cursor in the rest of the buffer
esc q iLeave

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, or a tool float or the palette opens.

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. All of them repeat while you hold them, and they 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 card when a background tab needs you or a long command finishes in one. N takes the oldest, so presses walk down the stack, and N takes the lot. A card holding the keyboard also answers Return and Esc directly.

Whether a card 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:

config
keybind = clear_screen=none

K 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.

Each action holds exactly one shortcut, so there is one place to look when you want to change something, and rebinding moves the whole action.

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 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 any of them in Settings under Shortcuts, or in your config.