curiositech

beautiful-cli-design

Design polished terminal UX for CLIs and TUIs. Use for setup flows, dashboards, tables, and actionable errors. NOT for web UIs, desktop windows, API schemas, or shell automation.

curiositech 3 1 Updated 1mo ago

Resources

10
GitHub

Install

npx skillscat add curiositech/port-daddy/beautiful-cli-design

Install via the SkillsCat registry.

SKILL.md

Beautiful CLI Design

Treat the terminal as a real interface surface: hierarchy, feedback, accessibility, and fallback modes all matter.

When to Use

  • Branded setup flows, login flows, and first-run wizards.
  • Rich command output with tables, spinners, status blocks, or markdown rendering.
  • Stateful terminal dashboards or TUIs that must feel intentional instead of bolted on.
  • Error and remediation flows where the output should guide action instead of dumping stack traces.

NOT for

  • Browser interfaces or responsive web dashboards.
  • Desktop GUI windows and native menu-bar apps.
  • API response schemas or machine-only output contracts.
  • Shell automation logic where human-facing polish is not the bottleneck.

Decision Points

flowchart TD
  A[CLI UX request] --> B{Need full-screen stateful interaction?}
  B -->|Yes| C{Team and runtime fit}
  C -->|React or TypeScript| D[Ink]
  C -->|Go| E[Bubble Tea or Huh]
  C -->|Rust| F[Ratatui or inquire]
  B -->|No| G{Need branded prompts or rich output?}
  G -->|Prompts| H[Clack, Huh, or inquire]
  G -->|Rich output| I[Chalk, Rich, or lipgloss plus tables and spinners]
  D --> J[Layer color, width, and failure handling]
  E --> J
  F --> J
  H --> J
  I --> J
  J --> K[Validate TTY fallback, Unicode width, and machine-readable mode]

Use this routing model first:

  • Prompt libraries are enough for wizards and first-run experiences.
  • Full TUI frameworks are worth it only when the interface has durable state and navigation.
  • Every visual choice must survive NO_COLOR, narrow widths, non-TTY pipes, and machine-readable flags.

Visual System Rules

  • Use semantic colors, not rainbow sampling. Success, warning, error, and one accent is usually enough.
  • Treat width as a first-class constraint. Reflow at 40, 80, and 120 columns.
  • Use Unicode-aware width calculation for tables and box drawing.
  • Make progress states honest: spinner for unknown duration, bars and ETA only when the denominator is real.
  • Turn every error surface into a next-action surface.

FAILURE MODES

Anti-Pattern: "Rainbow Vomit"

Symptom: Every piece of text has different colors, making nothing stand out
Detection Rule: If you count more than five colors in a single screen, you have hit this
Fix: Limit to three semantic colors plus one accent. Use grayscale for hierarchy.

Anti-Pattern: "Invisible in Light Mode"

Symptom: The CLI looks good in a dark terminal but becomes unreadable in light themes
Detection Rule: Hardcoded dark-theme colors without testing
Fix: Use semantic ANSI codes or verify the palette in both dark and light terminal themes.

Anti-Pattern: "Broken Pipe Panic"

Symptom: The CLI crashes or sprays ANSI codes when piped, for example mycli | head -5
Detection Rule: isTTY or equivalent detection is missing from the formatting path
Fix: Strip formatting for pipes and keep a --color=always override when the user explicitly wants it.

Anti-Pattern: "Ghost Cursor"

Symptom: The terminal cursor disappears after a crash and the user has to recover it manually
Detection Rule: Cursor hiding is used without exit handlers for failure and interruption paths
Fix: Always restore cursor state before process termination.

Anti-Pattern: "Asian Character Explosion"

Symptom: Tables and boxes misalign when users have CJK names or emoji in data
Detection Rule: Layout math uses string length instead of display width
Fix: Use Unicode-aware width libraries for every alignment calculation.

Anti-Pattern: "Pretty but Script-Hostile"

Symptom: The human output looks great, but --json, pipes, or CI logs become unusable
Detection Rule: The command cannot cleanly switch between human mode and machine mode
Fix: Keep a machine-readable output path that bypasses decoration entirely.

WORKED EXAMPLES

Example 1: Setup Wizard Enhancement

Before: Basic prompts, no branding, inconsistent styling

? What's your project name? my-app
? Choose framework: React
Installing dependencies...
Done.

After: Branded setup flow with consistent framing

โ”Œ  create-jury_rig-app
โ”‚
โ—‡  Project name?
โ”‚  my-app
โ”‚
โ—‡  Framework?
โ”‚  โ— React (recommended)
โ”‚    Vue
โ”‚    Svelte
โ”‚
โ—†  Installing dependencies...
โ”‚
โ”œ  Next steps โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚  cd my-app                    โ”‚
โ”‚  npm run dev                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
โ”‚
โ””  You're all set!

Why this works:

  • The command now has a recognizable visual language.
  • The next action is visible at the moment the task completes.
  • The user does not need to infer state from raw text.

Example 2: Build Pipeline Dashboard

Before: Plain text logs streaming past

Running lint...
Lint completed
Running build...
Build completed
Running tests...
Tests completed

After: Live updating dashboard with parallel status

โ•ญโ”€ Build Pipeline โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚  Lint        โœ“ done    0.8s                         โ”‚
โ”‚  Build       โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”  done  2.1s โ”‚
โ”‚  Test suite  โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•ธโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  64%  1.2s โ”‚
โ”‚  Type check  โ ‹ running...                           โ”‚
โ”‚                                                     โ”‚
โ”‚  Elapsed: 2.3s    ETA: 1.4s                        โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Decision rationale:

  • Ink is justified because the interface has durable, updating state.
  • Parallel tasks are readable without drowning the user in logs.
  • The dashboard still needs a non-TTY fallback for pipes and CI.

