TUI Design
Make thndrs feel composed, quiet, and responsive. Start with what the user sees and does. Let engineering support the design instead of defining it.
Work from the live product
- Inspect the running state, current code, and relevant tests or snapshots.
- Treat
docs/public/screenshot.png and docs/tui/*.tape as legacy artifacts until they are checked against the current product. Do not copy their composition by default.
- Name the state being improved and the action the user should notice first.
- Compare the state with the relevant patterns in references/harness-patterns.md. Adopt the reasoning, not another harness's skin.
- State the intended hierarchy, density, alignment, color, and interaction change before editing.
- Implement the smallest coherent change, render it, inspect it, and refine it once more.
For a narrow correction, keep this pass short. For a redesign, cover the whole state matrix before settling the visual system.
Design the frame
- Give each state one obvious focal point: active output, a decision, a selection, or the composer.
- Keep the transcript open and readable. Separate turns with rhythm and semantic markers before adding boxes.
- Pin the composer to the bottom and let it grow upward. Keep editable rows on the terminal background and bound them with a thin rounded border built from renderer-owned row primitives. Let semantic state tint the border quietly, and simplify or remove chrome before squeezing editable content at tiny widths.
- Leave the session label, surrounding space, status, and footer on the terminal background.
- Establish a spacing rhythm and shared alignment anchors. One stray row or column can make a small TUI feel unfinished.
- Use borders for real containment, focus, or selection. Avoid nested chrome and decorative rules around passive content.
- Keep labels short, specific, and visually subordinate to the user's draft and current work. Show one primary elapsed-time measure instead of competing operation and aggregate timers.
- Use one dominant accent plus semantic success, warning, and error roles. Make every state legible without color.
- Keep live updates spatially stable. Streaming, spinners, status changes, and popup dismissal must not make unrelated content jump.
- Design empty, busy, failed, cancelled, permission, long-content, and tiny-terminal states with the same care as the ideal screenshot. When a focused picker or help surface replaces the empty state, reclaim decorative gutters and hide the startup banner so the focused content gets the live viewport.
Read references/harness-patterns.md for the visual audit, component patterns, polish rubric, and lessons from Codex, Grok Build, Amp, and Factory Droid.
Protect the interaction
- Preserve drafts across recoverable errors, blocked submission, picker dismissal, and navigation.
- Route keys to the focused modal or picker before composer, active operation, and global actions.
- For mention pickers, route cursor and deletion keys to the composer while reserving vertical navigation for picker selection.
- Give focus and selection a text, shape, or position cue in addition to color.
- Keep keyboard operation complete. With mouse capture enabled, app-owned selection must hit-test semantic text at grapheme boundaries and exclude padding and unrelated chrome.
- Make app-owned selection read like native text selection: a contiguous neutral fill, precise first and last lines, and no decorative underline. Preserve terminal-native selection when capture is off.
- Define Enter, Escape, Tab, arrows, page keys, cancellation, paste, resize, and focus restoration for every changed surface.
- Keep the active choice visible while scrolling and resizing.
- When a surface gains or loses focus, update its input routing, scrolling, and redraw ownership together.
Preserve the rendering seams
Follow the established flow:
application state -> RendererView -> semantic surfaces/rows -> Ratatui frame -> Crossterm
Keep state transitions outside rendering and keep layout, wrapping, truncation, and semantic projection pure where practical. Reuse the current renderer modules before adding abstractions or crates. For editable text, derive rendered wrapping and cursor coordinates from the same layout, and prefer word boundaries with grapheme splitting only for overlong words.
Read references/ratatui-engineering.md only when changing terminal lifecycle, event handling, animation, themes, Unicode layout, dependencies, performance, or renderer boundaries.
Judge the result visually
- Render the affected states at realistic, narrow, and tiny sizes.
- Compare before and after captures for hierarchy, balance, rhythm, alignment, contrast, chrome, copy, and spatial stability.
- Run the narrowest behavioral and rendering checks needed for the change.
- Inspect changed snapshots cell by cell. Passing snapshots do not establish polish.
- Exercise a real terminal when cursor behavior, input timing, animation, terminal capabilities, or overall composition changed.
Use references/verification.md to select states and evidence. Regenerate public screenshots or VHS fixtures only after the product state is approved and the fixture represents it accurately.
Learn from feedback
Treat explicit user corrections and repeated visual-review findings as input to this skill. At the end of relevant TUI work, apply references/skill-maintenance.md: update the smallest rule or reference that would prevent the issue from recurring, validate the skill, and mention the update in the handoff.
Do not encode one-off taste, temporary workarounds, or screenshot-specific coordinates. Replace stale guidance and consolidate duplicates so the skill becomes sharper rather than longer.
Stop when the requested state is polished and verified. Leave unrelated renderer cleanup and feature work alone.
1---2name: tui-design3description: Design, redesign, implement, review, and visually polish the thndrs Ratatui interface, then improve the skill from reusable user feedback. Use for the transcript, composer, status line, pickers, prompts, overlays, themes, responsive layout, keyboard or mouse interaction, accessibility, rendering performance, terminal lifecycle, TUI snapshots, or terminal screenshots under crates/thndrs/src/cli/renderer and related application code.4---56# TUI Design78Make thndrs feel composed, quiet, and responsive. Start with what the user sees and does. Let engineering support the design instead of defining it.910## Work from the live product11121. Inspect the running state, current code, and relevant tests or snapshots.132. Treat `docs/public/screenshot.png` and `docs/tui/*.tape` as legacy artifacts until they are checked against the current product. Do not copy their composition by default.143. Name the state being improved and the action the user should notice first.154. Compare the state with the relevant patterns in [references/harness-patterns.md](references/harness-patterns.md). Adopt the reasoning, not another harness's skin.165. State the intended hierarchy, density, alignment, color, and interaction change before editing.176. Implement the smallest coherent change, render it, inspect it, and refine it once more.1819For a narrow correction, keep this pass short. For a redesign, cover the whole state matrix before settling the visual system.2021## Design the frame2223- Give each state one obvious focal point: active output, a decision, a selection, or the composer.24- Keep the transcript open and readable. Separate turns with rhythm and semantic markers before adding boxes.25- Pin the composer to the bottom and let it grow upward. Keep editable rows on the terminal background and bound them with a thin rounded border built from renderer-owned row primitives. Let semantic state tint the border quietly, and simplify or remove chrome before squeezing editable content at tiny widths.26- Leave the session label, surrounding space, status, and footer on the terminal background.27- Establish a spacing rhythm and shared alignment anchors. One stray row or column can make a small TUI feel unfinished.28- Use borders for real containment, focus, or selection. Avoid nested chrome and decorative rules around passive content.29- Keep labels short, specific, and visually subordinate to the user's draft and current work. Show one primary elapsed-time measure instead of competing operation and aggregate timers.30- Use one dominant accent plus semantic success, warning, and error roles. Make every state legible without color.31- Keep live updates spatially stable. Streaming, spinners, status changes, and popup dismissal must not make unrelated content jump.32- Design empty, busy, failed, cancelled, permission, long-content, and tiny-terminal states with the same care as the ideal screenshot. When a focused picker or help surface replaces the empty state, reclaim decorative gutters and hide the startup banner so the focused content gets the live viewport.3334Read [references/harness-patterns.md](references/harness-patterns.md) for the visual audit, component patterns, polish rubric, and lessons from Codex, Grok Build, Amp, and Factory Droid.3536## Protect the interaction3738- Preserve drafts across recoverable errors, blocked submission, picker dismissal, and navigation.39- Route keys to the focused modal or picker before composer, active operation, and global actions.40- For mention pickers, route cursor and deletion keys to the composer while reserving vertical navigation for picker selection.41- Give focus and selection a text, shape, or position cue in addition to color.42- Keep keyboard operation complete. With mouse capture enabled, app-owned selection must hit-test semantic text at grapheme boundaries and exclude padding and unrelated chrome.43- Make app-owned selection read like native text selection: a contiguous neutral fill, precise first and last lines, and no decorative underline. Preserve terminal-native selection when capture is off.44- Define Enter, Escape, Tab, arrows, page keys, cancellation, paste, resize, and focus restoration for every changed surface.45- Keep the active choice visible while scrolling and resizing.46- When a surface gains or loses focus, update its input routing, scrolling, and redraw ownership together.4748## Preserve the rendering seams4950Follow the established flow:5152```text53application state -> RendererView -> semantic surfaces/rows -> Ratatui frame -> Crossterm54```5556Keep state transitions outside rendering and keep layout, wrapping, truncation, and semantic projection pure where practical. Reuse the current renderer modules before adding abstractions or crates. For editable text, derive rendered wrapping and cursor coordinates from the same layout, and prefer word boundaries with grapheme splitting only for overlong words.5758Read [references/ratatui-engineering.md](references/ratatui-engineering.md) only when changing terminal lifecycle, event handling, animation, themes, Unicode layout, dependencies, performance, or renderer boundaries.5960## Judge the result visually61621. Render the affected states at realistic, narrow, and tiny sizes.632. Compare before and after captures for hierarchy, balance, rhythm, alignment, contrast, chrome, copy, and spatial stability.643. Run the narrowest behavioral and rendering checks needed for the change.654. Inspect changed snapshots cell by cell. Passing snapshots do not establish polish.665. Exercise a real terminal when cursor behavior, input timing, animation, terminal capabilities, or overall composition changed.6768Use [references/verification.md](references/verification.md) to select states and evidence. Regenerate public screenshots or VHS fixtures only after the product state is approved and the fixture represents it accurately.6970## Learn from feedback7172Treat explicit user corrections and repeated visual-review findings as input to this skill. At the end of relevant TUI work, apply [references/skill-maintenance.md](references/skill-maintenance.md): update the smallest rule or reference that would prevent the issue from recurring, validate the skill, and mention the update in the handoff.7374Do not encode one-off taste, temporary workarounds, or screenshot-specific coordinates. Replace stale guidance and consolidate duplicates so the skill becomes sharper rather than longer.7576Stop when the requested state is polished and verified. Leave unrelated renderer cleanup and feature work alone.