Skip to content

[RFC] feat(cli): Interactive TUI prototype#54

Draft
scoropeza wants to merge 2 commits intoaws-samples:mainfrom
scoropeza:feature/tui-prototype
Draft

[RFC] feat(cli): Interactive TUI prototype#54
scoropeza wants to merge 2 commits intoaws-samples:mainfrom
scoropeza:feature/tui-prototype

Conversation

@scoropeza
Copy link
Copy Markdown
Contributor

@scoropeza scoropeza commented May 1, 2026

[RFC] feat(cli): Interactive TUI prototype

📋 This is a design proposal / RFC — not intended for merge yet.

Looking for feedback on the TUI design, interaction patterns, and Peccy branding before integrating into the main CLI. Please comment on:

  • Overall UX flow (splash → tabs → panels)
  • Approval workflow (list → detail drill-down → approve/deny)
  • Branding (Peccy pixel art, animated pupils, color palette)
  • Technical approach (ESM integration, separate tsconfig)
  • Anything that feels off or could be improved

Summary

A full-screen terminal UI (TUI) prototype for bgagent, built with Ink (React for terminals). Proposes replacing the current text-only CLI with an interactive, tabbed interface that makes managing background coding agents intuitive and discoverable. Uses mock data — not wired to real APIs yet.

Demo

Full walkthrough

Full demo

Watch panel (event streaming + nudge)

Watch

What's included

5 panels in a tabbed layout

Panel Purpose Key interactions
Tasks List all tasks with status, step, cost ↑/↓ navigate, Enter → Watch
Watch Live event stream for a running task ↑/↓ scroll history, n nudge, a/d approve/deny
Approvals All pending approvals grouped by task Enter → full detail view, a/d respond
Policies Cedar policy explorer Enter toggles detail (stays open on navigate)
New Task Submit a task with repo picker + scopes Repo dropdown from RepoTable, scope checkboxes

Branding

  • Peccy pixel-art mascot rendered with half-block characters (▀▄█)
  • Full-size animated Peccy on splash screen (2.5s or press any key)
  • Mini Peccy (cropped head + eyes) in header on all panels
  • Pupils animate on a subtle ~51s cycle (idle → glance right → idle → glance left → idle → look down)

UX features

  • Alternate screen buffer — full-screen mode like vim/htop, no scrollback artifacts
  • Dynamic event window — sizes to terminal height automatically
  • Approval detail drill-down — Enter from list → full untruncated view with task goal, tool input, reason, matching Cedar rules, severity, live countdown
  • Deny confirmation — "The agent will be blocked and may not be able to continue" + y/n
  • Nudge with placeholdern opens inline input with example text
  • Progressive disclosure — scope picker expands/collapses, policy detail toggles
  • Repo dropdown — selects from registered repos (CDK Blueprint RepoTable) instead of free text
  • Context-aware HelpBar — different shortcuts per panel, number key legend on the right
  • Context-aware status badges — "● 2 active ⚠ 2 pending" inline next to title

Architecture

  • data.ts — abstraction layer over mock data; swap implementations for real API
  • context.tsx — shared React context for approval state + editing lock (useMemo for stable values)
  • constants.ts — single source of truth for colors, icons, labels
  • peccy-shared.ts — shared pixel rendering + animation sequence
  • ErrorBoundary.tsx — crash recovery with stack trace display
  • Signal handlers — SIGINT/SIGTERM/uncaughtException restore terminal

Quality

  • 6 rounds of UX evaluation (readability, navigation, domain UX, code quality)
  • Final scores: Visual 9.5, Navigation 9.5, Domain UX 9.6, Code Quality 8.8 — average 9.35/10
  • 18 TUI source files, 71KB total, zero direct mock imports from panels

How to try it

cd cli
npm install
npm run build
npm run tui

What's NOT included (next steps)

  • Wire data.ts to real REST API (replace mock functions with fetch calls)
  • Integrate into bgagent CLI as bgagent tui command
  • Real polling with adaptive interval (500ms→5s)
  • Shell tab completions (tabtab)
  • Smart defaults (repo from cwd, last task memory)
  • Terminal width responsive layout

Technical notes — ESM integration

The TUI depends on Ink (React for terminals), figures, and ink-spinner — all of which are ESM-only packages. The existing CLI uses CommonJS ("module": "CommonJS" in tsconfig.json).

To avoid disrupting the existing CLI build, the TUI is set up as a separate compilation target within the same workspace:

File Purpose
cli/src/tui/package.json {"type": "module"} — tells TypeScript this directory is ESM
cli/src/tui/tsconfig.json Separate tsconfig: module: "Node16", jsx: "react-jsx", rootDir: "."
cli/lib/tui/package.json {"type": "module"} — tells Node to run compiled output as ESM
cli/tsconfig.json Updated exclude to skip src/tui/**/* and src/mock/**/*
cli/package.json Added tui:compile and tui scripts

Build commands:

  • npm run compile — builds the existing CLI (unchanged, CommonJS)
  • npm run tui:compile — builds the TUI separately (ESM, JSX)
  • npm run tui — compiles + runs the TUI

New dependencies added to cli/:

  • ink@^5.2.1, ink-spinner, react, figures, strip-ansi (runtime)
  • @types/react (dev)

When the CLI eventually migrates to ESM (which is the direction the Node ecosystem is heading), the TUI's separate tsconfig can be merged back into the main one and the package.json shims removed.

Design decisions

Decision Rationale
Ink (React for terminals) Component model, diffing renderer, familiar React patterns
Half-block pixel art for Peccy Cross-platform, no special fonts, same technique as Claude Code / GitHub Copilot CLI
Alternate screen buffer Prevents scrollback artifacts from Ink re-renders
Shared context for approvals Watch, Approvals, and TabBar badge all stay in sync
Data abstraction layer Clean boundary for swapping mock → real API
figures library for icons Cross-platform fallbacks for Windows CMD
Progressive disclosure Direct commands → guided prompts → full TUI (3-tier strategy)

Known issues

⚠️ Pre-existing CDK peer dependency conflict on main

cdk/package.json declares @typescript-eslint/parser@^8 but also depends on @cdklabs/eslint-plugin@^1.5.10, which peer-requires @typescript-eslint/parser@^7. This blocks npm install across the entire monorepo without --legacy-peer-deps.

This is not introduced by this PR — it reproduces on a clean checkout of main. Recommend resolving separately by either downgrading parser to ^7 in CDK or waiting for @cdklabs/eslint-plugin to release v8 parser support. Filed as a separate concern to avoid coupling it with this prototype review.

  • Mock data only: The TUI uses mock data for demonstration. Wiring to real APIs is a follow-up.

Related

  • Design doc: docs/design/INTERACTIVE_AGENTS.md (rev 6)
  • Phase 3 HITL: docs/design/PHASE3_CEDAR_HITL.md (rev 3)
  • CLI UX research: see bgagent-tui-design.md in the prototype workspace

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