Back to Journal
#31 Sep 14, 2025 notes

TUI vs CLI

Auto-generated from notes

CLI Framework Purpose

CLI frameworks handle argument parsing, subcommands, help generation, and error handling automatically. Without them, you’re stuck with raw arg parsing which is annoying and error-prone.

TUI Framework Purpose

TUI frameworks are only needed for interactive interfaces like forms, real-time editing, navigation between screens, and rich displays. Simple terminal output doesn’t need TUI.

CLI vs TUI Integration Patterns

CLI-First: CLI does heavy lifting, TUI for specific interactions (myapp generate --interactive) TUI-First: CLI just launches TUI modes (myapp --mode onboard) Hybrid: CLI for simple stuff, auto-switches to TUI for complex operations

Technical Integration Flow

CLI framework receives command → validates/parses → calls handler → handler decides CLI output OR launch TUI → TUI runs interactively → returns results to CLI → CLI handles final output/cleanup.

CLI: Cobra (industry standard, good for multi-command tools) or urfave/cli (minimalist) TUI: charmbracelet/bubbletea + huh (forms) + lipgloss (styling) + glamour (markdown)

LinkedIn Tool Workflow Requirements

  1. Client onboarding forms (brand details, style, competitors, influencers)
  2. Topic/abstract generation for planning periods
  3. Draft review and quality checks
  4. On-demand reactive content creation

Wrapper Architecture (Best Pattern)

CLI does everything (complete functionality), TUI is a beautiful wrapper that makes it easier/cleaner. Power users get speed via CLI, new users get guidance via TUI, automation works via CLI.

Pure TUI vs Hybrid Decision

Pure TUI: Simpler architecture, better state management, richer interactions, no context switching Loses: No automation/scripting, no CI/CD integration, no quick one-liners, no Unix piping

Bubbletea vs React Architecture

React: Multiple useState pieces scattered across components, direct mutations Bubbletea: Single state object, all changes through ONE Update function (like Redux), unidirectional flow

Bubbletea Core Concepts

Model: Your entire app’s state (data + UI + loading states) Msg: Events/actions that happen (keypresses, API responses, navigation) Update: THE BRAIN - handles every possible event and returns new state View: How to display current state on screen

Business Logic Placement

Option 1: Inside Update function directly Option 2: Separate business logic layer, Update function calls it via Commands (cleaner approach)

Screen Routing in TUI

Simple: Change currentScreen string in state, View function renders based on it Complex: Map of screen models, delegate messages to current screen model

The Core TUI Loop

Wait for messages → Update model based on your code → Update view based on model changes → User interacts to create new message → Loop continues

External APIs as Messages

User action triggers Command → Command runs async in background → Command creates response Message → Message fed back to Update function → State updated → View re-renders

Commands (Side Effects)

Commands are functions that do async work (API calls, file operations) and return Messages back to the main loop. Multiple Commands can run concurrently with tea.Batch().

Everything Becomes Messages

API responses, file operations, timer events, websocket messages, database results - all converted to Messages that flow through the same Update function for unified handling.# CLI + TUI Framework Notes

CLI Framework Purpose

CLI frameworks handle argument parsing, subcommands, help generation, and error handling automatically. Without them, you’re stuck with raw arg parsing which is annoying and error-prone.

TUI Framework Purpose

TUI frameworks are only needed for interactive interfaces like forms, real-time editing, navigation between screens, and rich displays. Simple terminal output doesn’t need TUI.

CLI vs TUI Integration Patterns

CLI-First: CLI does heavy lifting, TUI for specific interactions (myapp generate --interactive) TUI-First: CLI just launches TUI modes (myapp --mode onboard) Hybrid: CLI for simple stuff, auto-switches to TUI for complex operations

Technical Integration Flow

CLI framework receives command → validates/parses → calls handler → handler decides CLI output OR launch TUI → TUI runs interactively → returns results to CLI → CLI handles final output/cleanup.

CLI: Cobra (industry standard, good for multi-command tools) or urfave/cli (minimalist) TUI: charmbracelet/bubbletea + huh (forms) + lipgloss (styling) + glamour (markdown)

LinkedIn Tool Workflow Requirements

  1. Client onboarding forms (brand details, style, competitors, influencers)
  2. Topic/abstract generation for planning periods
  3. Draft review and quality checks
  4. On-demand reactive content creation

Wrapper Architecture (Best Pattern)

CLI does everything (complete functionality), TUI is a beautiful wrapper that makes it easier/cleaner. Power users get speed via CLI, new users get guidance via TUI, automation works via CLI.

Pure TUI vs Hybrid Decision

Pure TUI: Simpler architecture, better state management, richer interactions, no context switching Loses: No automation/scripting, no CI/CD integration, no quick one-liners, no Unix piping

Bubbletea vs React Architecture

React: Multiple useState pieces scattered across components, direct mutations Bubbletea: Single state object, all changes through ONE Update function (like Redux), unidirectional flow

Bubbletea Core Concepts

Model: Your entire app’s state (data + UI + loading states) Msg: Events/actions that happen (keypresses, API responses, navigation) Update: THE BRAIN - handles every possible event and returns new state View: How to display current state on screen

Business Logic Placement

Option 1: Inside Update function directly Option 2: Separate business logic layer, Update function calls it via Commands (cleaner approach)

Screen Routing in TUI

Simple: Change currentScreen string in state, View function renders based on it Complex: Map of screen models, delegate messages to current screen model

The Core TUI Loop

Wait for messages → Update model based on your code → Update view based on model changes → User interacts to create new message → Loop continues

External APIs as Messages

User action triggers Command → Command runs async in background → Command creates response Message → Message fed back to Update function → State updated → View re-renders

Commands (Side Effects)

Commands are functions that do async work (API calls, file operations) and return Messages back to the main loop. Multiple Commands can run concurrently with tea.Batch().

Everything Becomes Messages

API responses, file operations, timer events, websocket messages, database results - all converted to Messages that flow through the same Update function for unified handling.