Skip to content

feat(tui): premium splash + working-view redesign#83

Merged
Vasanthdev2004 merged 4 commits into
mainfrom
feat/tui-premium-splash
Jun 6, 2026
Merged

feat(tui): premium splash + working-view redesign#83
Vasanthdev2004 merged 4 commits into
mainfrom
feat/tui-premium-splash

Conversation

@Vasanthdev2004

@Vasanthdev2004 Vasanthdev2004 commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Gives the terminal UI a visual-first identity: a centralized truecolor theme, a polished startup splash, and a three-zone working/session view.

Splash

  • Two-tone ANSI Shadow ZERO wordmark — solid block strokes in bright cyan, drop-shadow strokes in dim cyan (depth with no per-glyph hacks; lipgloss.Width ignores ANSI so centering stays correct).
  • Replaced the Enter / Tab / Ctrl+C keycap hints with a professional ⏵⏵ permission-mode status line (shift+tab to cycle).
  • Rounded box-drawing (╭──╮) for the header and prompt instead of ASCII +--+.

Working / session view (3 zones)

  • Header bar: zero · <cwd> · <git branch> · <provider/model> … ● ready — branch resolves from .git/HEAD (handles worktrees).
  • Body: role gutters ▍ you / ◇ zero, tool rows ▸ read_file <arg hint> with / status, and colorized diff cards (╭─ edit · <tool> ─╮, green + / red ) for patch/edit output.
  • Status line: permission mode on the left, live model · Nk↑ Nk↓ · $cost (from the usage tracker) on the right.

Internals

  • Centralized palette in theme.go (bright/dim cyan pair + role/status/diff/mode styles), shared by both views — replaces the raw ANSI "14"/"10"/"8".
  • Enriched transcriptRow with tool / status / detail so tool results can render structured cards.

Deferred (follow-up)

  • True scrollback via bubbles/viewport + alt-screen. The 3-zone structure is in place; the body renders inline for now (terminal-native scroll, no regression). Wiring the viewport needs height plumbing and is cleaner as its own change.

Testing

  • go build ./...
  • go test ./... (whole module) ✓
  • go vet ./internal/tui/

TestStartupSplashCollapsesAfterFirstPrompt was updated to assert the new working-view rendering (role gutters + status line) instead of the old user:/assistant: prefixes; all other tests unchanged.

Summary by CodeRabbit

  • New Features

    • Premium startup splash: centered branding, project info, command chips, prompt area, and compact footer; splash collapses on first real prompt.
    • Transcript/UI improvements: clearer header/status, working… indicator, grouped tool calls/results with success/error icons, diff-style result cards, and width-aware truncation.
    • Consistent terminal theme and styling across the TUI.
  • Tests

    • Added tests for splash behavior, bordered-block truncation/width, transcript rendering, and tool-result metadata preservation.

Runtime / TUI contract note

  • Event-to-rendering coverage is protected in TestAgentEventRenderingMappingCoversRuntimeContract: text, tool calls/results, plan updates, usage footer, errors, and control-only events are mapped explicitly.
  • This PR only displays the current permission mode in the status line. Full permission prompt/grant UX remains deferred to the tui-sandbox-permissions follow-up once runtime permission events land, so this splash work does not redefine that contract.

Centralized truecolor theme and a visual-first session UI.

Splash:
- Two-tone ANSI Shadow ZERO wordmark (bright blocks / dim shadow)
- Replace Enter/Tab/Ctrl+C keycaps with a permission-mode status line
- Rounded boxes for header and prompt

Working view (3 zones):
- Header bar: cwd, git branch, provider/model, run state
- Role-gutter rows (you / zero), tool rows with ok/err status and arg hints
- Colorized diff cards for patch/edit output
- Pinned status line: mode (left) + model, tokens, cost (right)

Internals:
- Centralized palette in theme.go (role/status/diff/mode styles)
- Enrich transcriptRow with tool/status/detail for structured rendering
- gitBranch resolves .git/HEAD including worktrees
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Zero automated PR review

Verdict: No blockers found

Blockers

  • None found.

Validation

  • [pass] Diff hygiene: git diff --check
  • [pass] Typecheck: bun run typecheck
  • [pass] Tests: bun run test
  • [pass] Build: bun run build
  • [pass] Smoke build: bun run smoke:build

