feat(tui): UX ergonomics round — clear confirm, OSC 52 copy, transcript find - #39
Merged
Conversation
The whole transcript — plus every turn stat, tool count, and context counter — was one accidental ^L away from gone, while deleting a single session or fact in the panels already required the d→y two-step gate. Arm the same confirmClear gate instead: y fires the wipe, any other key disarms, the composer footer shows the danger hint. /clear gains the same idle-only rule ^L always had, so a mid-turn wipe can no longer drop the view out from under a streaming turn.
The #1 post-turn action — pasting the answer into a PR, issue, or editor — had no keyboard path: selecting long markdown inside a full-screen alt-buffer TUI is clunky, especially without --mouse. ^Y and /copy now copy the latest finalized assistant reply via OSC 52. The sequence is emitted through tea.Exec so it reaches the terminal verbatim (tea.Println output is dropped on the alt-screen), the payload is consumed by the local terminal emulator only, and oversized replies are refused rather than silently truncated. Terminals without OSC 52 support ignore the sequence; the note says so. Promotes charmbracelet/x/ansi from indirect to direct — no new dependency.
Long agent sessions had no way to search content: turn jumps and folding navigate by position only. alt+f opens a one-row find strip above the composer — typed runes filter matches live across message text, reasoning/reply segments, and tool steps (names, args, results, sub-agent logs); enter jumps forward, N back, esc closes. The bar captures the keyboard while open, and the ^L clear-confirm chord stays live through it. Matches map to message blocks through a per-message line index built alongside the existing turn/step indexes, so jumps land with a line of context above the target.
alt+f find bar, ^Y OSC 52 copy, and the two-step confirm on ^L and /clear.
Every uncovered block in the UX round's new code now has a test: find-bar key routing (ctrl+c quit, backspace incl. the empty-query no-op, busy ctrl+l guard), per-kind matching across reasoning/reply items and step name/arg/result/logs, stale-match jumps, close idempotence, find-bar render states (hint, count, truncation), and the clipboardWrite runner (nil-writer guard, verbatim write, error propagation). All functions in find.go and clipboard.go are at 100% statement coverage; SetStdin/SetStderr stay empty-bodied (zero instrumentable statements) and are exercised by TestClipboardWriteRunner.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Top-3 UI/UX & ergonomics improvements, selected by code audit and validated by a 3-judge agent panel (majority rules; proposal in UX_PROPOSAL.md, kept out of the tree).
Judge verdicts
P1 — feat(tui): two-step confirm for ^L and /clear
The whole transcript + all session telemetry was one accidental
^Lfrom gone, while deleting a single session/fact in the panels already required the d→y gate.^Land/clearnow armconfirmClear:yfires, any other key disarms, the composer footer shows the danger hint./clearalso gains the idle-only rule (^Lalways had it), so a mid-turn wipe can't drop the view out from under a streaming turn.P2 — feat(tui): copy the last reply via OSC 52 (^Y, /copy)
The #1 post-turn action (pasting the answer elsewhere) had no keyboard path.
^Y//copycopy the latest finalized assistant reply viaansi.SetSystemClipboard. Emission goes throughtea.Exec—tea.Printlnoutput is dropped on the alt-screen — so the sequence reaches the terminal verbatim. Payload stays local (consumed by the terminal emulator); >100 KB replies are refused, not truncated; unsupported terminals silently ignore the sequence and the transient note says so.charmbracelet/x/ansipromotes from indirect to direct — no new dependency.P3 — feat(tui): transcript find bar (alt+f)
Long sessions had no content search — turn jumps/fold navigate by position only.
alt+fopens a one-row find strip: live match count across message text, reasoning/reply segments, and tool steps (names/args/results/sub-agent logs);⏎next,Nprevious,esccloses. The bar captures the keyboard while open; the^Lconfirm chord stays live through it. Per the quality judge's scope concern, inline markdown highlighting is deliberately excluded — navigation + count only.Verification
clear_confirm_test.go,clipboard_test.go,find_test.go), then implementation to green; 4 existing tests deliberately updated to the new confirm contract, never weakened.make fmt vet lint testall green: gofmt clean, vet clean, golangci-lint 0 issues, full race suite green.^L-through-find routing fix) is covered byTestClearClosesFind.Notes