building-glamorous-tuis

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Building Glamorous TUIs with Charmbracelet

用 Charmbracelet 构建美观的 TUI

Quick Router — Start Here

快速导航 — 从这里开始

I need to...UseReference
Add prompts/spinners to a shell scriptGum (no Go)Shell Scripts
Build a Go TUIBubble Tea + Lip GlossGo TUI
Build a production-grade Go TUIAbove + elite patternsProduction Architecture
Serve a TUI over SSHWish + Bubble TeaInfrastructure
Record a terminal demoVHSShell Scripts
Find a Bubbles componentlist, table, viewport, spinner, progress...Component Catalog
Get a copy-paste patternLayouts, forms, animation, testingQuick Reference / Advanced Patterns

我想要...使用工具参考文档
给 Shell 脚本添加提示/加载动画Gum(无需 Go)Shell 脚本
开发 Go TUIBubble Tea + Lip GlossGo TUI
开发生产级 Go TUI以上工具 + 高级模式生产架构
通过 SSH 提供 TUI 服务Wish + Bubble Tea基础设施
录制终端演示视频VHSShell 脚本
查找 Bubbles 组件list、table、viewport、spinner、progress...组件目录
获取可直接复制的代码模式布局、表单、动画、测试快速参考 / 高级模式

Decision Guide

决策指南

Is it a shell script?
├─ Yes → Use Gum
│        Need recording? → VHS
│        Need AI? → Mods
└─ No (Go application)
   ├─ Just styled output? → Lip Gloss only
   ├─ Simple prompts/forms? → Huh standalone
   ├─ Full interactive TUI? → Bubble Tea + Bubbles + Lip Gloss
   │  │
   │  └─ Production-grade?  → Also add elite patterns:
   │     (multi-view, data-    two-phase async, immutable snapshots,
   │      dense, must be       adaptive layout, focus state machine,
   │      fast & polished)     semantic theming, pre-computed styles
   │                           → See Production Architecture reference
   └─ Need SSH access? → Wish + Bubble Tea

是 Shell 脚本吗?
├─ 是 → 使用 Gum
│        需要录屏? → VHS
│        需要 AI 功能? → Mods
└─ 否(Go 应用)
   ├─ 仅需要带样式的输出? → 仅用 Lip Gloss
   ├─ 简单提示/表单? → 独立使用 Huh
   ├─ 完整交互式 TUI? → Bubble Tea + Bubbles + Lip Gloss
   │  │
   │  └─ 生产级 TUI?  → 额外加入高级模式:
   │     (多视图、数据密集、必须快速流畅且体验精致)   两阶段异步、不可变快照、自适应布局、焦点状态机、语义化主题、预计算样式
   │                           → 查看生产架构参考文档
   └─ 需要 SSH 访问? → Wish + Bubble Tea

Shell Scripts (No Go Required)

Shell 脚本(无需使用 Go)

bash
brew install gum  # One-time install
bash
undefined
bash
brew install gum  # 仅需安装一次
bash
undefined

Input

输入

NAME=$(gum input --placeholder "Your name")
NAME=$(gum input --placeholder "Your name")

Selection

选择

COLOR=$(gum choose "red" "green" "blue")
COLOR=$(gum choose "red" "green" "blue")

Fuzzy filter from stdin

从标准输入模糊筛选

BRANCH=$(git branch | gum filter)
BRANCH=$(git branch | gum filter)

Confirmation

确认操作

gum confirm "Continue?" && echo "yes"
gum confirm "Continue?" && echo "yes"

Spinner

加载动画

gum spin --title "Working..." -- long-command
gum spin --title "Working..." -- long-command

Styled output

带样式的输出

gum style --border rounded --padding "1 2" "Hello"