Scope

Head: 2bdf1cf16e2b
Changed files (10): internal/tui/model.go, internal/tui/model_test.go, internal/tui/rendering.go, internal/tui/session.go, internal/tui/session_test.go, internal/tui/startup.go, internal/tui/startup_test.go, internal/tui/theme.go, internal/tui/transcript.go, internal/tui/view.go

This deterministic review checks validation status and basic diff hygiene. A human reviewer still owns product judgment and design quality.

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Ready to act? Review this PR in Change Stack to turn feedback into patch suggestions you can inspect and refine.

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 869e9b20-c454-443a-bb02-8ec847251958

📥 Commits

Reviewing files that changed from the base of the PR and between c536772 and 2bdf1cf.

📒 Files selected for processing (1)
  • internal/tui/model_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/tui/model_test.go

Walkthrough

Adds a premium startup splash and refactors TUI rendering: centralized theme, startupView layout, width-aware row rendering (including tool-call/result metadata and diff cards), model UI state/window tracking, and command handling that toggles the splash; tests validate splash behavior and bordered block widths.

Changes

Premium Startup Splash & Enhanced Transcript Rendering

Layer / File(s) Summary
Theme & Transcript Data Model
internal/tui/theme.go, internal/tui/transcript.go
tuiTheme/zeroTheme centralize styles and transcriptRow now carries tool, status, and detail; append behavior updated.
Startup View Implementation
internal/tui/startup.go
Implements model.startupView() and helpers: header candidates, two-tone ZERO logo, centered command chips, bordered prompt, width/height normalization, ANSI-preserving truncation, and layout utilities.
Working View Header & Status Rendering
internal/tui/view.go (top)
Adds headerBar, provider/model/branch segments, statusLine, mode/usage segments, and related helpers including gitBranch.
View Utilities & Formatting Helpers
internal/tui/view.go (utilities)
Adds humanCount, shortenPath, argHint, diff detection/colorization, diffCard/titledCard, and rune-safe truncation used by tool result rendering.
Transcript Row Rendering with Theme
internal/tui/rendering.go
Rewrites renderRow(row, width) to apply zeroTheme to conversation rows and adds renderToolCallRow / renderToolResultRow. Tool results choose success/error icons and render diff cards or truncated summaries.
Model Structure & Window Size Handling
internal/tui/model.go (struct/init/Update)
Adds UI state fields (showSplash, exiting, pending, run IDs), width/height, removes lipgloss import, initializes showSplash:true, and handles tea.WindowSizeMsg.
View Orchestration & Transcript Layout
internal/tui/model.go (View)
View() now selects startupView() when showSplash is set; otherwise transcriptView() composes header, rendered rows (with startsTurn blank-line rules), and status/footer including pending indicator.
Command Handling & Transcript Enrichment
internal/tui/model.go (handleSubmit)
Updates command switch to consistently toggle showSplash and append appropriate system/status rows; enriches tool-call and tool-result transcript rows with tool, status, and detail.
Startup & Splash Tests
internal/tui/startup_test.go, internal/tui/model_test.go
Adds tests for startupProjectName and bordered block widths, plus model tests verifying splash initial state, collapse after first non-empty prompt, and persistence on empty submit; adds assertNotContains and findTranscriptRow helpers.

Sequence Diagram(s)

sequenceDiagram
  participant TUI_View as TUI View
  participant RenderRow as renderRow
  participant ToolCall as renderToolCallRow
  participant ToolResult as renderToolResultRow
  participant DiffCard as diffCard

  TUI_View->>RenderRow: renderRow(transcriptRow, width)
  alt transcriptRow.kind == "tool-call"
    RenderRow->>ToolCall: format tool name + detail
    ToolCall->>TUI_View: formatted tool-call line
  else transcriptRow.kind == "tool-result"
    RenderRow->>ToolResult: check status, pass detail
    alt looksLikeDiff(detail)
      ToolResult->>DiffCard: build diffCard(detail, width)
      DiffCard->>TUI_View: diff card block
    else
      ToolResult->>TUI_View: truncated muted one-line summary
    end
  else
    RenderRow->>TUI_View: apply zeroTheme styling for conversation rows
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Gitlawb/zero#69: Shares transcript-row enrichment and session hydration changes (tool metadata preservation).
  • Gitlawb/zero#57: Related TUI slash-command/command-registry and command routing changes.

