bubbletea-code-review by existential-birds/beagle
npx skills add https://github.com/existential-birds/beagle --skill bubbletea-code-review| 问题类型 | 参考文档 |
|---|---|
| Elm 架构,tea.Cmd 作为数据 | references/elm-architecture.md |
| 模型状态,消息处理 | references/model-update.md |
| 视图渲染,Lipgloss 样式 | references/view-styling.md |
| 组件组合,Huh 表单 | references/composition.md |
| Bubbles 组件(列表、表格等) | references/bubbles-components.md |
请先阅读 ! 最常见的审查错误是将正确的模式标记为错误。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 模式 | 为何正确 |
|---|---|
return m, m.loadData() | tea.Cmd 被立即返回;运行时异步执行 |
Update() 使用值接收器 | 标准的 BubbleTea 模式;模型通过值返回 |
嵌套的 m.child, cmd = m.child.Update(msg) | 正常的组件组合 |
返回 tea.Cmd 的辅助函数 | 创建命令描述符,Update 中无 I/O 操作 |
tea.Batch(cmd1, cmd2) | 命令由运行时并发执行 |
| 模式 | 为何错误 |
|---|---|
在 Update 中使用 os.ReadFile() | 阻塞 UI 线程 |
在 Update 中使用 http.Get() | 网络 I/O 阻塞 |
在 Update 中使用 time.Sleep() | 冻结 UI |
在 Update 中使用 <-channel(阻塞) | 可能无限期阻塞 |
在 Update 中使用 huh.Form.Run() | 阻塞调用 |
tea.Cmd 的辅助函数不应被标记为阻塞// 错误 - 修改模型
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.items = append(m.items, newItem) // 修改!
return m, nil
}
// 正确 - 返回新模型
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
newItems := make([]Item, len(m.items)+1)
copy(newItems, m.items)
newItems[len(m.items)] = newItem
m.items = newItems
return m, nil
}
// 错误 - Update 中阻塞
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
data, _ := os.ReadFile("config.json") // 阻塞 UI!
m.config = parse(data)
return m, nil
}
// 正确 - 使用命令
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, loadConfigCmd()
}
func loadConfigCmd() tea.Cmd {
return func() tea.Msg {
data, err := os.ReadFile("config.json")
if err != nil {
return errMsg{err}
}
return configLoadedMsg{parse(data)}
}
}
// 错误 - 每次渲染都创建新样式
func (m Model) View() string {
style := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("205"))
return style.Render("Hello")
}
// 正确 - 在包级别或模型中定义样式
var titleStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("205"))
func (m Model) View() string {
return titleStyle.Render("Hello")
}
每周安装量
109
代码仓库
GitHub 星标数
40
首次出现
2026年1月20日
安全审计
安装于
codex87
gemini-cli87
opencode85
claude-code82
github-copilot78
cursor75
| Issue Type | Reference |
|---|---|
| Elm architecture, tea.Cmd as data | references/elm-architecture.md |
| Model state, message handling | references/model-update.md |
| View rendering, Lipgloss styling | references/view-styling.md |
| Component composition, Huh forms | references/composition.md |
| Bubbles components (list, table, etc.) | references/bubbles-components.md |
Readelm-architecture.md first! The most common review mistake is flagging correct patterns as bugs.
| Pattern | Why It's Correct |
|---|---|
return m, m.loadData() | tea.Cmd is returned immediately; runtime executes async |
Value receiver on Update() | Standard BubbleTea pattern; model returned by value |
Nested m.child, cmd = m.child.Update(msg) | Normal component composition |
Helper functions returning tea.Cmd | Creates command descriptor, no I/O in Update |
tea.Batch(cmd1, cmd2) | Commands execute concurrently by runtime |
| Pattern | Why It's Wrong |
|---|---|
os.ReadFile() in Update | Blocks UI thread |
http.Get() in Update | Network I/O blocks |
time.Sleep() in Update | Freezes UI |
<-channel in Update (blocking) | May block indefinitely |
huh.Form.Run() in Update | Blocking call |
tea.Cmd are NOT flagged as blocking// BAD - mutates model
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.items = append(m.items, newItem) // mutation!
return m, nil
}
// GOOD - returns new model
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
newItems := make([]Item, len(m.items)+1)
copy(newItems, m.items)
newItems[len(m.items)] = newItem
m.items = newItems
return m, nil
}
// BAD - blocking in Update
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
data, _ := os.ReadFile("config.json") // blocks UI!
m.config = parse(data)
return m, nil
}
// GOOD - use commands
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, loadConfigCmd()
}
func loadConfigCmd() tea.Cmd {
return func() tea.Msg {
data, err := os.ReadFile("config.json")
if err != nil {
return errMsg{err}
}
return configLoadedMsg{parse(data)}
}
}
// BAD - creates new style each render
func (m Model) View() string {
style := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("205"))
return style.Render("Hello")
}
// GOOD - define styles at package level or in model
var titleStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("205"))
func (m Model) View() string {
return titleStyle.Render("Hello")
}
Weekly Installs
109
Repository
GitHub Stars
40
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubFailSocketPassSnykPass
Installed on
codex87
gemini-cli87
opencode85
claude-code82
github-copilot78
cursor75
Lark CLI妙记查询工具:快速获取飞书妙记元信息(标题、封面、时长)
35,300 周安装
ASP.NET .NET Framework容器化指南:Windows Docker容器部署完整教程
7,700 周安装
GitHub Copilot 代码注释与教程生成技能 - 自动重构Python代码并生成教学文档
7,700 周安装
代码范例蓝图生成器 - GitHub Copilot 自动扫描代码库生成高质量范例文档
7,800 周安装
CentOS Linux 问题诊断专家 | RHEL兼容命令与最佳实践解决方案
7,700 周安装
Azure资源健康诊断与修复指南 - 利用日志遥测分析问题
7,700 周安装
Azure成本优化工作流:自动分析IaC与资源,生成成本节约建议与GitHub Issue
7,700 周安装