# What TUI Framework Does Mole Use? Bubble Tea Architecture Explained

> Mole utilizes the Bubble Tea framework and Elm-style architecture for its TUI. Discover the Go implementation powering this interactive terminal application.

- Repository: [Tw93/Mole](https://github.com/tw93/Mole)
- Tags: architecture
- Published: 2026-03-20

---

**Mole uses the Bubble Tea framework from Charm Bracelet to build its interactive terminal user interfaces, implementing an Elm-style Model-View-Update architecture in Go.**

The `tw93/Mole` repository relies on **Bubble Tea** as its core **TUI framework**, supplemented by **Lip-gloss** for styling. This combination powers the real-time system monitoring dashboard and file analysis interfaces that run directly in the terminal.

## Bubble Tea: The Core TUI Framework

Mole builds its interactive interfaces with **[Bubble Tea](https://github.com/charmbracelet/bubbletea)**, a Go library that provides an Elm-inspired model-view-update (MVU) architecture. The framework is declared as a dependency in `go.mod` (version 1.3.10) at line 7.

You can see the framework in action across Mole's primary commands:

- In [`cmd/status/main.go`](https://github.com/tw93/Mole/blob/main/cmd/status/main.go), the `tea` package is imported at line 13 to power the system monitoring dashboard.
- In [`cmd/analyze/main.go`](https://github.com/tw93/Mole/blob/main/cmd/analyze/main.go), the same package appears at line 17 to handle the file system analysis interface.

While Bubble Tea handles the interaction logic and event loop, Mole uses **[Lip-gloss](https://github.com/charmbracelet/lipgloss)** for all visual styling—including colors, borders, and layout composition.

## How Mole Implements the MVU Pattern

Mole follows Bubble Tea's strict **model-view-update** pattern to maintain responsive terminal interfaces. The implementation in [`cmd/status/main.go`](https://github.com/tw93/Mole/blob/main/cmd/status/main.go) demonstrates each component of this architecture.

### The Model

The UI state is encapsulated in a struct defined at lines 49–60 of [`cmd/status/main.go`](https://github.com/tw93/Mole/blob/main/cmd/status/main.go):

```go
type model struct {
    // metrics, cursor position, animation frame, flags like catHidden
}

```

This struct holds collected system metrics, the current animation frame, cursor positions, and boolean flags such as `catHidden` that control UI element visibility.

### Initialization and Commands

The `Init()` method returns a `tea.Cmd` that kicks off the application's event loop. In Mole, this starts periodic data collection and animation:

```go
return tea.Batch(tickAfter(0), animTick())

```

The `tickAfter` helper schedules the next data pull using `time.After`, while `animTick()` manages the ASCII animation timing. These commands run asynchronously, ensuring the UI remains responsive during system monitoring operations.

### The Update Loop

The `Update()` function in `func (m model) Update(msg tea.Msg)` processes all events. It handles:

- **Key bindings** (`q`, `k`, etc.) for toggling UI elements and quitting
- **Window resize events** via `tea.WindowSizeMsg`
- **Periodic data refresh** triggered by `tickMsg`, which invokes `collectCmd()`
- **Animation frames** via `animTickMsg`

Because Bubble Tea is **event-driven**, Mole can perform background system monitoring while maintaining a 60fps-feeling interface.

### The View

The `View()` method renders the terminal output as a string. In [`cmd/status/main.go`](https://github.com/tw93/Mole/blob/main/cmd/status/main.go), this function assembles a header, ASCII "mole" art, and metric cards using helper functions like `renderHeader`, `buildCards`, and `renderTwoColumns`. All styling is applied through Lip-gloss:

```go
style := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#00FF00"))

```

## Reusing the Pattern: Analyze Command

The same Bubble Tea architecture is reused in [`cmd/analyze/main.go`](https://github.com/tw93/Mole/blob/main/cmd/analyze/main.go), where a file-system scanner runs as a background command. The scanner updates the UI model with progress and results via custom messages, demonstrating how the framework accommodates long-running tasks without blocking the interface.

## Minimal Working Example

Below is a standalone snippet that mirrors Mole's Bubble Tea implementation. It demonstrates the MVU skeleton with a real-time clock update:

```go
package main

import (
	"fmt"
	"time"

	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

type model struct {
	clock time.Time
	ready bool
	quit  bool
}

type tickMsg time.Time

func (m model) Init() tea.Cmd {
	return tea.Batch(tick(), tea.Tick(time.Second, func(t time.Time) tea.Msg {
		return tickMsg(t)
	}))
}

func tick() tea.Cmd {
	return func() tea.Msg { return tickMsg(time.Now()) }
}

func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyMsg:
		if msg.String() == "q" || msg.String() == "ctrl+c" {
			m.quit = true
			return m, tea.Quit
		}
	case tickMsg:
		m.clock = time.Time(msg)
		m.ready = true
		return m, tick()
	}
	return m, nil
}

func (m model) View() string {
	if !m.ready {
		return "Loading..."
	}
	style := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#00FF00"))
	return fmt.Sprintf("%s – %s", style.Render("Mole Demo"), m.clock.Format(time.RFC1123))
}

func main() {
	p := tea.NewProgram(model{})
	if err := p.Start(); err != nil {
		fmt.Printf("error: %v\n", err)
	}
}

```

## Summary

- **Bubble Tea** serves as the primary TUI framework in `tw93/Mole`, providing the Elm-style architecture that powers all interactive terminal features.
- The **model-view-update** pattern is implemented in [`cmd/status/main.go`](https://github.com/tw93/Mole/blob/main/cmd/status/main.go) (lines 49–60 for the model struct) and [`cmd/analyze/main.go`](https://github.com/tw93/Mole/blob/main/cmd/analyze/main.go), handling everything from key presses to background system metrics collection.
- **Lip-gloss** handles all visual styling, working alongside Bubble Tea's event loop to render colored headers, cards, and ASCII art.
- Background commands like `collectCmd()` and `tickAfter` leverage Bubble Tea's asynchronous command system to keep the UI responsive during intensive operations.
- The repository also contains bash-based fallbacks in `lib/ui/*.sh` for environments where the full Bubble Tea implementation isn't required.

## Frequently Asked Questions

### What is Bubble Tea?

Bubble Tea is a Go framework for building terminal user interfaces based on the Elm architecture. It provides a state container (model), an update function for handling events, and a view function for rendering, enabling developers to create complex, interactive TUIs with clean, predictable code flows.

### Does Mole use any other UI libraries besides Bubble Tea?

Yes, Mole uses **Lip-gloss** for all styling concerns, including colors, borders, and text layout. Additionally, the repository includes shell-based UI helpers in `lib/ui/*.sh` that serve as fallbacks for simpler menu rendering when the full Bubble Tea stack isn't needed.

### Where is the Bubble Tea model defined in Mole?

The primary model struct is defined in [`cmd/status/main.go`](https://github.com/tw93/Mole/blob/main/cmd/status/main.go) at lines 49–60. This struct tracks system metrics, animation frames, cursor positions, and UI state flags like `catHidden` that control the visibility of interface elements.

### Why did Mole choose Bubble Tea over other TUI frameworks?

According to the source code, Bubble Tea's **event-driven architecture** allows Mole to keep the UI responsive while performing system-monitoring work in the background. The framework's command system lets `collectCmd()` gather metrics asynchronously, while the animation speed adapts to CPU usage via `animTickWithSpeed`—features that would be difficult to implement in traditional blocking TUI libraries.