Suggested reviewers

  • gnanam1990
  • anandh8x
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely describes the main changes: a premium startup splash screen and redesigned working view, which align with the core refactoring across model.go, startup.go, rendering.go, and view.go.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tui-premium-splash

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/model_test.go`:
- Around line 145-167: The test calls next.View() before setting the model's
terminal dimensions, causing layout-dependent output to be incorrect; update the
model returned by m.Update (the variable named next of type model) to set
next.width and next.height to the same dimensions used in
TestInitialRenderShowsPremiumStartupSplash (e.g., assign appropriate integer
values to next.width and next.height) before calling next.View(), so the
splash/working view renders deterministically.
- Around line 169-177: The test TestStartupSplashStaysVisibleOnEmptySubmit must
set the model's terminal dimensions before calling View and assert that
working-view UI pieces are not present: initialize m.width and m.height (or call
the same size helper used in other tests) after newModel(...) and before calling
m.Update/View, then keep the positive assertion for "terminal coding agent" and
add negative assertions using assertNotContains for the role gutter markers and
status line strings (e.g. "▍ you", "◇ zero", "● ready") to match the pattern
used in TestInitialRenderShowsPremiumStartupSplash.

In `@internal/tui/startup.go`:
- Around line 213-218: The function fitStyledLine currently returns the input
unchanged and causes borderedBlock layout overflow; fix it by implementing
rune-safe truncation of styled/ANSI text: detect visible width with
lipgloss.Width, strip ANSI sequences (or use lipgloss utilities), truncate the
visible runes to the target width without breaking multi-rune graphemes, and
reapply/retain styling or use lipgloss.NewStyle().Width(width).Render(line) to
produce a width-limited rendered string; update fitStyledLine to return that
truncated/styled result so borderedBlock's padding math is correct.
- Around line 151-167: borderedBlock misaligns when lines are longer than
available width because fitStyledLine currently returns the full line; update
fitStyledLine to truncate strings to the provided width using lipgloss-aware
measurement (use lipgloss.Width to measure and lipgloss.Truncate or equivalent
to cut to the available width while preserving styling), ensure it accepts the
available width argument name matching usage in borderedBlock, and adjust the
call-sites (borderedBlock) to pass the numeric available width; add unit tests
that render oversized unstyled and styled lines through borderedBlock to assert
the right border stays aligned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 45593fdb-cd33-47da-82b5-af58c3b4bbe7

📥 Commits

Reviewing files that changed from the base of the PR and between 294e927 and d67c0db.

📒 Files selected for processing (7)
  • internal/tui/model.go
  • internal/tui/model_test.go
  • internal/tui/rendering.go
  • internal/tui/startup.go
  • internal/tui/theme.go
  • internal/tui/transcript.go
  • internal/tui/view.go

Comment thread internal/tui/model_test.go
Comment thread internal/tui/model_test.go
Comment thread internal/tui/startup.go
Comment thread internal/tui/startup.go

@gnanam1990 gnanam1990 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings:

  • [blocking] internal/tui/model.go:177-179 strips the enriched transcriptRow fields before rendering. runAgent now builds tool rows with tool, status, and detail, but the response handler appends them with appendRow(m.transcript, row.kind, row.text), which keeps only kind and text. As a result, tool result rows lose their status/output/diff detail before renderToolResultRow runs, so error results can render as a green success icon and diff cards never appear in the live TUI path. Preserve the full row object when appending msg.rows (and add a regression around an error or diff tool result).

  • [blocking] internal/tui/session.go:108-110 and internal/tui/session.go:192-195 have the same issue for resumed sessions. transcriptRowsFromSessionEvents does not populate tool, status, or detail for tool rows, then handleResumeCommand copies rows through appendRow, dropping any future metadata anyway. With the new renderer, resumed EventToolResult rows fall back to treating the whole old text as the tool name and default to a success icon with no output summary. Reconstruct and preserve full tool result rows from session events so resume shows the same status/detail semantics as live runs.

Validation run locally on the latest head fca36cb:

  • git merge --no-commit --no-ff origin/main merged cleanly
  • go test -count=1 ./internal/tui passed before and after the merge check
  • git diff --check passed

The earlier CodeRabbit sizing/truncation comments look fixed on the latest head, and CodeRabbit now approves; this remaining issue is in the newly introduced tool-row data flow.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
internal/tui/model_test.go (1)

186-188: 💤 Low value

Consider using string literals instead of Unicode escapes for readability.

The Unicode escape sequences work correctly but are harder to read than their literal forms. For test assertions, readability helps future maintainers.

♻️ Proposed refactor for readability
-	assertNotContains(t, view, "\u258d you")
-	assertNotContains(t, view, "\u25c7 zero")
-	assertNotContains(t, view, "\u25cf ready")
+	assertNotContains(t, view, "▍ you")
+	assertNotContains(t, view, "◇ zero")
+	assertNotContains(t, view, "● ready")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/model_test.go` around lines 186 - 188, The assertions use
Unicode escape sequences which hurt readability; update the three asserts in
model_test.go (the calls to assertNotContains with variable view) to use the
actual Unicode characters instead of escapes — replace "\u258d you" with "▍
you", "\u25c7 zero" with "◇ zero", and "\u25cf ready" with "● ready" so the test
strings are human-readable while keeping behavior the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/tui/model_test.go`:
- Around line 186-188: The assertions use Unicode escape sequences which hurt
readability; update the three asserts in model_test.go (the calls to
assertNotContains with variable view) to use the actual Unicode characters
instead of escapes — replace "\u258d you" with "▍ you", "\u25c7 zero" with "◇
zero", and "\u25cf ready" with "● ready" so the test strings are human-readable
while keeping behavior the same.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f5062c64-8718-4d88-a5c7-7bfe770c3f05

📥 Commits

Reviewing files that changed from the base of the PR and between fca36cb and c536772.

📒 Files selected for processing (5)
  • internal/tui/model.go
  • internal/tui/model_test.go
  • internal/tui/session.go
  • internal/tui/session_test.go
  • internal/tui/transcript.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/tui/transcript.go
  • internal/tui/model.go

@gnanam1990

gnanam1990 commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator

Review: PR #83 — feat(tui): premium splash + working-view redesign (Vasanthdev2004 / Vasanth)

URL: #83
State: OPEN
Author: Vasanthdev2004 (Vasanth T)
Size: +1086 / -49 (10 files, mostly additions)
Branch: feat/tui-premium-splash
Review Date: 2026-06
Reviewer note: Gnanam (runtime owner); note that gnanam1990 already has "Changes requested" on this PR per GitHub metadata.

Ownership Fit

Excellent match for Vasanth's lane (Product UX and TUI owner):

  • Bubble Tea TUI, startup screen, tool rendering, themes, daily CLI feel, permission-mode status, slash UX hints.
  • "Should Not Own Alone": provider internals, release packaging, platform adapters — this PR stays in internal/tui/* and only consumes (does not redefine) runtime contracts.

Directly addresses "TUI command flows need polish beyond basic rendering" and "startup screen stays minimal until the user asks for panels" from the baseline in WORK_SPLIT_PRD.

What the PR Delivers (User-Visible)

  • Premium splash: Centered truecolor ANSI Shadow "ZERO" wordmark (bright cyan solid + dim cyan drop-shadow box-drawing for depth). Professional subtitle, command chips, ⏵⏵ permission-mode status line (with shift+tab to cycle hint). Rounded box-drawing frames (╭──╮).
  • 3-zone working / session view:
    • Header bar: zero · <cwd> · <git branch (worktree-aware)> · <provider/model> … ● ready
    • Body: role gutters (▍ you / ◇ zero), collapsible-ish tool rows with ▸ read_file <hint>, colorized diff cards for edits/patches (╭─ edit · <tool> ─╮ + green + / red ).
    • Status line: permission mode left, live model · Nk↑ Nk↓ · $cost (from usage tracker) right.
  • Centralized theme.go: single source of truecolor hex palette + lipgloss styles (accent, border, roles, diffAdd/Del, modeAuto/Ask/Unsafe, logoBright/Dim). Replaces scattered ANSI magic strings ("14", "10", etc.). Downsables gracefully; works in tests/non-TTY.
  • transcriptRow enriched with tool / status / detail for structured rendering.
  • Model now tracks width/height, showSplash, gitBranch.
  • Tests updated (including TestStartupSplashCollapsesAfterFirstPrompt now asserting new gutters + status) + new coverage for bordered blocks, truncation, splash scenarios.
  • Deferred: full viewport/alt-screen scrollback (author notes this is intentional follow-up to keep the structural change focused).

Code & Architecture Observations (Runtime Contract Lens)

Positive (from runtime owner's view):

  • The TUI remains a thin presentation layer over the runtime event stream / zeroruntime, sessions.Store, usage.Tracker, agent.Options, tools.Registry. No re-implementation of agent loop, provider calls, permission decisions, or session persistence. Good.
  • Theme centralization reduces future drift and makes it easier for runtime events (plan_update, permission.request, usage, tool_result) to have consistent visual treatment.
  • Worktree-aware git branch in header is nice platform/TUI polish.
  • Diff cards directly improve "tool rendering" and "verification/test/git output UX" (Vasanth's remit).

Potential concerns / questions for discussion (why "Changes requested" was placed):

  1. Event consumption & transcript model: The enriched transcriptRow + new rendering in rendering.go / transcript.go / view.go must still faithfully map from the typed AgentEvent / session events that Gnanam owns (text deltas, tool_call, tool_result, usage, plan_update, permission, error, turn_end, etc.). The PR adds structure for tools/diffs — ensure no loss of thinking.delta, raw error details, or stream-json parity. (Recommend a side-by-side of before/after event → row mapping in the PR or a short table in docs.)
  2. Permission mode & sandbox UX: The new status line shows permission mode prominently. This is great for "safe autonomy" goal, but the actual prompt/decision UX for permissions is listed under Vasanth's upcoming feat/tui-sandbox-permissions. Make sure this PR doesn't pre-empt or duplicate the grant/prompt contract (Gnanam's feat/runtime-permission-events).
  3. Hardcoded assumptions vs contracts: Header includes "model · tokens · $cost". Cost/usage comes from the runtime tracker (good). Confirm the model name/provider shown is always the one resolved by the runtime (Gnanam's provider/model registry), not duplicated state in TUI.
  4. Width/height & resize handling: New model fields are good, but the current inline rendering (no viewport yet) relies on terminal scroll. Test thoroughly on narrow terminals and during long tool output.
  5. Test-only vs real runtime: The splash collapse test is updated, but the new beautiful rendering should ideally have a golden or snapshot test that exercises real tool rows + diff cards from a fake event stream (to protect the contract surface).

Tests & DoD

  • go build ./..., go test ./..., go vet ./internal/tui/
  • Updated existing tests + new splash / truncation / rendering tests.
  • No Bun/TS changes of note (correct — this is pure Go TUI now).

Fits the "For every code PR: Add or update tests..." rule.

Alignment with PRD / WORK_SPLIT

  • Directly advances "Terminal UI (P0)", "F4 — Terminal UI" (layout, streaming, tool rows, markdown-ish diffs, themes, splash).
  • "TUI command UX and daily CLI" workstream.
  • Supports the overall "Go-native core" migration (pairs well with Remove legacy TypeScript runtime #78 legacy removal).

Overall Recommendation

Strong direction — this is the visual identity Zero needs.

Conditional approve / Changes requested (consistent with existing gnanam1990 flag):

  1. Add a short "Event → Rendering mapping" note or comment (or a test helper) showing that all core AgentEvent types (including permission, plan, usage, errors, thinking) still render or are at least not regressed.
  2. Clarify in PR description or a follow-up issue how the prominent permission status line will evolve into the full tui-sandbox-permissions flows (to avoid contract drift with Gnanam's runtime-permission-events).
  3. Consider a minimal "render from event stream" test that feeds a few real-looking events (tool call + result with patch, usage, permission request) through the new transcript/view and asserts structure (gutters, cards, status).

Once the runtime consumption and permission UX coordination points are addressed or explicitly deferred with owners' agreement, this should land cleanly.

Vasanth: excellent work on the polish. This moves the "daily CLI feel" needle significantly.

@gnanam1990 gnanam1990 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes requested in my earlier review have been addressed:

  • c536772: Preserves enriched transcriptRow metadata (tool/status/detail) for tool results in live updates, resume path, and added regression test. This was the main blocking point.
  • fca36cb: Stabilizes splash/ startup rendering with proper width/height handling and test updates.

Relevant TUI tests pass. Good follow-through.

Approving.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants