# Keyboard shortcuts

> TUI key bindings for prompt and scrollback focus, cancel, rewind, vim mode, mouse actions, and multi-key Escape behavior with timing constraints.

- Repository: xai-org/grok-build
- GitHub: https://github.com/xai-org/grok-build
- Human docs: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458
- Complete Markdown: https://grok-wiki.com/public/docs/xai-org-grok-build-90205de50458/llms-full.txt

## Source Files

- `crates/codegen/xai-grok-pager/docs/user-guide/03-keyboard-shortcuts.md`
- `crates/codegen/xai-grok-pager/src/input`
- `crates/codegen/xai-grok-pager/src/app/mod.rs`
- `crates/codegen/xai-ratatui-textarea/src`
- `crates/codegen/xai-grok-pager/docs/user-guide/01-getting-started.md`

---

---
title: "Keyboard shortcuts"
description: "TUI key bindings for prompt and scrollback focus, cancel, rewind, vim mode, mouse actions, and multi-key Escape behavior with timing constraints."
---

The interactive Grok Build TUI binds keys through a single action registry (`ActionDef` / `ActionRegistry`): each action has a default key, optional alts, a `When` context (scrollback focused, prompt focused, agent screen, always), and optional double-press confirmation. Bindings are **built in and not user-remappable**. Terminal brand detection rewrites a few chords (VS Code family, Apple Terminal, Kitty keyboard protocol gaps). Scrollback **vim mode** gates bare-letter bindings; Escape is a separate policy (clear / rewind / mid-turn swallow) with an **800ms** double-press window, independent of focus and vim settings.

## Binding model

| Concept | Behavior |
|---------|----------|
| Registry | All shortcuts live in default action definitions, not scattered handlers |
| Context (`When`) | Exact match per input layer: scrollback, prompt, agent screen, global |
| Alt keys | Second (or more) bindings on the same action (e.g. `j` / `Down`) |
| Confirmation | Some actions require double-press within **1000ms** (`requires_confirmation`) |
| Esc policy | Handled outside the registry: arm clear or rewind with **800ms** TTL |
| Shortcuts bar | Bottom bar shows high-priority hints for the current focus and run state |
| Cheatsheet | `Ctrl+.` or `Ctrl+X` opens the full shortcuts help; palette lists the same actions |

Open the **command palette** with `Ctrl+P` or `?` to search actions, slash commands, and skills without memorizing chords.

## Input modes: simple vs vim scrollback

Two orthogonal UI settings control keys:

| Setting | Config | Default | Controls |
|---------|--------|---------|----------|
| Scrollback vim mode | `[ui].vim_mode` in `~/.grok/config.toml`, or `/vim-mode` | `false` | Bare-letter scrollback nav (`j`/`k`, `h`/`l`, `g`/`G`, …) |
| Prompt simple mode | `[ui].simple_mode` | `true` | Prompt editor: plain input vs experimental vim-in-prompt |

**Simple mode (default scrollback):** arrows for entry nav, `Shift+Arrow` for turn jumps, `Space` or any letter to focus the prompt (letter types into the composer).

**Vim mode (opt-in scrollback):** `j`/`k`, `H`/`L`, `J`/`K`, `h`/`l`, `e`/`E`, `g`/`G`, `y`/`Y`, `r`, `x`, `o`/`O`, and `i` for insert/focus. Arrow keys, `Tab`, `Esc`, `Space`, `PageUp`/`PageDown`, and every `Ctrl+letter` shortcut work in **both** modes.

```toml
# ~/.grok/config.toml
[ui]
vim_mode = true      # scrollback hjkl / gG (does not change the prompt editor)
simple_mode = true   # plain prompt input (default)
```

## Navigation (scrollback focused)

| Key | Alt | Action |
|-----|-----|--------|
| `j` | `Down` | Select next entry |
| `k` | `Up` | Select previous entry |
| `⇧L` | `Shift+Right` | Next turn (user prompt) |
| `⇧H` | `Shift+Left` | Previous turn |
| `⇧J` | — | Next assistant response |
| `⇧K` | — | Previous assistant response |
| `g` | — | Top of scrollback |
| `⇧G` | — | Bottom of scrollback |
| `Ctrl+K` | — | Scroll up one line (selection unchanged) |
| `Ctrl+J` | — | Scroll down one line |
| `PageUp` | — | Page up (selection → top of viewport) |
| `PageDown` | — | Page down (selection → bottom of viewport) |
| `Ctrl+U` | — | Half page up |
| `Ctrl+D` | `Shift+D` in VS Code family | Half page down |
| `o` / `⇧O` | — | Next / previous link (vim mode) |

