Skip to content

style(cli): polish matrix tui launcher#249

Open
Nima-Naderi wants to merge 9 commits into
084-matrix-cli-tui-testsfrom
084-matrix-cli-tui-polish
Open

style(cli): polish matrix tui launcher#249
Nima-Naderi wants to merge 9 commits into
084-matrix-cli-tui-testsfrom
084-matrix-cli-tui-polish

Conversation

@Nima-Naderi
Copy link
Copy Markdown
Collaborator

@Nima-Naderi Nima-Naderi commented May 29, 2026

Summary

  • Polishes the Matrix CLI TUI launcher with a Matrix-themed centered home screen, terminal-native MATRIX OS wordmark, static ASCII rabbit, cleaner prompt/status layout, and matching command palette styling.
  • Keeps the change visual-only: no launch routing, runtime API, gateway client, auth, session, dependency, or lockfile changes.
  • Addresses Greptile's review findings by using ordered keys for static ASCII art and by making the command palette respect detected terminal columns.
  • Addresses Greptile's follow-up compact-width finding by scaling command title padding from the palette's actual render width.

Tests

  • pnpm --filter @finnaai/matrix exec vitest run tests/tui/home-render.test.tsx tests/tui/command-palette.test.tsx tests/tui/accessibility.test.tsx: passed, 10 tests.
  • pnpm --filter @finnaai/matrix exec tsc --noEmit: passed.
  • pnpm run check:patterns: 0 violations, 5 existing warning groups outside this visual TUI diff.
  • git diff --check: passed.

Review/Monitoring

  • PR Title, Vercel Preview Comments, and Vercel checks passed on 413a2c49b0b7ad007d9861f009ed499287a7dba6; latest commit f6c512c6d60317bbf76fb8598aef4ca71105987c is pushed and awaiting check/Greptile refresh.
  • Greptile reached 5/5 on 413a2c49b0b7ad007d9861f009ed499287a7dba6, then noted one cosmetic compact-width spacing follow-up; that follow-up is fixed in f6c512c6d60317bbf76fb8598aef4ca71105987c.

Notes

  • bun and flox are not installed in this environment, so validation used direct pnpm equivalents.
  • Full pnpm --filter @finnaai/matrix test is blocked locally by stale /tmp/test-auth-1.json and /tmp/test-auth-2.json files owned by nobody; the unrelated OAuth tests fail on EPERM rename into those paths. The changed TUI tests pass.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
matrix-os-www Ready Ready Preview, Comment May 29, 2026 3:57pm

Request Review

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 29, 2026

Greptile Summary