**[Full Gum Reference →](references/shell-scripts.md#gum-the-essential-tool)**
**[VHS Recording →](references/shell-scripts.md#vhs-terminal-recording)**
**[Mods AI →](references/shell-scripts.md#mods-ai-in-terminal)**

---
gum style --border rounded --padding "1 2" "Hello"

**[完整 Gum 参考 →](references/shell-scripts.md#gum-the-essential-tool)**
**[VHS 录屏 →](references/shell-scripts.md#vhs-terminal-recording)**
**[Mods AI →](references/shell-scripts.md#mods-ai-in-terminal)**

---

Go Applications

Go 应用

bash
go get github.com/charmbracelet/bubbletea github.com/charmbracelet/lipgloss
bash
go get github.com/charmbracelet/bubbletea github.com/charmbracelet/lipgloss

Minimal TUI (Copy & Run)

最简 TUI(复制即可运行)

go
package main

import (
    "fmt"
    tea "github.com/charmbracelet/bubbletea"
    "github.com/charmbracelet/lipgloss"
)

var highlight = lipgloss.NewStyle().Foreground(lipgloss.Color("212")).Bold(true)

type model struct {
    items  []string
    cursor int
}

func (m model) Init() tea.Cmd { return nil }

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    switch msg := msg.(type) {
    case tea.KeyMsg:
        switch msg.String() {
        case "q", "ctrl+c":
            return m, tea.Quit
        case "up", "k":
            if m.cursor > 0 { m.cursor-- }
        case "down", "j":
            if m.cursor < len(m.items)-1 { m.cursor++ }
        case "enter":
            fmt.Printf("Selected: %s\n", m.items[m.cursor])
            return m, tea.Quit
        }
    }
    return m, nil
}

func (m model) View() string {
    s := ""
    for i, item := range m.items {
        if i == m.cursor {
            s += highlight.Render("▸ "+item) + "\n"
        } else {
            s += "  " + item + "\n"
        }
    }
    return s + "\n(↑/↓ move, enter select, q quit)"
}

func main() {
    m := model{items: []string{"Option A", "Option B", "Option C"}}
    tea.NewProgram(m).Run()
}
go
package main

import (
    "fmt"
    tea "github.com/charmbracelet/bubbletea"
    "github.com/charmbracelet/lipgloss"
)

var highlight = lipgloss.NewStyle().Foreground(lipgloss.Color("212")).Bold(true)

type model struct {
    items  []string
    cursor int
}

func (m model) Init() tea.Cmd { return nil }

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
    switch msg := msg.(type) {
    case tea.KeyMsg:
        switch msg.String() {
        case "q", "ctrl+c":
            return m, tea.Quit
        case "up", "k":
            if m.cursor > 0 { m.cursor-- }
        case "down", "j":
            if m.cursor < len(m.items)-1 { m.cursor++ }
        case "enter":
            fmt.Printf("Selected: %s\n", m.items[m.cursor])
            return m, tea.Quit
        }
    }
    return m, nil
}

func (m model) View() string {
    s := ""
    for i, item := range m.items {
        if i == m.cursor {
            s += highlight.Render("▸ "+item) + "\n"
        } else {
            s += "  " + item + "\n"
        }
    }
    return s + "\n(↑/↓ move, enter select, q quit)"
}

func main() {
    m := model{items: []string{"Option A", "Option B", "Option C"}}
    tea.NewProgram(m).Run()
}

Library Cheat Sheet

工具库速查表

NeedLibraryExample
TUI framework
bubbletea
tea.NewProgram(model).Run()
Components
bubbles
list.New()
,
textinput.New()
Styling
lipgloss
style.Foreground(lipgloss.Color("212"))
Forms
huh
huh.NewInput().Title("Name").Run()
Markdown
glamour
glamour.Render(md, "dark")
Animation
harmonica
harmonica.NewSpring()
Full Go TUI Guide → All Bubbles Components → Layout & Animation Patterns →

需求依赖库示例
TUI 开发框架
bubbletea
tea.NewProgram(model).Run()
UI 组件
bubbles
list.New()
,
textinput.New()
样式处理
lipgloss
style.Foreground(lipgloss.Color("212"))
表单开发
huh
huh.NewInput().Title("Name").Run()
Markdown 渲染
glamour
glamour.Render(md, "dark")
动画效果
harmonica
harmonica.NewSpring()
完整 Go TUI 指南 → 所有 Bubbles 组件 → 布局与动画模式 →

SSH Apps (Infrastructure)

SSH 应用(基础设施)

go
s, _ := wish.NewServer(
    wish.WithAddress(":2222"),
    wish.WithHostKeyPath(".ssh/key"),
    wish.WithMiddleware(
        bubbletea.Middleware(handler),
        logging.Middleware(),
    ),
)
s.ListenAndServe()
Connect:
ssh localhost -p 2222
Full Infrastructure Guide →

go
s, _ := wish.NewServer(
    wish.WithAddress(":2222"),
    wish.WithHostKeyPath(".ssh/key"),
    wish.WithMiddleware(
        bubbletea.Middleware(handler),
        logging.Middleware(),
    ),
)
s.ListenAndServe()
连接命令:
ssh localhost -p 2222
完整基础设施指南 →

Production TUI Architecture (Elite Patterns)

生产级 TUI 架构(高级模式)

Beyond basic Bubble Tea: patterns that make TUIs feel fast, polished, and professional. Each links to a full code example in Production Architecture.
基础 Bubble Tea 之外的模式,可让 TUI 更流畅、精致、专业。每个模式都链接到生产架构中的完整代码示例。

My TUI is slow or janky

我的 TUI 运行缓慢或卡顿

SymptomPatternFix
UI blocks during computationTwo-Phase AsyncPhase 1 instant, Phase 2 background goroutine
Render path holds mutexImmutable SnapshotsPre-build snapshot, atomic pointer swap
File changes cause stutterBackground WorkerDebounced watcher + coalescing
Thousands of allocs per framePre-Computed StylesAllocate delegate styles once at startup
O(n²) string concat in View()strings.BuilderPre-allocated Builder with Grow()
Glamour re-renders every frameCached MarkdownCache by content hash, invalidate on width change
GC pauses during interactionIdle-Time GCTrigger GC during idle periods
Large dataset = high memoryObject Poolingsync.Pool with pre-allocated slices
Rendering off-screen itemsViewport VirtualizationOnly render visible rows
症状模式解决方案
计算过程中 UI 阻塞两阶段异步架构第一阶段即时响应,第二阶段后台 goroutine 执行
渲染路径持有互斥锁不可变快照模式预构建快照,原子指针交换
文件变更导致卡顿带文件监听的后台 worker防抖监听 + 事件合并
每帧渲染产生数千次内存分配预计算样式提升性能启动时一次性分配所有样式
View() 中存在 O(n²) 字符串拼接在 View() 中使用 strings.Builder通过 Grow() 预分配 Builder 内存
Glamour 每帧重复渲染Markdown 渲染缓存按内容哈希缓存,宽度变更时失效
交互过程中出现 GC 停顿空闲时段 GC 管理在空闲时段触发 GC
大数据集导致内存占用过高对象池提升内存效率配合预分配切片使用 sync.Pool
渲染屏幕外的元素视口虚拟化仅渲染可见行

My layout breaks on different terminals

我的布局在不同终端上显示异常

SymptomPatternFix
Hardcoded widths breakAdaptive Layout3-4 responsive breakpoints (80/100/140/180 cols)
Colors wrong on light terminalsSemantic Theming
lipgloss.AdaptiveColor
+ WCAG AA contrast
Items have equal priority → list shufflesDeterministic SortingStable sort with tie-breaking secondary key
Sort mode not visibleDynamic Status BarLeft/right segments with gap-fill
症状模式解决方案
硬编码宽度导致显示错误自适应布局引擎3-4 个响应式断点(80/100/140/180 列)
浅色终端下颜色显示错误语义化主题系统
lipgloss.AdaptiveColor
+ WCAG AA 对比度标准
元素优先级相同导致列表顺序随机确定性稳定排序带次级排序键的稳定排序
排序模式不可见带动态分段的状态栏左右分段,中间自动填充间隙

My TUI has multiple views and it's getting messy

我的 TUI 有多个视图,代码越来越混乱

SymptomPatternFix
Key routing chaosFocus State MachineExplicit focus enum + modal priority layer
User gets lost in nested viewsBreadcrumb Navigation
Home > Board > Priority
path indicator
Overlay dismiss loses positionFocus RestorationSave focus before overlay, restore on dismiss
Old async results overwrite new dataStale Message DetectionCompare data hash before applying results
Multiple component updates per frametea.Batch AccumulationCollect cmds in slice, return
tea.Batch(cmds...)
Background goroutine panic kills TUIError Recovery
defer/recover
wrapper for all goroutines
症状模式解决方案
按键路由逻辑混乱多视图焦点状态机显式焦点枚举 + 模态优先级层级
用户在嵌套视图中迷路面包屑导航
首页 > 看板 > 优先级
路径指示器
关闭浮层后焦点位置丢失焦点恢复打开浮层前保存焦点,关闭后恢复
旧的异步结果覆盖新数据过期消息检测应用结果前对比数据哈希
每帧多次更新组件tea.Batch 命令累加将命令收集到切片中,返回
tea.Batch(cmds...)
后台 goroutine panic 导致 TUI 崩溃后台 goroutine 错误恢复所有 goroutine 加
defer/recover
包装

I want to add data-rich visualizations

我想要添加数据丰富的可视化效果

WantPatternCode
Bar charts in list columnsUnicode Sparklines
▇▅▂
using 8-level block characters
Color-by-intensityPerceptual Heatmapsgray → blue → purple → pink gradient
Dependency graph in terminalASCII Graph RendererCanvas + Manhattan routing (╭─╮│╰╯)
Age at a glanceAge Color CodingFresh=green, aging=yellow, stale=red
Borders that mean somethingSemantic BordersRed=blocked, green=ready, yellow=high-impact
需求模式代码
列表列中的柱状图Unicode 迷你折线图使用 8 级块字符实现
▇▅▂
按强度着色感知热力图灰 → 蓝 → 紫 → 粉渐变
终端中的依赖图ASCII 图渲染器画布 + 曼哈顿路由 (╭─╮│╰╯)
快速查看内容新旧程度年龄颜色编码新鲜=绿色,即将过期=黄色,过期=红色
边框携带状态信息语义化边框红色=阻塞,绿色=就绪,黄色=高影响

I want my TUI to feel polished and professional

我想让我的 TUI 体验更精致专业

WantPatternKey Idea
Vim-style
gg
/
G
Vim Key CombosTrack
waitingForG
state between keystrokes
Search without jankDebounced Search150ms timer, fire only when typing stops
Search across all fields at onceComposite FilterValueFlatten all fields into one string
4-line cards with metadataRich DelegatesCustom delegate with Height()=4
Expand detail inlineInline ExpansionToggle with
d
, auto-collapse on j/k
Copy to clipboardClipboard Integration
y
for ID,
C
for markdown + toast feedback
?
/
`
/
;
help
Multi-Tier HelpQuick ref + tutorial + persistent sidebar
Kanban with mode switchingKanban SwimlanesPre-computed board states, O(1) switch
Collapsible tree with h/lTree NavigationFlatten tree to visible list for j/k nav
Suspend TUI for vim editEditor Dispatch
tea.ExecProcess
for terminal, background for GUI
Remember expand/collapsePersistent StateSave to JSON, graceful degradation on corrupt
Tune via env varsEnv Preferences
NO_COLOR
, theme, debounce, split ratio
Optional feature missing?Graceful DegradationDetect at startup, hide unavailable features
Full Production Architecture Guide →

需求模式核心思路
Vim 风格
gg
/
G
快捷键
Vim 按键组合追踪两次按键之间追踪
waitingForG
状态
搜索无卡顿防抖搜索150ms 计时器,仅在输入停止时触发
同时搜索所有字段零分配模糊搜索的复合过滤值将所有字段扁平化为单个字符串
带元数据的 4 行卡片丰富的多行列表代理自定义代理,Height()=4
行内展开详情行内展开
d
切换,按 j/k 时自动折叠
复制到剪贴板剪贴板集成
y
复制 ID,按
C
复制 markdown + 吐司反馈
?
/
`
/
;
帮助入口
多层级帮助系统快速参考 + 教程 + 持久化侧边栏
带模式切换的看板带泳道模式的看板预计算看板状态,O(1) 切换
按 h/l 折叠/展开树树导航将树扁平化为可见列表,支持 j/k 导航
挂起 TUI 打开 vim 编辑编辑器调度终端用
tea.ExecProcess
,GUI 用后台模式
记住展开/折叠状态持久化状态保存到 JSON,损坏时优雅降级
通过环境变量调优环境变量配置
NO_COLOR
、主题、防抖时长、分屏比例
可选功能缺失?优雅降级启动时检测,隐藏不可用功能
完整生产架构指南 →

Pre-Flight Checklist (Every TUI)

上线前检查清单(所有 TUI 适用)

  • Handle
    tea.WindowSizeMsg
    — resize all components
  • Handle
    ctrl+c
    — cleanup, restore terminal state
  • Detect piped stdin/stdout — fall back to plain text
  • Test on 80×24 minimum terminal
  • Provide
    --no-tui
    /
    NO_TUI
    escape hatch
  • Test with both light AND dark backgrounds
  • Test with
    NO_COLOR=1
    and
    TERM=dumb
For production TUIs, see the full checklist (16 must-have + 20 polish items).

  • 处理
    tea.WindowSizeMsg
    — 调整所有组件大小
  • 处理
    ctrl+c
    — 清理资源,恢复终端状态
  • 检测管道输入/输出 — 降级为纯文本模式
  • 在最小 80×24 尺寸的终端上测试
  • 提供
    --no-tui
    /
    NO_TUI
    降级开关
  • 在浅色和深色背景下都进行测试
  • NO_COLOR=1
    TERM=dumb
    环境下测试
生产级 TUI 请查看完整清单(16 项必备 + 20 项优化项)。

When NOT to Use Charm

什么时候不应该使用 Charm

  • Output is piped:
    mytool | grep
    → plain text
  • CI/CD: No terminal → use flags/env vars
  • One simple prompt: Maybe
    fmt.Scanf
    is fine
Escape hatch:
go
if !term.IsTerminal(os.Stdin.Fd()) || os.Getenv("NO_TUI") != "" {
    runPlainMode()
    return
}

  • 输出被管道传输:
    mytool | grep
    → 用纯文本
  • CI/CD 环境: 无终端 → 使用参数/环境变量
  • 单个简单提示: 可能
    fmt.Scanf
    就足够了
降级开关:
go
if !term.IsTerminal(os.Stdin.Fd()) || os.Getenv("NO_TUI") != "" {
    runPlainMode()
    return
}

All References

所有参考资料

I need...Read this
Copy-paste one-linersQuick Reference
Prompts to give Claude for TUI tasksPrompts
Gum / VHS / Mods / Freeze / GlowShell Scripts
Bubble Tea architecture, debugging, anti-patternsGo TUI
Bubbles component APIs (list, table, viewport...)Component Catalog
Theming, layouts, animation, Huh forms, testingAdvanced Patterns
Elite patterns: async, snapshots, focus machines, adaptive layout, sparklines, kanban, trees, cachingProduction Architecture
Wish SSH server, Soft Serve, teatestInfrastructure
我需要...阅读本文
可直接复制的单行代码快速参考
给 Claude 的 TUI 开发提示词提示词
Gum / VHS / Mods / Freeze / Glow 用法Shell 脚本
Bubble Tea 架构、调试、反模式Go TUI
Bubbles 组件 API(list、table、viewport...)组件目录
主题、布局、动画、Huh 表单、测试高级模式
高阶模式:异步、快照、焦点状态机、自适应布局、迷你折线图、看板、树、缓存生产架构
Wish SSH 服务端、Soft Serve、teatest基础设施