native macOS codings agent orchestrator prowl.onev.cat
Prowl docs components terminal.md
12 kB

Terminal — Tabs, Splits & Panes #

The terminal layer: tabs within a worktree, splitting a tab into panes, the Ghostty engine underneath, tab titles & icons, shell integration, and fonts.

Keywords: terminal, tab, split, pane, surface, ghostty, font size, shell integration, OSC 133, scrollback, find, search, close tab, new tab, tab title, tab icon, CJK, font fallback, Japanese, Hiragino, ghostty config, dedicated config

Related: concepts · canvas · shelf · agent-detection · cli · keyboard-shortcuts

What it is #

Inside each worktree you get terminal tabs. Each tab is a layout of one or more panes (a.k.a. surfaces) — split horizontally/vertically — rendered by the embedded Ghostty engine. One worktree → many tabs → each tab → one or more panes.

Worktree
└─ Tab  (has a title + icon)
   └─ Pane / surface  (a live Ghostty terminal; tabs can hold several, split)

A single Ghostty app instance hosts every pane as an independent surface, which is why Prowl is fully native and CJK-correct.

Tabs #

Operation How
New tab Terminal menu → New Terminal (Ghostty new_tab, typically ⌘T); the + on a Shelf spine; the prowl create tab CLI
Select tab 1–9 ⌘1–⌘9
Previous / Next tab ⌘⇧[ / ⌘⇧]
Close focused tab Terminal menu → Close Terminal Tab (Ghostty close_tab)
Close (right-click a tab) Close Tab · Close Other Tabs · Close Tabs to the Right · Close All
Undo a close Ghostty undo (typically ⌘Z) within undo-timeout (5 s default) restores the last closed tab or pane in place; redo (⌘⇧Z) closes it again. See undo close
Rename tab Right-click → Rename Tab (sets a custom title)
Change tab icon Right-click → Change Tab Icon (pick an SF Symbol)
Reorder tabs Drag tabs in the tab bar

In Shelf view, tabs of the open book are also cycled with ⌘⌃↑ / ⌘⌃↓.

Splits (panes) #

Splitting is handled by Ghostty actions (bind/keys in your Ghostty config):

Operation Ghostty action
New split (vertical / right) new_split:right
New split (horizontal / down) new_split:down
Focus adjacent pane goto_split:left/right/up/down, or the app shortcuts below
Resize split resize_split:<dir>:<px>
Equalize splits equalize_splits
Zoom / maximize a pane toggle_split_zoom (app default ⌘⌥⇧F)
Close a pane close_surface (Terminal menu → Close Terminal)

App-level pane navigation (works inside the terminal too): ⌘[ / ⌘] previous / next pane, ⌘⌥↑/↓/←/→ for directional pane focus, ⌘⌥⇧F to zoom / unzoom the focused pane. Shelf spines also expose split vertical / split horizontal buttons on the open book.

Zoom and close also have mouse affordances: hovering a pane's top drag handle reveals a zoom button and a close button in the pane's top-right corner. The close button closes that pane with the same confirmation as the tab bar's close button, and its tooltip shows the close_surface shortcut (⌘W by default) so the keyboard route is discoverable. A zoomed pane keeps both buttons visible so it's always clear how to leave zoom.

Tab titles — important caveat #

A tab's displayed title is, in order of precedence:

  1. a custom title you set via Rename Tab, else
  2. the live shell title the running program emits (OSC 2), else
  3. an auto-generated default like project 1, project 2.

Rapid live-title animation is coalesced per tab to at most one visible update per second so one spinner frame does not rebuild the entire tab bar. The newest withheld title is applied at the end of that interval even when no agent is running, so a live title may visibly lag by up to one second but its final value is not left behind.

The Run Script tab is labeled RUN SCRIPT and is title-locked for its lifetime. Prowl also "learns" your shell's idle prompt so it doesn't mistake it for a meaningful title.

Titles are free-form and can lie or lag. Any program can set any title. When automating, never target a pane by its title — use the JSON pane.id or, for a same-session handoff, the text pN handle from prowl list. The bundled prowl-cli skill repeats this for good reason.

Tab icons #

Tabs get an auto-detected icon based on what's running (e.g. an agent's icon), which you can override (Change Tab Icon) or which a script can set. Icon precedence is auto < script < user.

An Agent Profile launch applies that runtime's brand icon itself instead of waiting for detection — to the new tab, or to the containing tab when the profile opens in a split. Auto-detection reads the first token of the command, and a profile that sets launch-scoped environment variables runs as env VAR=… claude, whose first token is env. The slot stays claimable, so a later recognised command in the same tab still takes it over.

Shell integration & status (OSC sequences) #