This PR polishes the Matrix CLI TUI launcher with a Matrix-themed home screen: a centered wordmark, a 25-line ASCII rabbit mascot, responsive layout breakpoints, and a restyled command palette that respects terminal width. It also adds proper alternate-screen entry/exit and a q-to-quit keybinding.

  • app.tsx: Alternate-screen entry/exit is now guarded by shouldUseAlternateScreen() and cleaned up via both a synchronous process.once(\"exit\", ...) listener and the async finally block, correctly handling both normal and forced exits.
  • HomeView.tsx: Introduces three width breakpoints and a fullScreenHeight path that activates at rows >= 30; the fullScreenHeight threshold does not account for the 37-line content height in the medium-width layout, which can clip the status row in short terminals.
  • CommandPalette.tsx / Mascot.tsx: Palette width is now capped to Math.min(columns, 76); mascot uses array-index keys and gains a compact one-liner fallback for narrow terminals.

Confidence Score: 4/5

Safe to merge with the fullscreen height overflow addressed; all other changes are purely visual and well-tested.

The fullscreen layout path activates at rows >= 30, but the medium-width art layout totals ~37 lines. Ink/yoga clips children that overflow a height-constrained Box, so the status line and blocking-action hint disappear silently in 30-36-row terminals.

packages/sync-client/src/cli/tui/views/HomeView.tsx — the fullScreenHeight threshold and mascot-visibility condition need to be reconciled.

Important Files Changed

Filename Overview
packages/sync-client/src/cli/tui/app.tsx Adds alternate-screen entry/exit with synchronous process.once cleanup, q-to-quit via Ink's useApp().exit(), and passes columns/rows to child views.
packages/sync-client/src/cli/tui/views/HomeView.tsx Adds responsive layout breakpoints and fullscreen centering; fullScreenHeight threshold of 30 rows conflicts with the 37-line content height in the medium-width layout.
packages/sync-client/src/cli/tui/views/CommandPalette.tsx Now accepts columns prop and caps width via Math.min(Math.max(1, columns), 76); title padding scales from actual render width.
packages/sync-client/src/cli/tui/views/Mascot.tsx Replaces simple face glyph with 25-line ASCII rabbit; uses array-index keys and adds compact fallback for narrow terminals.
packages/sync-client/tests/tui/home-render.test.tsx Expands coverage for wide/narrow/tall/no-color layouts; fullscreen test uses rows=40, leaving the 30–36 row overflow window untested.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
packages/sync-client/src/cli/tui/views/HomeView.tsx:34-55
**Full-screen mascot overflows the height-constrained Box**

`fullScreenHeight` activates at `rows >= 30`, but in the medium-width band (`!narrow && !extraWide`, roughly 80–123 columns), the mascot is rendered inline above the prompt. The mascot alone is 25 lines; with the title (1), `marginBottom` gaps (2), the bordered prompt panel (7), and the status row (2), the column totals ~37 lines. Ink/yoga clips children that overflow a height-constrained Box, so in a 30-to-36-row terminal the entire status line and the `blockingActions` hint are silently cut off. The fullscreen threshold must account for this art height: raising `rows >= 30` to `rows >= 40` (or conditionally suppressing the mascot when `fullScreenHeight && rows < 40`) closes the gap.

Reviews (11): Last reviewed commit: "fix(cli): restore fullscreen tui on proc..." | Re-trigger Greptile

Comment thread packages/sync-client/src/cli/tui/views/Mascot.tsx
Comment thread packages/sync-client/src/cli/tui/views/HomeView.tsx Outdated
Comment thread packages/sync-client/src/cli/tui/views/CommandPalette.tsx Outdated
@Nima-Naderi
Copy link
Copy Markdown
Collaborator Author

@greptileai please re-review the latest commit.

@Nima-Naderi
Copy link
Copy Markdown
Collaborator Author

@greptileai please re-review latest commit f6c512c.

Copy link
Copy Markdown
Collaborator Author

Nima-Naderi commented May 29, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

Comment on lines 136 to 149
export async function launchTui(options: { noColor?: boolean } = {}): Promise<void> {
const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
await waitUntilExit();
const useAlternateScreen = shouldUseAlternateScreen();
if (useAlternateScreen) {
process.stdout.write(ENTER_ALTERNATE_SCREEN);
}
try {
const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
await waitUntilExit();
} finally {
if (useAlternateScreen) {
process.stdout.write(EXIT_ALTERNATE_SCREEN);
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Alternate screen not restored on process.exit()

async finally blocks are skipped when process.exit() is called — the event loop stops immediately. Ink's default Ctrl+C handling in raw mode calls process.exit(0), so pressing Ctrl+C while the TUI is open will leave the terminal stuck in alternate screen mode (blank screen, no scrollback) until the user runs reset. Adding a synchronous process.on('exit', ...) handler guarantees cleanup regardless of how the process terminates.

Suggested change
export async function launchTui(options: { noColor?: boolean } = {}): Promise<void> {
const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
await waitUntilExit();
const useAlternateScreen = shouldUseAlternateScreen();
if (useAlternateScreen) {
process.stdout.write(ENTER_ALTERNATE_SCREEN);
}
try {
const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
await waitUntilExit();
} finally {
if (useAlternateScreen) {
process.stdout.write(EXIT_ALTERNATE_SCREEN);
}
}
}
export async function launchTui(options: { noColor?: boolean } = {}): Promise<void> {
const useAlternateScreen = shouldUseAlternateScreen();
if (useAlternateScreen) {
process.stdout.write(ENTER_ALTERNATE_SCREEN);
const restore = () => process.stdout.write(EXIT_ALTERNATE_SCREEN);
process.once("exit", restore);
try {
const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
await waitUntilExit();
} finally {
process.removeListener("exit", restore);
restore();
}
} else {
const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
await waitUntilExit();
}
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/sync-client/src/cli/tui/app.tsx
Line: 136-149

Comment:
**Alternate screen not restored on `process.exit()`**

`async` `finally` blocks are skipped when `process.exit()` is called — the event loop stops immediately. Ink's default Ctrl+C handling in raw mode calls `process.exit(0)`, so pressing Ctrl+C while the TUI is open will leave the terminal stuck in alternate screen mode (blank screen, no scrollback) until the user runs `reset`. Adding a synchronous `process.on('exit', ...)` handler guarantees cleanup regardless of how the process terminates.

```suggestion
export async function launchTui(options: { noColor?: boolean } = {}): Promise<void> {
  const useAlternateScreen = shouldUseAlternateScreen();
  if (useAlternateScreen) {
    process.stdout.write(ENTER_ALTERNATE_SCREEN);
    const restore = () => process.stdout.write(EXIT_ALTERNATE_SCREEN);
    process.once("exit", restore);
    try {
      const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
      await waitUntilExit();
    } finally {
      process.removeListener("exit", restore);
      restore();
    }
  } else {
    const { waitUntilExit } = render(<MatrixTuiApp noColor={options.noColor} />);
    await waitUntilExit();
  }
}
```

How can I resolve this? If you propose a fix, please make it concise.

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.

1 participant