npx skills add https://github.com/ggprompts/tfe --skill bubbletea使用 Go、Bubbletea 和 Lipgloss 构建精美终端用户界面的生产就绪技能。
在以下情况下使用此技能:
关键提示:在实现任何布局之前,请查阅 references/golden-rules.md 了解 4 条黄金法则。这些规则可以防止最常见且令人沮丧的 TUI 布局错误。
完整细节和示例见 references/golden-rules.md。
此项目包含一个生产就绪的模板系统。当此技能与新项目捆绑时(通过 new_project.sh),请使用现有的模板结构作为起点。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
所有新项目都遵循此架构:
your-app/
├── main.go # 入口点(最小化,约 21 行)
├── types.go # 类型定义、结构体、枚举
├── model.go # 模型初始化与布局计算
├── update.go # 消息分发器
├── update_keyboard.go # 键盘处理
├── update_mouse.go # 鼠标处理
├── view.go # 视图渲染与布局
├── styles.go # Lipgloss 样式定义
├── config.go # 配置管理
└── .claude/skills/bubbletea/ # 此技能(已捆绑)
main.go 最小化(仅作为入口点,约 21 行)types.go 中(结构体、枚举、常量)完整可重用组件目录见 references/components.md:
模板中提供基于物理的优美动画:
使用示例和集成模式见 references/effects.md。
实现布局时,请遵循以下顺序:
func (m model) calculateLayout() (int, int) {
contentWidth := m.width
contentHeight := m.height
// 减去 UI 元素
if m.config.UI.ShowTitle {
contentHeight -= 3 // 标题栏(3 行)
}
if m.config.UI.ShowStatus {
contentHeight -= 1 // 状态栏
}
// 关键:考虑面板边框
contentHeight -= 2 // 顶部 + 底部边框
return contentWidth, contentHeight
}
// 根据焦点/手风琴模式计算权重
leftWeight, rightWeight := 1, 1
if m.accordionMode && m.focusedPanel == "left" {
leftWeight = 2 // 焦点面板获得 2 倍权重
}
// 根据权重计算实际宽度
totalWeight := leftWeight + rightWeight
leftWidth := (availableWidth * leftWeight) / totalWeight
rightWidth := availableWidth - leftWidth
// 计算最大文本宽度以防止换行
maxTextWidth := panelWidth - 4 // -2 边框,-2 内边距
// 在渲染前截断所有文本
title = truncateString(title, maxTextWidth)
subtitle = truncateString(subtitle, maxTextWidth)
func truncateString(s string, maxLen int) string {
if len(s) <= maxLen {
return s
}
return s[:maxLen-1] + "…"
}
在处理鼠标事件前,始终检查布局模式:
func (m model) handleLeftClick(msg tea.MouseMsg) (tea.Model, tea.Cmd) {
if m.shouldUseVerticalStack() {
// 垂直堆叠模式:使用 Y 坐标
topHeight, _ := m.calculateVerticalStackLayout()
relY := msg.Y - contentStartY
if relY < topHeight {
m.focusedPanel = "left" // 顶部面板
} else {
m.focusedPanel = "right" // 底部面板
}
} else {
// 并排模式:使用 X 坐标
leftWidth, _ := m.calculateDualPaneLayout()
if msg.X < leftWidth {
m.focusedPanel = "left"
} else {
m.focusedPanel = "right"
}
}
return m, nil
}
常见问题的详细解决方案见 references/troubleshooting.md:
// 错误:可能导致错位
panelStyle := lipgloss.NewStyle().
Border(border).
Height(height) // 不要这样做!
// 正确:将内容行填充到精确高度
for len(lines) < innerHeight {
lines = append(lines, "")
}
panelStyle := lipgloss.NewStyle().Border(border)
当面板未对齐或渲染不正确时:
完整的调试决策树见 references/troubleshooting.md。
所有项目都支持 YAML 配置并具有热重载功能:
theme: "dark"
keybindings: "default"
layout:
type: "dual_pane"
split_ratio: 0.5
accordion_mode: true
ui:
show_title: true
show_status: true
mouse_enabled: true
show_icons: true
配置文件从以下位置加载:
~/.config/your-app/config.yaml(用户配置)./config.yaml(本地覆盖)必需:
github.com/charmbracelet/bubbletea
github.com/charmbracelet/lipgloss
github.com/charmbracelet/bubbles
gopkg.in/yaml.v3
可选(根据需要取消 go.mod 中的注释):
github.com/charmbracelet/glamour # Markdown 渲染
github.com/charmbracelet/huh # 表单
github.com/alecthomas/chroma/v2 # 语法高亮
github.com/evertras/bubble-table # 交互式表格
github.com/koki-develop/go-fzf # 模糊查找器
所有参考文件都根据需要逐步加载:
遵循这些模式,你将避免 90% 的 TUI 布局错误。
每周安装数
136
仓库
GitHub 星标数
13
首次出现
2026 年 1 月 26 日
安全审计
安装于
opencode130
codex126
github-copilot126
gemini-cli125
kimi-cli111
amp111
Production-ready skill for building beautiful terminal user interfaces with Go, Bubbletea, and Lipgloss.
Use this skill when:
CRITICAL : Before implementing ANY layout, consult references/golden-rules.md for the 4 Golden Rules. These rules prevent the most common and frustrating TUI layout bugs.
Full details and examples in references/golden-rules.md.
This project includes a production-ready template system. When this skill is bundled with a new project (via new_project.sh), use the existing template structure as the starting point.
All new projects follow this architecture:
your-app/
├── main.go # Entry point (minimal, ~21 lines)
├── types.go # Type definitions, structs, enums
├── model.go # Model initialization & layout calculation
├── update.go # Message dispatcher
├── update_keyboard.go # Keyboard handling
├── update_mouse.go # Mouse handling
├── view.go # View rendering & layouts
├── styles.go # Lipgloss style definitions
├── config.go # Configuration management
└── .claude/skills/bubbletea/ # This skill (bundled)
main.go minimal (entry point only, ~21 lines)types.go (structs, enums, constants)See references/components.md for the complete catalog of reusable components:
Beautiful physics-based animations available in the template:
See references/effects.md for usage examples and integration patterns.
When implementing layouts, follow this sequence:
func (m model) calculateLayout() (int, int) {
contentWidth := m.width
contentHeight := m.height
// Subtract UI elements
if m.config.UI.ShowTitle {
contentHeight -= 3 // title bar (3 lines)
}
if m.config.UI.ShowStatus {
contentHeight -= 1 // status bar
}
// CRITICAL: Account for panel borders
contentHeight -= 2 // top + bottom borders
return contentWidth, contentHeight
}
// Calculate weights based on focus/accordion mode
leftWeight, rightWeight := 1, 1
if m.accordionMode && m.focusedPanel == "left" {
leftWeight = 2 // Focused panel gets 2x weight
}
// Calculate actual widths from weights
totalWeight := leftWeight + rightWeight
leftWidth := (availableWidth * leftWeight) / totalWeight
rightWidth := availableWidth - leftWidth
// Calculate max text width to prevent wrapping
maxTextWidth := panelWidth - 4 // -2 borders, -2 padding
// Truncate ALL text before rendering
title = truncateString(title, maxTextWidth)
subtitle = truncateString(subtitle, maxTextWidth)
func truncateString(s string, maxLen int) string {
if len(s) <= maxLen {
return s
}
return s[:maxLen-1] + "…"
}
Always check layout mode before processing mouse events:
func (m model) handleLeftClick(msg tea.MouseMsg) (tea.Model, tea.Cmd) {
if m.shouldUseVerticalStack() {
// Vertical stack mode: use Y coordinates
topHeight, _ := m.calculateVerticalStackLayout()
relY := msg.Y - contentStartY
if relY < topHeight {
m.focusedPanel = "left" // Top panel
} else {
m.focusedPanel = "right" // Bottom panel
}
} else {
// Side-by-side mode: use X coordinates
leftWidth, _ := m.calculateDualPaneLayout()
if msg.X < leftWidth {
m.focusedPanel = "left"
} else {
m.focusedPanel = "right"
}
}
return m, nil
}
See references/troubleshooting.md for detailed solutions to common issues:
// BAD: Can cause misalignment
panelStyle := lipgloss.NewStyle().
Border(border).
Height(height) // Don't do this!
// GOOD: Fill content lines to exact height
for len(lines) < innerHeight {
lines = append(lines, "")
}
panelStyle := lipgloss.NewStyle().Border(border)
When panels don't align or render incorrectly:
See references/troubleshooting.md for the complete debugging decision tree.
All projects support YAML configuration with hot-reload:
theme: "dark"
keybindings: "default"
layout:
type: "dual_pane"
split_ratio: 0.5
accordion_mode: true
ui:
show_title: true
show_status: true
mouse_enabled: true
show_icons: true
Configuration files are loaded from:
~/.config/your-app/config.yaml (user config)./config.yaml (local override)Required:
github.com/charmbracelet/bubbletea
github.com/charmbracelet/lipgloss
github.com/charmbracelet/bubbles
gopkg.in/yaml.v3
Optional (uncomment in go.mod as needed):
github.com/charmbracelet/glamour # Markdown rendering
github.com/charmbracelet/huh # Forms
github.com/alecthomas/chroma/v2 # Syntax highlighting
github.com/evertras/bubble-table # Interactive tables
github.com/koki-develop/go-fzf # Fuzzy finder
All reference files are loaded progressively as needed:
Follow these patterns and you'll avoid 90% of TUI layout bugs.
Weekly Installs
136
Repository
GitHub Stars
13
First Seen
Jan 26, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode130
codex126
github-copilot126
gemini-cli125
kimi-cli111
amp111
LarkSuite Whiteboard CLI 工具:自动化生成专业图表与画板,支持DSL和Mermaid
37,400 周安装