Ghostty's shell integration drives several Prowl features via terminal escape sequences:

  • OSC 133 (prompt/command marks) — lets Prowl know when a command starts and finishes and its exit code. This powers command-finished notifications, auto-close-on-success, and the prowl send --capture output capture.
  • OSC 2 (title) — feeds tab titles and agent/icon detection.
  • Progress reports (OSC 9;4) — long commands report busy/idle, feeding the tab's activity indicator and task status. Task status also folds in detected agent activity (Working/Blocked, incl. background workflows) — see agent-detection.
  • Program status (OSC 7501) — Prowl answers the support query, so programs that speak the protocol (Claude Code 2.1.295+, Pi 1.1.0+) report idle/working/blocked/done. Prowl receives the reports but does not act on them yet; the activity indicator and agent detection still use the signals above.
  • Bell / desktop notification — increments unread indicators.

--capture in the CLI requires OSC 133 on the target pane; without it you get CAPTURE_UNSUPPORTED (read the screen with read --wait-stable instead).

Every pane's environment reports TERM_PROGRAM=prowl (with TERM_PROGRAM_VERSION set to the app version), so scripts and agents can detect they're running inside Prowl rather than standalone Ghostty. TERM itself stays xterm-ghostty — terminfo-based feature detection is unaffected.

Command-finished behavior #

When a command finishes (via OSC 133), Prowl can:

  • fire a notification if it ran longer than the threshold (default 10s) — see notifications;
  • auto-close the tab/pane if it was launched with "close on success" and the exit code is 0;
  • skip the notification for user-initiated exits (Ctrl-C → 130, SIGTERM → 143) or if you typed in that pane within the last ~3 seconds.

Font size #

  • Reset / Increase / Decrease via the Terminal menu (Ghostty reset_font_size / increase_font_size:1 / decrease_font_size:1; usually ⌘0 / ⌘+ / ⌘-).
  • The chosen size is remembered (terminalFontSize) and applied across worktrees; new tabs and splits inherit the focused pane's size.
  • Going back to Ghostty's font-size (for example with Reset) clears the remembered size, so later changes to font-size apply again. A remembered size that equals the current font-size is cleared at launch.

Terminal menu: Find… (start_search), Find Next/Previous (search:next/search:previous), Hide Find Bar (end_search), Use Selection for Find (search_selection). These are Ghostty-managed.

Scrollback, CJK, copy/paste #

Scrollback, wide/CJK character rendering, and copy/paste are handled by Ghostty with its defaults. Customize terminal behavior in the Ghostty config that Prowl uses (see Ghostty config).

CJK font fallback. When the active Ghostty config sets neither font-family nor font-codepoint-map (including its config-file includes, the active theme file, and --font-family=… launch arguments), Prowl maps kana, CJK punctuation, CJK ideographs (including the supplementary planes), and fullwidth forms to one system CJK font, and Hangul to Apple SD Gothic Neo. Without this, Ghostty picks a font for kana and punctuation by scoring every installed font, which often selects BIZ UDGothic, BIZ UDMincho, or Osaka-Mono, so CJK text changes face and size within a line. The font follows the first CJK language in the system language list (a -AppleLanguages launch argument wins; Prowl's own app language does not count):

First CJK language Font
Japanese Hiragino Sans
Korean Apple SD Gothic Neo
Traditional Chinese (Taiwan) PingFang TC
Traditional Chinese (Hong Kong, Macau) PingFang HK
Simplified Chinese, or no CJK language PingFang SC

Set font-family or font-codepoint-map to take over; Prowl then adds nothing.

Ghostty config #

By default Prowl reads the same config files as the standalone Ghostty app (config or config.ghostty in ~/.config/ghostty/ and in ~/Library/Application Support/com.mitchellh.ghostty/, plus their config-file includes), so a change applies to both apps.

Settings → General → Terminal Config → Choose File… selects a dedicated file for Prowl only (ghosttyConfigPath). That file replaces Ghostty's config files; it is not layered on top of them, so copy any setting you want to keep. Relative config-file includes resolve from the file's folder. If the file does not exist, terminals use Ghostty's built-in defaults and Settings shows a warning; Open Config creates it. Use Ghostty's Config returns to the shared files. Open Config and Reload act on whichever source is active, and a change of source applies to running terminals immediately.

Prowl-only keys such as prowl-split-divider-width are read from the active source's file.

Color scheme #

The terminal theme automatically follows the macOS light/dark appearance. There's no in-app Ghostty theme picker; change Ghostty colors via its config file.

Layout persistence #

If restoreTerminalLayoutOnLaunch is enabled, Prowl saves the tab/split layout (which worktrees, tabs, split trees, titles, icons) and restores it on next launch. Notification bodies are not persisted.

Gotchas for agents #

  • Tab selection ≠ pane focus. A tab can have several panes; selecting a tab doesn't pin which split has keyboard focus. The CLI's pane.focused is the truth.
  • Closing the last tab leaves the worktree with no visible terminal (Shelf removes the book; Canvas drops the card). ⌘Z within undo-timeout brings it back.
  • Closing a pane or tab asks for confirmation after editing within the last 10 seconds or during input-method composition. See recent input close protection.
  • A closed pane or tab stays restorable for Ghostty's undo-timeout (5 s by default). Observers see the close immediately: prowl agents wait reports the pane as gone, and a restored pane gets a new short handle. See undo close.
  • --capture and stable reads depend on the pane's shell integration; agents running full-screen TUIs may need read --wait-stable rather than --capture.