`PageUp` / `PageDown` also scroll while the **ordinary** prompt is focused, without moving focus or the draft. An open history panel, `@` file search, slash menu, or completion dropdown keeps those keys for its own navigation.

## View and block content (scrollback focused)

| Key | Alt | Action |
|-----|-----|--------|
| `h` | `Left` | Collapse selected entry |
| `l` | `Right` | Expand selected entry |
| `e` | — | Toggle fold |
| `⇧E` | — | Expand all / collapse all |
| `Ctrl+E` | — | Expand/collapse all thinking blocks |
| `r` | — | Toggle raw markdown on selection |
| `y` | — | Copy block content |
| `⇧Y` | — | Copy block metadata (e.g. shell command / path) |
| `Enter` | `Ctrl+F` | Open block in fullscreen viewer |
| `x` | — | Kill background task on selected task block (vim mode) |

Optional `pager.toml` pin for hand folds:

```toml
[scrollback.scroll]
respect_manual_folds = true   # opt-in; default off
```

When pinned, streaming finish events leave a manual fold alone; expanding while auto-scroll follows the tail stops follow. Resume with `⇧G`, `j` at the last entry, scrolling past the bottom, or sending a prompt. `⇧E` clears all pins; `Ctrl+E` clears thinking pins.

## Focus

| Key | Context | Action |
|-----|---------|--------|
| `Tab`, `Space`, `i` (vim) | Scrollback focused | Focus prompt |
| `Tab` | Prompt focused | Focus scrollback |
| `Enter` | Prompt focused (idle) | Send prompt |
| Letter keys (simple mode) | Scrollback focused | Auto-focus prompt and type |

**Esc is not a focus key.** It never switches panes; clear / rewind / mid-turn policy owns bare Esc.

## Escape policy and timing

Bare Esc (no modifiers) is handled by a dedicated policy before generic bindings. First-press **steal-Esc** wins for overlays, modals, slash/`@`/completion dropdowns, history and scrollback search, text selection, link highlight, voice, and empty-composer exit from Bash (`!`) / Remember (`#`) / Feedback modes (even mid-turn).

| State | Gesture | Effect |
|-------|---------|--------|
| Turn running | `Esc` | Swallowed (does **not** cancel). Use `Ctrl+C` or palette cancel. |
| Turn cancelling | `Esc` | Re-sends cancel (retry if ack lost). `Ctrl+C` escalates toward quit. |
| Idle, non-empty prompt (text or image chips), **prompt focused** | **2× Esc within 800ms** | Clear prompt; text saved to prompt history. First press: “press again to clear”. |
| Idle, empty prompt, conversation has user turns, **prompt or scrollback** | **2× Esc within 800ms** | Open rewind picker (same as `/rewind`). First press silent. |
| Idle empty with no turns, or scrollback with draft / moded composer / needs-input overlay / history search open | `Esc` | Swallowed no-op |

Default clear/rewind window is **`PendingAction::ESC_DOUBLE_PRESS_TTL` = 800ms**. Tests may override via `GROK_ESC_DOUBLE_PRESS_MS` (clamped; production users should keep the default).

### Ctrl+C vs Esc

| Situation | `Ctrl+C` | `Esc` |
|-----------|----------|-------|
| Mid-turn, non-empty draft | Clear draft; turn keeps running | No-op (swallowed) |
| Mid-turn, empty prompt | Cancel turn | No-op while running; retry cancel only if already cancelling |
| Idle, non-empty prompt | Clear in **one** press | Clear only with **2× within 800ms** |
| Idle, empty + messages | — | Rewind with **2× within 800ms** |

## Agent-level and session chords