Example 3: Error Message Transformation

Before: Cryptic technical error

Error: ENOENT: no such file or directory, open 'jury_rig.config.ts'
    at Object.openSync (fs.js:498:3)

After: Helpful, actionable error with context

โ•ญโ”€ Configuration Error โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚                                                      โ”‚
โ”‚  โœ— Could not find configuration file                 โ”‚
โ”‚                                                      โ”‚
โ”‚    Looked in:                                        โ”‚
โ”‚    โ€ข ./jury_rig.config.ts                             โ”‚
โ”‚    โ€ข ./.skill-runtime-archive/config.ts                            โ”‚
โ”‚    โ€ข ~/.skill-runtime-archive/config.ts                            โ”‚
โ”‚                                                      โ”‚
โ”‚    To fix: Run wg init to create a configuration     โ”‚
โ”‚                                                      โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

What the expert catches:

  • Users need remediation, not just failure facts.
  • Lookup context belongs in the message because it shortens the support loop.
  • Styled errors should still degrade to plain text cleanly.

Fork Guidance

Fork when the problem has distinct lanes:

  • Visual system lane: hierarchy, symbols, copy tone, spacing, and box styles.
  • Runtime compatibility lane: TTY detection, color fallback, width handling, cursor cleanup, and machine-readable modes.
  • Interaction lane: prompts, state machines, dashboards, and redraw behavior.

Keep final decisions in the parent lane so one actor owns the overall terminal language.

QUALITY GATES

  • Terminal compatibility tested: Works in macOS Terminal, iTerm2, VS Code terminal, and basic xterm
  • Color degradation verified: NO_COLOR=1, TERM=dumb, and pipe output (| cat) all produce clean text
  • Width responsiveness confirmed: Readable at 40, 80, and 120 column widths
  • Cursor cleanup implemented: SIGINT and SIGTERM handlers restore hidden cursor on all exit paths
  • Unicode safety validated: CJK characters and emoji do not break table alignment or box drawing
  • Performance benchmarked: Progress updates are capped and redraw loops do not saturate the terminal
  • Accessibility compliant: Semantic color usage is informative, not decorative
  • Machine-readable output: --json or --format=json bypasses all decoration for scripts
  • Consistent visual language: Same symbols, colors, and box styles throughout the app
  • Error messages actionable: Every error includes a specific next step or fix suggestion

Output Contract

A CLI/TUI design that clears this skill's bar carries:

  • visualSystem: semantic colors (success/warning/error/accent), consistent symbols and box styles, no rainbow vomit.
  • runtimeCompatibility: NO_COLOR/TERM=dumb honored, pipe/non-TTY output clean, exit codes meaningful, errors on stderr.
  • layout: Unicode-width-aware column alignment, reflow at 40/80/120 columns.
  • feedback: honest progress (spinner for unknown duration, bar+ETA only with a real denominator), quiet by default, --json/--format=json escape hatch.

Use scripts/cli_design_audit.mjs to audit a CLI design spec JSON and return { pass, score, findings, recommendations }; see schemas/cli-spec.schema.json for the input shape and examples/sample-input.json for a passing spec.

Reference Map

  • diagrams/01_flowchart_decision-points.md โ€” companion routing diagram for scope checks and first-pass implementation choice.
  • references/00-charmbracelet-ecosystem-overview.md โ€” fast orientation for Bubble Tea, lipgloss, gum, and adjacent tooling.
  • references/02-ink-react-for-cli.md and references/03-inkjs-ui-components.md โ€” React-flavored terminal UI guidance.
  • references/05-lipgloss-go-v2.md and references/10-huh-terminal-forms.md โ€” polished Go output and prompt surfaces.
  • references/09-log-structured-logging.md โ€” how to coexist with structured logs and machine-facing consumers.
  • schemas/cli-spec.schema.json โ€” validate a CLI design spec JSON before auditing it.
  • examples/sample-input.json โ€” a passing CLI design spec, for calibration.
  • scripts/cli_design_audit.mjs โ€” deterministic scoring of a CLI design spec against this skill's Quality Gates.
  • templates/output-template.md โ€” reusable structure for writing up a CLI/TUI design deliverable.
  • agents/openai.yaml โ€” subagent descriptor for delegated CLI/TUI design or audit.
  • README.md โ€” quick start for using this skill and its auditor.

Skill Bundle Index

Every file in this skill, and when to open it. Auto-generated; run scripts/index_references.py --fix.

root

  • `CHANGELOG.md` โ€” Beautiful Cli Design โ€” Changelog โ€” - Upgraded to the agentic-family standard: provenance moved to block-style kind: first-party, owners: [port-daddy] (prior recovery prove
  • `README.md` โ€” Beautiful CLI Design โ€” Treat the terminal as a real interface surface: hierarchy, feedback, accessibility, and fallback modes all matter โ€” for branded setup flows,
  • `affordance-scorecard.json` โ€” affordance scorecard (data/schema)

agents/

diagrams/

examples/

  • `examples/INDEX.md` โ€” Examples Index โ€” | File | When to load | |---|---| | sample-input.json | A passing cli-spec.schema.json input โ€” use as a starting point or to calibrate `
  • `examples/expected-output.md` โ€” Example Output: Beautiful CLI Design โ€” Scenario: a legacy deploy CLI paints every status line in red/green/yellow with no fallback symbol, ignores NO_COLOR, and writes its error
  • `examples/sample-input.json` โ€” sample input (data/schema)

references/

schemas/

scripts/

templates/