CRUSH — Collaborative TUI Shell
Vendored terminal UI framework (github.com/charmbracelet/crush) — Bubble Tea terminal app infrastructure for AI-assisted development.
The Terminal AI TUI Gap
Terminal-based AI assistants need a rich TUI framework — chat history, streaming responses, tool call visualization, markdown rendering. Building this from scratch is significant work. CRUSH (from Charmbracelet) provides the Bubble Tea foundation: composable components, event-driven architecture, and a beautiful terminal UI. The task was to understand, vendor, and extend CRUSH for the Pollen ecosystem.
Most AI interactions in the terminal today are single-turn prompts piped through curl or wrapped in a thin REPL. There is no session history, no streaming visualisation, no structured tool call display. Products like GitHub Copilot CLI and Warp AI have demonstrated that developers want rich terminal-native AI experiences — but building the TUI plumbing from zero is months of work. By vendoring CRUSH, we jump-started with a production-quality Bubble Tea foundation and focused on the Pollen-specific customizations: multi-turn conversation, streaming Markdown rendering, and structured tool call cards.
Component-Based TUI Architecture
CRUSH is a Go Bubble Tea TUI app with a component-based architecture: chat view (message history with Markdown rendering), thinking block (streaming tool call visualization), provider abstraction (OpenAI-compatible API), and conversation management. The TUI uses Bubble Tea's Model/Update/View pattern with Lip Gloss styling and Bubbles components for spinners, text input, and viewport.
The core architecture follows a unidirectional data flow: user keystrokes trigger Update messages that mutate the model, View renders the current state to the terminal buffer. The chat engine maintains a slice of messages (user + assistant), each rendered via a Lip Gloss-styled component tree. Streamed responses arrive via a channel-driven provider abstraction and are incrementally appended to the assistant message buffer, causing View to re-render as tokens arrive. Tool calls are parsed from the stream and displayed as structured cards with status, duration, and output.
type Model struct {
messages []Message
provider Provider
}
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if msg.Type == tea.KeyEnter {
return m, m.provider.Stream(m.messages)
}
}
return m, nil
}
func (m Model) View() string {
return lipgloss.JoinVertical(lipgloss.Top, renderMessages(m.messages)...)
}
TUI View ↔ Bubble Tea Model ↔ Provider API ↔ LLM
User Input → Streaming Response → Render
Languages, Frameworks & Ecosystem
Key Decisions
lipgloss.Color palette defined once and referenced by name, rather than raw \033[38;5;XXXm codes scattered through rendering code. Composable styles (e.g., baseStyle.Copy().Bold(true).Foreground(accentColor)) reduce UI code by ~40% compared to string-based terminal styling, and make theme switching a single palette swap instead of a codebase-wide find-and-replace.Key Development Sessions
Project Metrics
Complete understanding and vendoring of the CRUSH TUI framework. The vendored codebase is integrated into the Pollen ecosystem as the terminal AI assistant interface, providing chat history, streaming response rendering, tool call visualization, and markdown display — all within a native terminal experience. Industry alignment: GitHub Copilot CLI (terminal-based AI coding assistant) and Warp AI (AI-native terminal with inline suggestions).