| Key | Context | Action |
|-----|---------|--------|
| `Ctrl+P` / `?` | Agent screen | Command palette |
| `Ctrl+M` | Agent (scrollback) | Model picker |
| `Ctrl+M` | Prompt focused | Toggle multiline |
| `Ctrl+C` | Agent screen | Cancel / clear draft (see above) |
| `Ctrl+O` | Agent screen | Toggle always-approve (YOLO) |
| `Ctrl+S` | Agent / welcome | Session picker (`/resume`) |
| `Ctrl+;` (`Ctrl+'` alt; **local macOS VS Code family:** primary `Ctrl+4`) | Agent | Toggle prompt queue when non-empty |
| `Shift+Tab` | Prompt | Cycle Normal → Plan → Always-approve |
| `Ctrl+G` | Agent | Send current task to background |
| `Ctrl+T` / `Ctrl+B` | Agent | Toggle todos / tasks panes |
| `Ctrl+L` | Agent | Extensions modal (**non–VS Code family**); on VS Code family this is mid-turn **send now** |
| `↑` | Empty normal prompt | Open history; `↑`/`↓` browse; `↓` at newest closes |
| `!` | Empty prompt | Enter shell mode |
| `Ctrl+.` / `Ctrl+X` | Agent | Keyboard shortcuts help |
| `F2` / `Ctrl+,` / `Cmd+,` | Agent | Settings modal |
| `Ctrl+Space` / `F8` | Always | Voice dictation (toggle or hold per config) |

**`Ctrl+.`** needs Kitty keyboard protocol (or tmux `extended-keys on`). On VS Code family, VTE, Apple Terminal, Windows Terminal, JetBrains, tmux without extended keys, screen, etc., the UI advertises **`Ctrl+X`** as primary; **`Ctrl+X` always works** as a classic control character. Use `/terminal-setup` if modified keys misbehave under tmux.

## During an active turn

| Input | Behavior |
|-------|----------|
| Plain `Enter` with text | **Queue** a follow-up (held while blocked on background tasks / subagents) |
| Plain `Enter` on empty composer | **Send now** the top queued follow-up |
| Send-now chord (below) | **Cancel current turn** and run your message next (queue/tasks/subagents keep running) |
| Blocked waiting + text + `Enter` | Cancel blocked wait and run your message next |

### Send now (interject) by terminal

| Terminal | Primary | Alternates |
|----------|---------|------------|
| Default | `Ctrl+Enter` | `Ctrl+I` |
| Apple Terminal | `Ctrl+O` | `Ctrl+Enter`, `Ctrl+I` |
| VS Code family (VS Code, Cursor, Windsurf, Zed) | **`Ctrl+L`** | *(none)* |

In multiline mode, `Shift+Enter` / `Alt+Enter` send while plain `Enter` inserts a newline — except empty composer mid-turn with a queue, where plain `Enter` still force-sends the top row. Queue follow-ups without stopping the agent; use send-now only when you want “stop and take this”.

WezTerm needs `enable_kitty_keyboard = true` for modified Enter. On Windows non–VS Code, prefer `Ctrl+I` if `Ctrl+Enter` drops the Ctrl bit. On VS Code family, unbind host **Clear** on `Ctrl+L` so the PTY receives form feed (`\x0c`).

## Global and welcome

| Key | Action | Confirmation |
|-----|--------|--------------|
| `Ctrl+N` | New session (optional git worktree) | Double-press within **1000ms** |
| `Ctrl+Q` | Quit | Double-press within **1000ms** |
| `Ctrl+D` | Quit alt (sole quit key on VS Code family) | Same |

First press arms a pending action (“press again…”); second press within 1000ms executes. Other keys or TTL expiry cancel.

**Welcome screen only:** `Ctrl+W` new worktree (in a git repo), `Ctrl+I` import Claude settings, `Ctrl+Shift+I` dismiss that row. There is **no** key for “return home” — use `/home` (alias `/welcome`).

## VS Code family remaps

In VS Code / Cursor / Windsurf / Zed integrated terminals:

| Default elsewhere | VS Code family |
|-------------------|----------------|
| Quit `Ctrl+Q` (+ `Ctrl+D` alt) | **`Ctrl+D` only** |
| Half page down `Ctrl+D` | **`Shift+D`** |
| Send now `Ctrl+Enter` / `Ctrl+I` | **`Ctrl+L` only** |
| Extensions `Ctrl+L` | Unbound → `/plugins`, `/hooks`, or palette |
| Queue toggle `Ctrl+;` | Local **macOS**: primary **`Ctrl+4`** (`;` / `'` still alts) |

## Paste, images, and mouse

### Paste and drag-and-drop

