Scrollback TUI
The dim interactive terminal UI comes in two forms: fullscreen and scrollback. This page covers the scrollback form; for the other one see Fullscreen TUI.
Scrollback writes straight onto the terminal's main screen: the conversation grows downward line by line, the same way git log or npm test output does, and older lines move into the terminal's own scrollback buffer. History belongs to the terminal — scrolling, searching, selecting and copying all use the keys your terminal already gives you; the app does not take them over. When you quit, the whole conversation is still there.
The trade-off: the mouse is off for the entire session (terminal scrolling and mouse reporting are mutually exclusive), and there is no theme switching (lines already written to the terminal cannot be repainted).
When to use it
| Situation | Use |
|---|---|
You want to search the whole conversation with Cmd+F afterwards |
Scrollback |
| You want to drag-select a chunk of output as plain text | Scrollback |
| You want the conversation and your shell commands in one terminal record | Scrollback |
| You work over SSH / tmux | Scrollback |
| You need mouse clicks, themes, centered dialogs | Fullscreen |
Both forms share the same sessions and configuration, and you can switch between them at any time without losing a session.
Launch
# Open the scrollback form
dim tui --scrollback
# Open and resume a specific session
dim tui --scrollback --session <session-id>
Until you set a default form, plain dim opens scrollback.
Make it the default
dim tui --scrollback default
This only writes the setting; it does not open the UI. It prints Default TUI form set to scrollback, after which plain dim starts in scrollback. You can also change it in the app: /settings → Startup UI form.
Switch forms while running
Type /tui and press Enter to switch to the other form; /tui --fullscreen and /tui --scrollback pick a target explicitly. Switching does not start a new session and does not interrupt a running turn.
First time in a directory
The first launch inside a directory asks whether you trust it — project-level .mcp.json and hooks are only loaded once it is trusted. Declining exits without starting a session.
Layout
The terminal splits into two parts: everything above is already committed and belongs to the terminal; everything below is the interactive area that repaints.
── terminal scrollback: wheel / Cmd+F / drag-copy are the terminal's ──
┌────────────────────────────────────────────────────┐
│ ▓▓▓▓ │
│ ▓▓ ▓▓ Welcome to DIM! │
│ ▓▓ ▓▓ Type / for commands · Ctrl+P for palette │
│ ▓▓▓▓ │
│ │
│ Workspace ~/repo │
│ Git branch main │
└────────────────────────────────────────────────────┘
› fix this failing test
◆ Let me look at the failure first.
● Read src/app.test.ts
● Bash npm test -- --filter app
✕ Edit src/app.ts +1 -1
── below repaints continuously ───────────────────────────
∴ checking the test output… ← live region
· Bash npm test 4s
⣾ working 4s
┌─────────────────────────────────────────┐
│ › Ask anything... │ ← composer
└─────────────────────────────────────────┘
esc interrupt ctx 42.0K (33%) model ← status line
Startup commits a configuration summary: working directory, Git branch, current model, approval mode, and one line telling you how your terminal scrolls and searches. It is a one-time snapshot; later setting changes are not written back into it.
Reading the output
Every block starts with a 2-column gutter marking its type, and all lines inside a block are indented past the gutter so a drag-select copies clean text.
| Marker | Meaning |
|---|---|
› |
Your message (tinted full-width, marking the start of a turn) |
◆ |
Model reply |
∴ |
Thinking |
● |
Tool finished |
✕ |
Tool failed |
⚙ |
Subagent / background task notice (prefixed bg ·) |
■ |
Error |
◦ |
Status, compaction, interrupt, approval outcome and other system notices |
Tool blocks show a summary rather than the full output:
● Bash npm test
● Grep "ProviderManager" 12 matches
● Edit src/app.ts +2 -1
12 - const a = 1
12 + const a = 2
● Write src/new.ts (120 lines)
The model reads the complete tool result; you read the summary. That is deliberate — it keeps thousands of output lines from burying the conversation.
Code blocks keep their original fences and get syntax highlighting, with no decoration beyond the shared 2-space gutter; copying one only means stripping those two spaces.
Scrolling, searching, copying
These are your terminal's features, so the keys differ per terminal:
| Terminal | Page back | Search | Copy selection |
|---|---|---|---|
| macOS Terminal / iTerm2 | Cmd+PageUp or wheel |
Cmd+F |
drag / Cmd+C |
| kitty / Ghostty / WezTerm / Alacritty | Shift+PageUp or wheel |
the terminal's own pager search | drag / Ctrl+Shift+C |
| Linux (GNOME / Konsole) | Shift+PageUp |
Ctrl+Shift+F |
Ctrl+Shift+C |
| Windows Terminal | Ctrl+Shift+PageUp |
Ctrl+Shift+F |
drag / Ctrl+Shift+C |
| Inside tmux | prefix+[ for copy-mode |
copy-mode / |
copy-mode Space then Enter |
Jump to top / bottom: Cmd+Home / Cmd+End on macOS, Shift+Home / Shift+End on most terminals, Ctrl+Shift+Home / Ctrl+Shift+End in Windows Terminal, and g / G in tmux copy-mode.
You do not have to memorize this: the startup summary includes a one-line cheat sheet for the terminal you are actually on, and /keys commits the full table into the scrollback so you can search it back later.
The composer
The composer sits at the end of the document and grows from 1 to 7 lines with your content.
| Action | Key |
|---|---|
| Send | Enter |
| New line | Shift+Enter, or Ctrl+J on terminals that do not report it |
Switch AGENT / PLAN mode |
Tab |
| Browse input history (single-line composer) | Up / Down |
| Open the command palette | / or Ctrl+P |
| Mention a skill | $ |
| Mention a file or directory | @, or just type a path; Tab completes directories |
| Paste a clipboard image | Ctrl+V |
| Clear the draft | Esc (idle, no panel open) |
Long text, file paths and images fold into a highlighted token; delete the token to drop the attachment. Input history is stored per working directory.
Panels
Scrollback has no centered dialogs: every panel opens below the composer, same width, same left edge, one at a time.
┌─────────────────────────────────────────────┐
│ › │
└─────────────────────────────────────────────┘
┌ Sessions ─────────────────────── esc close ┐
│ filter: fix_ │
│ › fix test flake 10m ago │
│ composer refactor 2h ago │
│ 1-2 / 23 · enter open · ^R refresh │
└─────────────────────────────────────────────┘
esc interrupt ctx 42.0K (33%) model
| Panel type | Keys |
|---|---|
| List | Type to filter; Up/Down, Home/End, PageUp/PageDown to move; Enter to activate; Esc clears the filter, then closes |
| Form | Tab/Shift+Tab between controls, Left/Right for segmented options, Space to toggle, Enter to run, Esc to go back a step |
Completion (/, $, paths) |
The composer stays editable, typing filters, a space closes the panel |
Every panel carries a hint line with the keys that currently work, so nothing has to be memorized.
Commands
Commands match the fullscreen form, plus two that only exist here:
| Command | What it does |
|---|---|
/keys |
Commits the full key reference (app keys plus your terminal's native keys) into the scrollback |
/queue |
Review and manage messages queued during a run |
Two commands are deliberately absent:
| Command | Why |
|---|---|
/theme |
Lines already written cannot be repainted, so a theme change would leave history in mismatched colors |
/effort |
The reasoning level is adjustable inline in the /models panel with Left/Right |
Everything else is available: /new, /resume, /connect, /models, /approvals, /settings, /mcp, /plugins, /skills, /timeline, /compact, /export, /language, /debug, /tui, /exit.
/resume only lists sessions from the current directory. To open a session from elsewhere, cd there and start the CLI again.
In the /models panel, Left/Right adjusts the thinking level of the focused row and saves immediately; Enter only selects the model and closes the panel.
While a turn is running
After you send, a live region appears above the composer: stable thinking and reply lines keep flowing into terminal history and only the last unfinished line stays live, with running tools and their elapsed time listed underneath.
∴ current unfinished thinking line…
current unfinished reply line…
· Bash npm test 4s
┌─ Queue (2) ─────────────────────────┐
│ › then run lint │
│ › and update the docs │
│ ↑ edit · ctrl+s steer now · /queue │
└─────────────────────────────────────┘
⣾ working 4s
| Goal | How |
|---|---|
| Interrupt this turn | Esc |
| Keep typing while it runs | Just type; Enter puts the message in the queue |
| Edit the newest queued message | ↑ with an empty composer |
| Steer the oldest queued message into this turn | Ctrl+S |
| Manage the queue (delete, steer one by one) | /queue |
| See background work and subagents | Ctrl+O |
One status line stays pinned at the bottom: mode chip, approval mode, run state and branch on the left; context usage and current model on the right.
AGENT ⏵⏵ default :main ctx 42.0K (33%) gpt-5.2
The approval chip is colored by how much you have handed over: default grey, approve for me yellow, full access red.
Approvals and questions
Approval opens below the composer too:
┌ Permission required ────────────────────────┐
│ Bash: rm -rf node_modules │
│ [Allow once] Allow always Reject │
│ y allow · n reject · ←→ move · enter confirm│
└─────────────────────────────────────────────┘
Y allows once, N rejects, Left/Right/Tab moves focus, Enter confirms. The outcome is committed as a ◦ block, so the terminal record is a complete audit trail of what you approved.
For model questions (AskUser): Up/Down moves between options, 1–9 picks the Nth directly, Space toggles, Enter moves to the next question, Tab/Left/Right switches questions, and the Confirm tab submits. Esc cancels the whole prompt.
Keyboard reference
Scrollback uses only Ctrl combinations and unmodified keys — Cmd and Alt are intercepted by terminals themselves.
| Key | Action |
|---|---|
Enter |
Send |
Shift+Enter / Ctrl+J |
New line |
Tab |
Switch AGENT / PLAN |
Ctrl+P |
Command palette (works from any panel) |
Ctrl+O |
Background work panel |
Ctrl+T |
Timeline / message picker |
Ctrl+N |
New session |
Ctrl+V |
Paste clipboard image |
Ctrl+R |
Refresh in the sessions / skills panel |
Ctrl+D |
Delete in the sessions / skills panel |
F2 |
Rename in the sessions panel |
Esc |
Panel: clear filter, then close. Running: interrupt. Idle: clear draft |
Ctrl+C |
First press closes a panel / clears the draft / interrupts; second press exits |
Events are dispatched in the order exit confirm → runtime prompt → panel → composer; once a layer handles a key, lower layers never see it.
Quitting
Press Ctrl+C twice, or type /exit. If work is still running you get a confirm prompt: Enter / Y forces the exit, Esc / N stays.
After quitting, the whole conversation is still in your terminal, and still scrollable, searchable and copyable.
Troubleshooting
I scrolled up and new output disappeared. The terminal is parked where you scrolled to. Use your terminal's jump-to-bottom key, or scroll back down.
Old content looks wrong after a resize. Lines already written are never re-wrapped — terminals disagree on hard-wrap behavior, and re-wrapping would break copy fidelity. New content uses the new width.
Resuming a session does not show older messages. Resume replays only the most recent page (up to 100 messages); earlier history cannot be inserted above what is already on screen, and the boundary is marked explicitly. Use /timeline to reach older content.
Text is unreadable on a light background. Startup probes the terminal background once and picks a dark or light palette. If the probe guesses wrong, use the fullscreen form and pick a theme with /theme.
The mouse does nothing. The mouse is off for the whole session — that is what makes native terminal scrolling work. Every action has a keyboard path; /keys lists them.
DimAgent