Scrollback & Copy
Scrolling
Section titled “Scrolling”Cold-history packing runs in incremental maintenance turns, rather than encoding the entire backlog under one terminal lock. Each turn visits at most 512 rows and packs at most one block per grid, with a 128 KiB shallow-cell target (a single oversized row may exceed that target). This is a work bound, not a guaranteed wall-clock deadline. Visible and recently used history remain directly readable.
On Unix, the existing PTY actor services input and output between continuations. Windows uses bounded app-loop maintenance with a short deadline only while work remains; maintenance alone does not request a redraw. Reflow queues repacking, and new output invalidates an interrupted scan safely. Once the backlog is complete, no maintenance timer remains. Retention and copy semantics are unchanged.
Mouse/trackpad: just scroll over a pane. Apps that enable terminal mouse reporting receive their wheel input; full-screen apps that request alternate scrolling do too. Regular transcripts scroll Luvus’s retained history.
Each pane has a 10 MiB retained-history budget by default. Change it in Settings → Layout → Scrollback memory. Luvus’s Alacritty adapter converts this budget to a conservative row limit at the current pane width, so it protects memory predictably but reports retained bytes as an estimate rather than an exact allocator measurement. Reducing the setting trims existing history immediately; increasing it applies to subsequent output.
Completed rows stay fully lossless but cold history is packed into bounded, shared blocks. Repeated cells use a block-local dictionary, while high-entropy content falls back to direct packed cells. The visible screen and recent 128 history rows stay in the normal mutable representation. Unix schedules packing on a bounded activity deadline inside the existing PTY descriptor actor; Windows uses its coalesced output boundary. This adds no thread or idle polling, and reading old history does not inflate the complete transcript.
Keyboard scroll mode: press Shift+↑ (no prefix needed, so it works
even where macOS eats Ctrl+Space). The status bar switches to SCROLL and
plain keys navigate without reaching the program in the pane:
| Key | Action |
|---|---|
1–9 |
jump through history (1 = oldest, 9 = newest) |
j / k (or ↓/↑) |
line down / up |
f / b (or Space/PageDn/PageUp) |
page down / up |
g / G |
top of history / live bottom |
/ |
search retained output in this exact PTY pane |
q, Esc, 0, or just typing |
back to live |
The inline / search is owned by Luvus, so query and navigation keys never
reach the child process. Type a query and press Enter; retained rows are
scanned synchronously, and the first case-insensitive match at or after the
current viewport is selected (wrapping to the oldest match when needed). Press
Ctrl-I to toggle case sensitivity; sensitive
mode adds Aa after the query, while the default insensitive mode stays
unmarked. Press Ctrl-U while editing or after committing to clear the
query and continue editing without leaving search or moving the viewport.
Matches are highlighted in place like FILE search: the current word uses the
accent color, and other visible hits use amber. Press
n / N for the next / previous match; both wrap within that pane’s
retained rows. Esc while editing or after committing
cancels the search and restores the viewport from before /, leaving keyboard
scroll mode active; press Esc again to return to live output. A no-match
query remains active as 0/0 until canceled. Search retains at most 10,000
matches; a + after the count means additional retained-output matches exist
beyond the navigable set. Terminal output or a pane reflow invalidates committed
coordinates and returns the same query to editing rather than navigating stale
rows.
This pane-local search is separate from the prefix global fuzzy finder. The
configured prefix followed by / still searches sessions, workspaces, tabs,
panes, agents, files, and retained output across the selected Luvus home.
While scrolled, a ↑N badge at the pane’s top-right shows how many lines
up you are, and anything you type snaps back to live first, so you always see
what you’re typing.
Unmodified PageUp and PageDown scroll normal transcript history. When a
terminal app has claimed paging input (for example a full-screen TUI or an
application-cursor pager), Luvus forwards those keys unchanged. Shift+↑,
Shift+PageUp, and prefix scroll shortcuts remain explicit Luvus controls.
Copying
Section titled “Copying”Drag across a pane to select. Release requests a copy; the Copied to Clipboard
toast appears only after a native clipboard helper confirms success. Luvus requests both your native OS clipboard (pbcopy / wl-copy /
xclip / clip) and OSC 52. The terminal must permit OSC 52 clipboard writes;
that escape sequence does not acknowledge whether the clipboard changed.
Soft-wrapped display rows copy as one logical line. Hard line breaks and any
leading indentation inside the selection remain unchanged.
Many agents and other full-screen applications turn on terminal mouse
reporting. Inside such a pane, a plain drag belongs to the application, so
Luvus does not select or copy it. Hold Shift while dragging to select with
Luvus instead. A right-click always opens the Luvus pane menu.
Clipboard helpers run on the client machine, including when attached over
SSH. On Linux, the client uses wl-copy when WAYLAND_DISPLAY is set and
X11 helpers when DISPLAY is set. It preserves the client’s display environment,
including XDG_RUNTIME_DIR and sockets named wayland-1; it does not use the
remote server’s display or guess a socket name. Launch the client from your
desktop terminal with those variables intact. Restarting the background server
does not repair a missing client display environment.
Unix helper work runs off the rendering loop with a two-second timeout per helper. Failed helpers fall through to another applicable helper. Rapid copies retain only the latest pending selection. If all attempted helpers fail, Luvus requests a terminal notification explaining that native copy failed and OSC 52 was requested instead. Failure notifications are queued for the UI thread; an idle thin client shows them with the next server message. Notifications also depend on terminal support. When no native helper applies, OSC 52 remains available without a native-success claim. No clipboard text or helper stderr is logged.
For Wayland troubleshooting, run wl-copy and wl-paste from the same outer
terminal that launches the Luvus client. Check WAYLAND_DISPLAY and
XDG_RUNTIME_DIR there, not just in the detached server. A socket symlink is not
required. Applications inside a pane can also copy with OSC 52 (for example
Claude Code drag-select or printf with a \e]52;c;… sequence). Luvus forwards
those writes through the same client clipboard path as its own selection copy.
OSC 52 read (paste from the host clipboard into a pane) is not enabled. Rapid
pane and selection copies retain only the latest pending text.
For keyboard selection, press Ctrl+Space, then y by default. Change
the second key in Settings → Keys → Copy terminal text. Shift-based V
input always passes through to the terminal, including inside agent prompts. Copy
mode keeps all navigation inside Luvus. Its word motions are whitespace-delimited,
so w and e behave like vim’s W and E:
| Key | Action |
|---|---|
arrows or h/j/k/l |
character and line movement |
w / e / B |
next word start / word end / previous word start |
Space or f / b |
page down / up |
Ctrl+D / Ctrl+U |
half a page down / up when search is closed |
/ |
search retained output from the copy cursor |
g / G |
oldest / newest retained row |
1–9 then a motion |
repeat it, so 12j moves twelve rows |
N then g or G |
jump to retained row N, like vim’s NG |
v |
reset the selection anchor at the cursor |
y or Enter |
copy and return to live output |
q or Esc |
cancel and restore the viewport where copy mode began |
Copy mode’s / search uses the same exact, case-insensitive matching and
word-level highlights as SCROLL search. Press Enter to commit; the copy
cursor moves synchronously to the first match at or after its current position.
The selection
anchor stays unchanged. Use n / N to move between matches and
Ctrl-I to toggle case sensitivity. While SEARCH is active, Ctrl-U
clears the query and returns to editing instead of moving half a page. Esc
clears SEARCH and returns to COPY; press Esc again to cancel COPY and restore
its entry viewport. After committing a search, y or Enter copies the
selection and returns to live output.
A typed count shows in the status bar until a motion consumes it. 0 only joins
a count already being typed — on its own it stays “first column”. Counts are
capped at four digits, and any key copy mode does not recognise clears the
pending count instead of reaching the program in the pane.