| Action | macOS | Linux | Windows |
|--------|-------|-------|---------|
| Drag image into prompt | Finder | Files / Dolphin | Explorer |
| Paste copied file path/chip | `Cmd+V` | `Ctrl+V` | `Ctrl+V` |
| Screenshot / “Copy Image” | `Cmd+V` | `Ctrl+V` | **`Alt+V`** |

Non-image files insert an absolute path as text. Windows Terminal’s default `Ctrl+V` drops image clipboards; `Alt+V` is the grok escape hatch. To force `Ctrl+V` images, null the host binding in Windows Terminal `settings.json`.

**Linux:** `Ctrl+V` reads CLIPBOARD only (no PRIMARY fallback). Unmodified **middle click** pastes PRIMARY when `DISPLAY` is set (XWayland needs `xclip` or `xsel`). `Shift+Insert` / `Shift+middle click` are terminal-native paths. Over SSH, use terminal-native paste so the local terminal feeds the PTY.

**Select all:** in-app `Cmd+A` is wired only on **Ghostty** (unbind Ghostty’s own `cmd+a` so the TUI receives it). Elsewhere the terminal keeps native Select All.

Optional: `[ui] mouse_reporting_toggle = true` enables **`Ctrl+R`** (scrollback focused) to toggle mouse capture for native terminal selection.

### Mouse

- Click a scrollback entry to select it  
- Wheel / trackpad scroll (normalized stream; tune via `scroll_mode`, `scroll_lines`, `invert_scroll`, or `GROK_SCROLL_MODE`)  
- Click the prompt to focus it  
- Hover highlight on the prompt (configurable in `pager.toml`)  
- Middle click PRIMARY paste on Linux X11/XWayland  

## Quick reference

**Scrollback — simple (default)**

```
Nav:     Up/Down   Shift+Left/Right (turns)
Scroll:  Ctrl+J/K  PgUp/PgDn  Ctrl+U/D
Focus:   Space or any letter
```

**Scrollback — vim**

```
Nav:     j/k  H/L turns  J/K responses  g/G
Scroll:  Ctrl+J/K  Ctrl+U/D (Shift+D in VS Code)  PgUp/PgDn
Fold:    h/l  e  E    Content: y Y Enter    View: r  Ctrl+E
Focus:   i  Tab  Space
```

**Prompt**

```
Send:     Enter          Newline: Shift+Enter / Alt+Enter
Multiline: Ctrl+M        Paste: Ctrl+V (Alt+V images on Windows)
Leave:    Tab            Cancel: Ctrl+C (empty) / clear draft first
Clear:    Esc Esc (800ms, non-empty idle)
Rewind:   Esc Esc (800ms, empty idle + messages)
```

**Always**

```
Palette: Ctrl+P or ?     Model: Ctrl+M (from scrollback)
YOLO:    Ctrl+O          New: Ctrl+N (×2)    Quit: Ctrl+Q or Ctrl+D
```

## Related pages

<Cards>
  <Card title="Quickstart" href="/quickstart">
    First interactive session: launch, auth, send a prompt, cancel turns, read tool output in scrollback.
  </Card>
  <Card title="Slash commands" href="/slash-commands">
    `/vim-mode`, `/rewind`, `/multiline`, `/plugins`, `/home`, and other command-palette entries.
  </Card>
  <Card title="Configure Grok" href="/configure-grok">
    `config.toml` / `pager.toml` precedence, `[ui].vim_mode`, `simple_mode`, and `grok inspect`.
  </Card>
  <Card title="Plan mode" href="/plan-mode">
    Mode cycle via Shift+Tab and how plan mode interacts with tools and permissions.
  </Card>
  <Card title="Theming" href="/theming">
    TUI appearance, screen modes, and terminal capability constraints that affect key delivery.
  </Card>
  <Card title="Troubleshooting" href="/troubleshooting">
    tmux, SSH, Kitty keyboard protocol, OSC 52 clipboard, and terminal diagnostics.
  </Card>
  <Card title="Permissions and safety" href="/permissions-and-safety">
    Always-approve (YOLO) and how tool authorization interacts with cancel and send-now.
  </Card>
  <Card title="Sessions" href="/sessions">
    New / resume / rewind lifecycle behind Ctrl+N, Ctrl+S, and Esc Esc rewind.
  </Card>
</Cards>
