Synced from monorepo

Synced from monorepo

Changes:
- Cache growing transcripts on the messages backend
- Tell the model when a wait was clamped instead of re-inviting it
- Stop the stationarity nudge from claiming results are identical
- Deliver the stationarity nudge after the tool result
- Run auth provider commands through the platform shell (fixes Windows)
- Keep monitor tool stdout short and prescriptive
- Use UUIDs for analytics event insert IDs
- Stop crashing at startup when the host runs out of threads
- Delete the current session from within the session
- Add project forking-settings toggle (backend and deploy-time control)
- Reap a session’s bash and background commands when it closes
- Reap a session’s hook child processes when it closes
- Track coding-data consent decisions
- Fail open the access gate to stop false CLI paywalls
- Ship Agent Dashboard user guide
- Enable doom-loop recovery by default
- Kill agent children and the idle inhibitor when the parent process dies
- Fix multi-process credential wipe and orphaned session log writers

Source-Revision: 6372e41d828b8a6ee82c29e01a69e27ec895cca9
This commit is contained in:
grokkybara[bot] 2026-07-29 17:17:54 +00:00
commit 500129c714
89 changed files with 3841 additions and 771 deletions

View file

@ -212,6 +212,7 @@ Actions available from any screen.
| Key | Alt Key | Action | Confirmation |
|-----|---------|--------|-------------|
| `Ctrl+N` | | Create a new session (optionally in a git worktree) | Yes (double-press within 1000ms) |
| `Ctrl+\` | | Open or toggle the [Agent Dashboard](23-dashboard.md) | No |
| `Ctrl+Q` | `Ctrl+D` | Quit the application | Yes (double-press within 1000ms) |
**VS Code family terminal** (VS Code, Cursor, Windsurf, Zed integrated terminals): `Ctrl+Q` is captured by the host, so Grok makes **`Ctrl+D` the sole quit key** (`Ctrl+Q` is not bound). Half-page-down is rebound to bare **`Shift+D`**. Mid-turn interject uses **`Ctrl+L`** (no alternates) because `Ctrl+Enter` / `Ctrl+I` do not reliably reach the PTY; extensions are opened via `/plugins` instead of `Ctrl+L`.
@ -239,6 +240,30 @@ Bindings that only fire on the welcome screen (before any agent session is open)
---
## Agent Dashboard
Bindings while the [Agent Dashboard](23-dashboard.md) is focused (`Ctrl+\` or `/dashboard`).
| Key | Action |
|-----|--------|
| `↑` / `↓`, `j` / `k` | Navigate agent rows (selecting a row opens peek) |
| `Enter` | Open the selected agent, or send a typed peek reply / dispatch prompt |
| `Ctrl+S` | Reply or dispatch **and** attach to that agent |
| `Ctrl+/` | Toggle search / filter mode |
| `Ctrl+R` | Rename the selected agent |
| `Ctrl+T` | Pin / unpin |
| `Ctrl+G` | Toggle grouping (state ↔ working directory) |
| `Ctrl+X` | Stop a running turn, or press twice within 2s to close the session |
| `Ctrl+O` | Toggle always-approve on the selected agent |
| `Tab` | Toggle focus between the list and the dispatch / peek input |
| `Esc` | Step back (cancel search → close peek → clear filter → unfocus → unselect → exit) |
| `Ctrl+\` | Exit the dashboard (or return from an attached agent) |
| `Ctrl+.` (alt: `?`) | Shortcuts cheatsheet |
Details (peek vs dispatch, search prefixes, persistence): [Agent Dashboard](23-dashboard.md).
---
## Command Palette
Press `Ctrl+P` or `?` to open the command palette -- a searchable list of actions. The palette shows:

View file

@ -18,6 +18,12 @@ Start a fresh session and clear the current conversation. Alias: `/clear`.
Open the session picker to reload a previous session from disk.
### `/dashboard`
Open the [Agent Dashboard](23-dashboard.md): live roster of top-level sessions in this pager (peek, reply, dispatch, pin, rename, stop, attach). Aliases: `/agents-dashboard`, `/sessions`.
Not `/config-agents` (alias `/agents`), which manages agent *definitions* and personas. Hidden in minimal mode; disable with `GROK_AGENT_DASHBOARD=0` or `[dashboard].enabled = false`.
### `/compact [context]`
Compress conversation history to reclaim context-window space. Pass a note to tell Grok what to keep:
@ -80,6 +86,12 @@ Quit the application. Alias: `/exit`.
Leave the current session and return to the welcome screen. Alias: `/welcome`.
### `/delete`
Delete the current session's history and return to the welcome screen. Confirms first.
To delete a session you are not in, open `/resume` and press `d` then `y`.
### `/rename`
Rename the current session. Alias: `/title`.
@ -369,6 +381,8 @@ Open the Claude import modal to bring over `~/.claude` settings: permissions, en
Open the agents modal to view and manage agent definitions, set the default, and switch the active one. Alias: `/agents`.
Not the live multi-session [Agent Dashboard](23-dashboard.md) (`/dashboard` / `Ctrl+\`).
### `/personas`
Create, edit, and delete personas. A subagent can apply a persona to shape how it behaves.

View file

@ -62,6 +62,14 @@ End the session and quit Grok:
Alias: `/exit`. To leave the current session but stay in Grok, use `/home` to return to the welcome screen.
### Delete the current session
```
/delete
```
Confirms, then permanently removes the session history and returns to the welcome screen. From `/resume`, press `d` then `y` on a row to delete a session you are not currently in.
---
## Resuming Sessions
@ -78,7 +86,7 @@ This opens a session picker that lists recent sessions for the current workspace
Typing in the picker filters the list by title and also searches your conversation content as you type; content matches appear under an "Extended search results" heading. Press `Ctrl+/` to search immediately without the brief pause.
To switch between, rename, or close the sessions that are currently active (the parent session and any forks), use `/dashboard` (or its alias `/sessions`) instead.
For the live top-level sessions in this pager (parent and forks) — switch, rename, peek, dispatch, or close — use the [Agent Dashboard](23-dashboard.md): `/dashboard` (aliases `/sessions`, `/agents-dashboard`) or `Ctrl+\`.
### From the Command Line

View file

@ -1,22 +1,26 @@
# Agent Dashboard
The Agent Dashboard is a centralised, agent-native overview of every
top-level session you have in flight — your local sessions and forks
— grouped by state, with peek, attach, and dispatch from one screen.
Subagents are not listed here: they run under their parent session,
which already shows when work is in flight.
The Agent Dashboard lists every top-level session in this pager process —
local sessions and forks — grouped by state. From one screen you can peek,
reply, attach, pin, rename, stop, or dispatch a new agent. Subagents are not
listed; they run under their parent, which already shows when work is in
flight.
Not the agents modal (`/config-agents` / `/agents` — definitions and
personas), the session picker (`/resume` / `Ctrl+S` — past conversations on
disk), or the workflows run UI (`/workflows`).
---
## Opening the dashboard
Three entry points, all opening the same view:
- **`grok dashboard`** — launches the TUI directly into the dashboard.
- **`grok dashboard`** — launch the TUI into the dashboard.
- **`/dashboard`** (aliases **`/agents-dashboard`**, **`/sessions`**) — open
from inside an active session.
- **Ctrl+\\** — same as the slash command, two keystrokes. Configurable
in `~/.grok/config.toml` under `[keybindings]` like every other shortcut.
from inside a session.
- **`Ctrl+\`** — same view as the slash command.
Hidden in minimal mode. Set `GROK_AGENT_DASHBOARD=0` or
`[dashboard].enabled = false` to disable.
---
@ -35,46 +39,36 @@ Three entry points, all opening the same view:
↑/↓ select (peek) · Enter open · Ctrl+R rename · Ctrl+T pin · Ctrl+X stop · ? help · Esc new
```
Each row is a top-level agent (subagents aren't shown — they run under
their parent). Rows are sorted by state (Needs input → Working → Idle →
Inactive → Completed → Failed) so same-state rows sit adjacent, or by
working directory (toggle with `Ctrl+G`). **Inactive** holds roster-only
sessions — idle/dormant sessions owned by other pager processes that
haven't been loaded in this one — so **Idle** stays focused on the
sessions you're actively cycling between. Because it's background noise,
**Inactive starts collapsed** (expand it with `→` / click — see below).
Each row is a top-level agent. Sort by state (Needs input → Working → Idle →
Inactive → Completed → Failed) so same-state rows sit together, or by working
directory (`Ctrl+G` toggles). **Inactive** is roster-only sessions owned by
other pager processes that this process has not loaded — background noise, so
the section **starts collapsed** (expand with `→` / click).
To keep the **Idle** group scannable, only the most recent idle agents
stay visible — the 8 freshest, plus any active within the last hour. The
rest fold into a **"N more"** row (marked with a `+` / `-` toggle) at the
bottom of the group; select it and press `Enter` / `→` (or click it) to
reveal them all, and `←` to re-fold. The Idle header always shows the true total. Folding is
suspended while a filter or search is active (so every match shows).
To keep **Idle** scannable, only the most recent idle agents stay visible —
the 8 freshest, plus any active within the last hour. The rest fold into a
**"N more"** row at the bottom of the group; select it and press `Enter` /
`→` (or click) to expand, `←` to re-fold. The Idle header always shows the
true total. Folding is suspended while a filter or search is active.
The state icon matches Grok Build's sibling views (
`tasks_pane`):
State icons match other session lists in Grok Build:
- `⋅`/`:`/`⸬`/`⁙` — animated spinner for **Working** rows.
- `⋅`/`:`/`⸬`/`⁙` — animated spinner for **Working**
- `●` — filled circle for **Needs input**, **Completed**, **Failed**,
**Blocked**. Colour communicates the state (yellow / green / red /
amber).
- `○` — hollow circle for **Idle** and **Inactive** rows.
**Blocked** (color: yellow / green / red / amber)
- `○` — hollow circle for **Idle** and **Inactive**
A row stays in **Working** while it has live background work even if its
turn has finished — a running background task, a `monitor`, or an active
scheduled `/loop`. The activity line says what's running (e.g.
`1 monitor · 2 loops still running`), since each can wake the agent for a
new turn.
A row stays **Working** while it has live background work even if its turn
has finished — a background task, a `monitor`, or an active scheduled
`/loop`. The activity line says what is still running (for example
`1 monitor · 2 loops still running`).
There are no inline group headers — the sort order keeps same-state
rows adjacent and the per-row dot+colour communicates which group
each row belongs to (matching other session lists).
There are no inline group headers; sort order keeps same-state rows adjacent,
and the per-row dot + color shows the group.
The dispatch input shares the same `PromptWidget` chrome as the
agent view's prompt (rounded box, `` prefix, accent border, info
line). Pressing `Ctrl+/` flips it into **search mode**: the ``
prefix becomes a yellow `Search:` and whatever you type live-filters
the row list instead of being dispatched.
The dispatch input uses the same prompt chrome as the agent view. Press
`Ctrl+/` to flip it into **search mode**: the `` prefix becomes a yellow
`Search:` and typing live-filters the list instead of dispatching.
---
@ -82,248 +76,185 @@ the row list instead of being dispatched.
| Key | Action |
| --- | --- |
| `↑` / `↓`, `j` / `k` | Navigate rows AND section titles (selecting a row opens its peek panel) |
| `→` / `←` (on a section title) | Expand / collapse the section (shows / hides its rows); `l` / `h` in vim mode |
| `↑` / `↓`, `j` / `k` | Navigate rows and section titles (selecting a row opens peek) |
| `→` / `←` (on a section title) | Expand / collapse the section (`l` / `h` in vim mode) |
| `Enter` (on a section title) | Toggle the section collapsed / expanded |
| `Enter` (empty reply) | Open the selected agent's conversation full-screen (details view) |
| `Ctrl+S` | Send the peek reply AND open the agent (or dispatch + attach a new session) |
| `Shift+Enter` / `Alt+Enter` | Insert a newline in the reply / dispatch input (multiline compose) |
| `1``9` | Answer a pending permission / ask question (when the peek shows options) |
| `Enter` (empty reply) | Open the selected agent full-screen (details view) |
| `Ctrl+S` | Send the peek reply and open the agent (or dispatch and attach a new session) |
| `Shift+Enter` / `Alt+Enter` | Newline in the reply / dispatch input |
| `1``9` | Answer a pending permission / ask question when peek shows options |
| `Enter` (typed reply) | Send / queue the reply to the selected agent |
| `/` | Types a literal `/` into the prompt |
| `Ctrl+/` | Toggle search mode (live-filter the rows) |
| `/` | Literal `/` into the prompt |
| `Ctrl+/` | Toggle search mode (live-filter rows) |
| `Ctrl+R` | Rename selected row |
| `Ctrl+T` | Pin / unpin |
| `Ctrl+G` | Toggle grouping (state ↔ directory) |
| `Ctrl+X` | Stop / kill (two presses within 2s to close a session) |
| `Shift+↑` / `Shift+↓` | Reorder pinned rows |
| `Esc` | Step back one level: cancel search → close peek (clear reply draft, then unselect) → clear filter → **unfocus the dispatch input** (so `↑`/`↓`, `j`/`k` navigate the list) → unselect row (→ `[+ New Agent]`) → exit dashboard. Esc never clears your typed dispatch draft — use `Ctrl+U` / `Ctrl+C` for that |
| `Ctrl+\` | Return to the dashboard from the details view, or exit dashboard |
| `Ctrl+.` (alt: `?`) | Open the keyboard shortcuts cheatsheet. Footer advertises `?` when `Ctrl+.` cannot be delivered. Bare `?` opens help when list-focused or the draft is empty (otherwise types); `Ctrl+X` remains stop |
| `Esc` | Step back: cancel search → close peek → clear filter → unfocus dispatch → unselect row → exit. Never clears a typed dispatch draft (`Ctrl+U` / `Ctrl+C` for that) |
| `Ctrl+\` | Return from details view, or exit dashboard |
| `Ctrl+.` (alt: `?`) | Keyboard shortcuts cheatsheet. Footer shows `?` when `Ctrl+.` cannot be delivered. Bare `?` opens help when list-focused or the draft is empty |
When grouping by state, each group has a **section title** (e.g. `Working`,
`Idle`) with a `▸`/`▾` disclosure marker. Section titles are part of the
up/down navigation: select one and press `→` to expand it (showing its rows)
or `←` to collapse it — `l` / `h` do the same when vim mode is on.
**Clicking** a section title toggles it, and **hovering**
brightens its text. Collapse state is remembered while the dashboard stays open.
The **Inactive** section starts collapsed by default each time the pager
starts; expanding it sticks until you quit.
When grouping by state, each group has a **section title** (for example
`Working`, `Idle`) with a `▸`/`▾` marker. Select a title and press `→` /
`←` to expand or collapse (`l` / `h` in vim mode). Click toggles; hover
brightens. Collapse state is remembered while the dashboard stays open.
**Inactive** starts collapsed each time the pager starts; expanding it sticks
until you quit.
Opening a row shows the agent's conversation in the **details view**:
a single top header row (the agent name on the left, `{i}/{n} [][]
[Dashboard]` cycle/close affordances on the right) sits above the conversation,
which renders **full-width** — no bordered modal frame — so the prompt
position and overall padding match the dashboard list view. All key
presses route to the attached agent; `Esc` / `Ctrl+\\` (or the `[Dashboard]`
affordance) return to the dashboard, the `[]` / `[]` chips cycle to
the previous / next agent, and the agent's shortcuts bar shows a
`Ctrl+\\: back to dashboard` hint. Quick gotcha — `Esc` only returns to
the dashboard; typing `/exit` inside the agent actually closes the
underlying session (returning to the dashboard with a "Session closed"
toast).
Opening a row shows the agent's conversation in the **details view**: a top
header (agent name; `{i}/{n}` cycle chips and `[Dashboard]` on the right)
above a full-width conversation — no bordered modal — so padding matches the
list view. Keys go to the attached agent; `Esc` / `Ctrl+\` (or `[Dashboard]`)
return to the dashboard; `[]` / `[]` cycle agents. The shortcuts bar shows
`Ctrl+\: back to dashboard`. Gotcha: `Esc` only returns; `/exit` inside the
agent closes the session (dashboard toast: "Session closed").
`Ctrl+X` in the details view is state-dependent. While a **turn is
running** it cancels the turn — the same behaviour as `Ctrl+C`,
including the keep-subagents prompt — and never touches the session
itself, so mashing it to stop a turn can't close anything. In any
other state — **idle**, a slash command in flight (commands can't
be cancelled yet), or a cancel still pending — `Ctrl+X` arms a
confirmation: the shortcuts bar flips to "press Ctrl+x again to
close this session", and a second press within 2 seconds closes the
session and returns you to the dashboard. Pressing any other key
cancels the confirmation, and a turn that starts inside the window
downgrades the confirmed press to a cancel instead of closing.
(On terminals where `Ctrl+X` doubles as the shortcuts-cheatsheet
binding, the cheatsheet stays reachable via `Ctrl+.` inside the
details view.)
`Ctrl+X` in the details view is state-dependent. While a **turn is running**
it cancels the turn (same as `Ctrl+C`, including the keep-subagents prompt)
and never closes the session. Otherwise — **idle**, a slash command in
flight, or a cancel still pending — `Ctrl+X` arms a confirmation: press again
within 2 seconds to close the session and return to the dashboard. Any other
key cancels the confirmation; a turn that starts inside the window turns the
confirmed press into a cancel instead. (If `Ctrl+X` is also the cheatsheet
binding on your terminal, use `Ctrl+.` inside the details view.)
For the full behavioural specification (including the registry-lookup
rules and the mouse-event intercept matrix) see plan
[§3.10](../../plan/agent-dashboard.md) "Keybindings (v1)" — the user
guide here is intentionally short and cross-references the plan as
the source of truth.
See [Keyboard Shortcuts](03-keyboard-shortcuts.md#agent-dashboard).
All shortcuts are registered under `When::DashboardFocused` and can be
rebound via `~/.grok/config.toml`.
---
## Completing or closing a session
There is **no** “mark completed” command. Row state is derived from the agent:
- **Completed** / **Failed** when work ends on its own (turn finished and no
background task / monitor / `/loop` still running).
- **`Ctrl+X` once** while a turn is running cancels the turn.
- **`Ctrl+X` twice** (within 2s) on an idle / stopped row **closes** the
session and removes it from the live roster.
- In the details view, `/exit` also closes the session (Esc only returns).
Use close/stop when you want a row gone; there is no manual complete flag.
---
## Dispatch input
The bottom textarea **always spawns a NEW session** — it is never a
reply target. A selected row is the overview's navigation cursor, not a
reply destination; to talk to an existing agent, open it (navigate +
`Enter`, or click) and reply inside its own view.
The bottom textarea **always spawns a new session**. A selected row is the
navigation cursor, not a reply target — open an agent to talk to it.
Enter handler:
- Free text → new top-level session seeded with the prompt. Text is never
treated as a filter (even if it starts with `/`, `s:`, `a:`, or `#`);
filtering is `Ctrl+/` search mode. A leading `/` runs a pager-global slash
command.
- Empty input → open the selected row, or create a new agent when
`[+ New Agent]` is focused.
- Free text → creates a new top-level session, seeded with the prompt.
Text is **never** reinterpreted as a filter — a prompt may start with
`/`, `s:`, `a:`, or `#` and still dispatches verbatim (filtering is
the explicit `Ctrl+/` search mode). A leading `/` runs a pager-global
slash command.
- Empty input → opens the selected row (`Attach`), or creates a new
agent when the `[+ New Agent]` button is focused.
`Ctrl+S` after typing dispatches **and** attaches; plain `Enter` stays on the
dashboard so you can dispatch several sessions. `Shift+Enter` / `Alt+Enter`
insert a newline; the box grows with the draft (up to a cap, then scrolls).
Press `Ctrl+S` after typing a prompt to dispatch AND attach
(jump into the new session); plain `Enter` stays on the dashboard so
you can dispatch several sessions in a row. `Shift+Enter` / `Alt+Enter`
insert a newline for a multi-line prompt — the box **grows in height**
as you add lines (up to a cap, after which it scrolls), so the whole
draft stays visible.
The dispatch input accepts any non-empty prompt; an empty /
whitespace-only prompt is ignored. Prompts above 64 KiB are rejected
with a toast.
Empty or whitespace-only prompts are ignored. Prompts above 64 KiB are
rejected with a toast.
### Focus: input bar ↔ overview list (`Tab`)
The dashboard has two focus areas — the **dispatch input bar** (typing)
and the **overview list** (navigating). `Tab` toggles between them; the
inactive input dims its border and hides its caret.
Two focus areas: the **dispatch input** and the **overview list**. `Tab`
toggles between them; the inactive input dims its border and hides its caret.
On open, focus defaults to the **overview list** when at least one agent
exists (so `↑`/`↓` / vim `j`/`k` navigate immediately). With **no**
agents, focus stays on the **dispatch input** so you can type a first
prompt right away. Either way, the `[+ New Agent]` button is the cursor
target (no agent row is pre-selected).
exists (so `↑`/`↓` / vim `j`/`k` navigate immediately). With **no** agents,
focus stays on the **dispatch input**. Either way, the cursor starts on
`[+ New Agent]` (no agent row pre-selected).
- **Input focused**: type to compose a new-session prompt. `↑`/`↓`
navigate the row list when the prompt is empty (a convenience),
otherwise move the caret. `Esc` unfocuses the input → overview list
(your typed draft is kept) so you can navigate straight away.
- **Overview focused**: `↑`/`↓` — and, in **vim mode**, `j`/`k` — move
between agent rows. `Enter` opens the highlighted agent (on
`[+ New Agent]`, it sends a typed draft, else creates a new session).
`Esc` **stays on the list** and steps back — clearing an active filter,
then unselecting the row (→ `[+ New Agent]`), then exiting the
dashboard. `Tab` or `i` (vim) — or any other printable key — return to
the input.
- **Input focused**: type a new-session prompt. Empty prompt: `↑`/`↓`
navigate rows; non-empty: move the caret. `Esc` unfocuses to the list
(draft kept).
- **Overview focused**: `↑`/`↓` (and vim `j`/`k`) move between rows. `Enter`
opens the highlighted agent (on `[+ New Agent]`, sends a typed draft or
creates a new session). `Esc` stays on the list and steps back — clear
filter, then unselect (→ `[+ New Agent]`), then exit. `Tab`, `i` (vim), or
any printable key returns to the input.
---
## Peek panel
The peek panel is shown **by default whenever an agent row is
selected** — it **replaces** the new-session dispatch box. With no row
selected (the `[+ New Agent]` button focused, or after `Esc`), the
dispatch box returns for starting a new session. So selecting a row is
how you talk to an existing agent; deselecting is how you start a new
Selecting an agent row shows the **peek panel** in place of the dispatch box.
With no row selected (`[+ New Agent]`, or after `Esc`), the dispatch box
returns. Select a row to talk to an existing agent; deselect to start a new
one.
The panel shows, top to bottom, a header (the **last response type**
`Thinking` / `Thought` / `Response` / `Edit` / `Read` / `Bash` / … — on
the left, **time** on the far right), the most recent response
(**word-wrapped** to fit, up to ~3 rows), and a live ` reply` input. A
`…` marker appears on the last row only when there's more than fits.
Top to bottom: header (**last response type** — `Thinking` / `Thought` /
`Response` / `Edit` / `Read` / `Bash` / … — and **time**), the most recent
response (word-wrapped, up to ~3 rows; `…` when truncated), and a live
` reply` input.
The selected agent's **model** and, when it's in always-approve (yolo)
mode, an **`always-approve`** flag are shown on the panel's **bottom
border** (bottom-right) — the same config-badge slot the new-session
dispatch box uses. This holds in the question / approval modes too, so
the model and approval mode are always in view while you answer. (The
dashboard list rows no longer repeat the model or an always-approve badge,
keeping the list compact.)
The selected agent's **model** and, in always-approve (yolo) mode, an
**`always-approve`** flag sit on the panel's bottom border (same badge slot as
the dispatch box), including while answering questions. List rows no longer
repeat model or always-approve badges.
**`Shift+Tab` cycles the peeked agent's mode** (Normal → Plan →
Always-approve → Normal) — the same cycle as Shift+Tab inside that agent's
chat view, applied to the **live** agent (the badge updates to match).
This differs from the new-session dispatch box, where Shift+Tab only
stages the mode for the *next* agent.
Always-approve → Normal) on the **live** agent. On the dispatch box,
Shift+Tab only stages mode for the *next* agent.
Unlike the dispatch box (which only ever spawns new sessions), the
peek's reply **talks to the selected agent**:
Unlike dispatch (new sessions only), peek reply **talks to the selected
agent**:
- **Type into ` reply`, then `Enter`** to send. An **idle** agent
starts the turn immediately; a **busy** agent **queues** the message
so it sends after the current turn finishes (the same queue/drain
behaviour as the agent view's own prompt). `Ctrl+S` replies AND
opens the agent's detail view; `Shift+Enter` / `Alt+Enter` insert a
newline (multiline compose) and the reply **grows in height** to fit
the draft (up to a cap, then it scrolls).
- With an **empty** reply, `Enter` opens the agent.
- **`↑`/`↓` move the caret within the reply** once it has content (so you
can edit a multi-line draft). While the reply is **empty** (or
unfocused via `Tab`), `↑`/`↓` instead **switch the selected agent**
the panel follows the selection cursor and refreshes live, and the
switch clears any half-typed draft so a reply can't land on the wrong
agent. (`Tab` to the row list to navigate agents while a draft is in
the reply.)
- **`Esc` unselects**: it first clears a typed reply, then deselects the
row and focuses the `[+ New Agent]` button (bringing back the
new-session input).
- **`Tab`** toggles focus between the reply input and the row list: an
unfocused reply dims its border and hides the caret; a printable key
re-focuses it and starts composing.
- The reply is a **full prompt editor** (the same component as the
dispatch box and the agent prompt): pasting multi-line text folds
into a `[Pasted: N lines]` chip with the same preview overlay and
expand affordances as the agent prompt (`Enter` / double-click /
paste-again), mouse click / drag place the caret and select text,
and the usual editing chords work (word navigation, `Ctrl+A`/`Ctrl+E`,
`Alt+Backspace`, `Ctrl+W`/`Ctrl+U`/`Ctrl+K`, undo, Shift+arrow
selection, `Ctrl+Shift+V` inline paste).
Typing **`@`** opens the file-context picker rooted at the **peeked
agent's** working directory (so `@path` resolves against the agent
you're replying to); its dropdown floats **above** the panel and
`↑`/`↓`/`Tab`/`Enter`/`Esc` drive it while it's open.
Dashboard chords (`Ctrl+X` stop, `Ctrl+T` pin, `Shift+↑/↓` reorder,
…) still win over the editor while the panel is open.
- When a **permission / ask-tool question** is pending, the ` reply`
row is hidden and the options are listed instead: **`↑`/`↓` move the
highlighted option** (marked with `▸`) and **`Enter` answers** it.
**`1``9`** still answer an option directly. (While answering, the
arrows pick options rather than switching agents.)
- The **free-text row** accepts an inline typed answer (just like the
chat panel): the permission **"No" / reject** option ("No, reject
(type to add feedback)") and the ask-tool **"Other"** row ("Other
(type your own answer)"). Type on it and `Enter` sends the rejection +
message / the free-text answer.
- This also covers the agent's **Ask tool** (`AskUserQuestion`): its
options + the "Other" row show in the peek, answered the same way.
**Multi-question** forms are walked one question at a time — a `(i/N)`
marker shows progress and each answer advances to the next, submitting
on the last. (Forms with a **multi-select** question are left to the
agent's own view — open the agent to answer those.)
- **Type into ` reply`, then `Enter`** to send. Idle agents start immediately;
busy agents **queue** the message (same as the agent view prompt). `Ctrl+S`
replies and opens the detail view; `Shift+Enter` / `Alt+Enter` insert a
newline (reply grows with the draft).
- Empty reply + `Enter` opens the agent.
- **`↑`/`↓` move the caret** once the reply has content. While empty (or
unfocused via `Tab`), `↑`/`↓` **switch the selected agent** — the panel
follows, and a half-typed draft is cleared so it cannot land on the wrong
agent. (`Tab` to the list to navigate while a draft is in the reply.)
- **`Esc` unselects**: clear a typed reply first, then deselect and focus
`[+ New Agent]`.
- **`Tab`** toggles focus between reply and row list; a printable key
re-focuses the reply.
- Full prompt editor (same as dispatch / agent prompt): multi-line paste
chips, mouse select, word navigation, `Ctrl+A`/`Ctrl+E`, `Alt+Backspace`,
`Ctrl+W`/`Ctrl+U`/`Ctrl+K`, undo, Shift+arrow selection, `Ctrl+Shift+V`
inline paste. **`@`** opens the file picker rooted at the **peeked agent's**
working directory; the dropdown floats above the panel. Dashboard chords
(`Ctrl+X` stop, `Ctrl+T` pin, `Shift+↑/↓` reorder, …) still win while the
panel is open.
- Pending **permission / ask-tool** question: ` reply` hides; options list
instead. **`↑`/`↓` highlight**, **`Enter` answers**, **`1``9`** answer
directly. Free-text **No / reject** and ask-tool **Other** accept a typed
answer on the free-text row. Multi-question Ask forms walk one at a time
(`(i/N)`); multi-select forms need the agent's own view.
The panel only renders when the terminal is tall enough; on very short
terminals the dispatch box shows even with a row selected.
On very short terminals the panel may not fit; the dispatch box stays even
with a row selected.
---
## Search / filter (`Ctrl+/`)
Filtering lives behind an explicit **search mode** so normal typing
always dispatches. Press `Ctrl+/` to toggle it: the prompt prefix
flips from `` to a yellow `Search:` and every keystroke live-filters
the row list.
`Ctrl+/` toggles search mode so normal typing always dispatches. Prefix
flips from `` to yellow `Search:`; every keystroke live-filters the list.
Inside search mode:
- `Enter` — confirm: keep the filter and return to the dispatch prompt.
- `Esc` or `Ctrl+/` — cancel: clear the filter and exit search.
- `↑` / `↓` — navigate filtered rows.
- `Enter`**confirm**: keep the filter applied and return to the
dispatch prompt (rows stay filtered; `Esc` later clears them).
- `Esc` or `Ctrl+/`**cancel**: clear the filter and exit search.
- `↑` / `↓` — navigate the filtered rows.
Prefixes (only inside search mode):
The query supports the same prefixes as before (they are only honoured
*inside* search mode now):
- `a:<name>` — filter by agent label (case-insensitive substring,
matches persona / role).
- `s:<state>` — filter by row state. Accepts `working`, `idle`,
`completed`, `failed`, `needs-input`, `blocked` and synonyms
(`busy`/`running`/`done`/etc.).
- `#<text>` — substring match on `#<text>` (matches the literal
`#` in labels; reserved for future PR filtering).
- anything else — plain substring match over label + working dir.
- `a:<name>` — agent label (case-insensitive substring; persona / role).
- `s:<state>` — row state: `working`, `idle`, `completed`, `failed`,
`needs-input`, `blocked` and synonyms (`busy`/`running`/`done`/etc.).
- `#<text>` — substring match on `#<text>` (literal `#` in labels).
- anything else — substring over label + working dir.
---
## Persistence
Per-user dashboard preferences live under `[dashboard]` in
`~/.grok/config.toml`:
Per-user preferences under `[dashboard]` in `~/.grok/config.toml`:
```toml
[dashboard]
@ -333,19 +264,5 @@ pinned = ["top:<session_id>", "sub:<parent_session_id>:<child_session_id>"]
reorder = ["top:<session_id>"]
```
Pinned/reorder entries are keyed by **session id**, not by the
per-process `AgentId(usize)`, so they survive restarts and don't
attach to whatever agent happens to share the old slot number.
Set `GROK_AGENT_DASHBOARD=0` to force-disable the feature for a single
pager invocation; the slash command and CLI subcommand will print a
friendly toast.
---
## Phase 4 (out of scope for v1)
The current dashboard lists only agents owned by **this** pager
process. The plan's Phase 4 ("supervisor / `grok --bg`") would list
sessions that survive pager exit — that's a separate roadmap and not
shipped yet.
Pinned/reorder entries use **session id** (not a per-process agent slot), so
they survive restarts.