Reviews BubbleTea TUI code for proper Elm architecture, model/update/view patterns, and Lipgloss styling. Use when reviewing terminal UI code using charmbracelet/bubbletea.
/plugin marketplace add existential-birds/beagle/plugin install beagle@existential-birdsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/bubbles-components.mdreferences/composition.mdreferences/elm-architecture.mdreferences/model-update.mdreferences/view-styling.md| 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 |
Read elm-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")
}
Use when working with Payload CMS projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.