Guide · Open source
How to use Bubble Tea: build a terminal app in Go
Updated · written with AI from the project's own documentation and checked against our catalogue data
Bubble Tea is a Go framework for building terminal applications, the text-based programs you run in a command line window. This guide walks through the official shopping-list tutorial so you can see how a small interactive program is put together. After reading it, you will understand the model, Init, Update and View methods and how to start a program with tea.NewProgram.
Quick start
- 1Install the library. Fetch Bubble Tea into a Go module by running go mod tidy in your project, as the tutorial suggests. You need Go installed.
- 2Create the model. Define a struct holding the choices, the cursor index and a map of selected items.
- 3Write Init. Return nil from Init when the program needs no initial I/O.
- 4Handle key presses in Update. Switch on tea.KeyPressMsg and update the model for keys such as up, down, enter and q.
- 5Render with View. Build a string from the model and return it with tea.NewView.
- 6Start the program. Pass the initial model to tea.NewProgram and call Run, handling any error.
What Bubble Tea is and how it is structured
Bubble Tea is based on The Elm Architecture, a pattern where the app keeps a model of its state, updates that state when events arrive, and renders a view from that state. The README describes it as well-suited for simple and complex terminal applications, either inline, full-window, or a mix of both.
The tutorial assumes you have a working knowledge of Go.
- Model: a type, usually a struct, that stores application state.
- Init: returns an initial command for the application to run.
- Update: handles incoming messages and returns an updated model.
- View: renders the UI from the model.
Set up the imports for your program
Start with a main package and import the standard libraries you need plus the Bubble Tea library, which the tutorial calls tea for short. The README notes that you may need to run go mod tidy to download bubbletea and its dependencies.
package main
import (
"fmt"
"os"
tea "charm.land/bubbletea/v2"
)Define the model that stores state
The model holds the shopping list items, the cursor position, and which items are selected. The tutorial uses a map as a set of selected indexes.
- choices: the items on the list.
- cursor: the index of the item the cursor points at.
- selected: a map of which items are selected.
type model struct {
choices []string
cursor int
selected map[int]struct{}
}Write Init and the initial state
Init can return a Cmd that performs initial I/O. The tutorial needs no I/O at this point, so Init returns nil, which means no command. The initial model is created in a separate function that fills in the list and an empty selection map.
func initialModel() model {
return model{
choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"},
selected: make(map[int]struct{}),
}
}
func (m model) Init() tea.Cmd {
return nil
}Handle key presses in Update
Update is called when things happen. Key presses arrive as tea.KeyPressMsg messages. In the tutorial, ctrl+c and q return tea.Quit to exit the program, up and k move the cursor up, down and j move it down, and enter or space toggle the selected state of the item under the cursor. Update returns the updated model and a nil command when no further work is needed.
- ctrl+c or q: quit the program with tea.Quit.
- up or k: move the cursor up.
- down or j: move the cursor down.
- enter or space: toggle selection of the current item.
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
case "up", "k":
if m.cursor > 0 {
m.cursor--
}
case "down", "j":
if m.cursor < len(m.choices)-1 {
m.cursor++
}
case "enter", "space":
_, ok := m.selected[m.cursor]
if ok {
delete(m.selected, m.cursor)
} else {
m.selected[m.cursor] = struct{}{}
}
}
}
return m, nil
}Render the screen in View
View looks at the current model and builds a tea.View. You do not write redrawing logic yourself, because Bubble Tea takes care of redrawing. The view can also declare optional terminal features such as alt screen mode, mouse tracking and cursor position. The tutorial's view draws a header, one row per item with a cursor marker and a selection checkbox, and a footer.
func (m model) View() tea.View {
s := "What should we buy at the market?\n\n"
for i, choice := range m.choices {
cursor := " "
if m.cursor == i {
cursor = ">"
}
checked := " "
if _, ok := m.selected[i]; ok {
checked = "x"
}
s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice)
}
s += "\nPress q to quit.\n"
return tea.NewView(s)
}Run the program with tea.NewProgram
To start the app, pass the initial model to tea.NewProgram and call Run. If Run returns an error, the tutorial prints it and exits with status 1.
func main() {
p := tea.NewProgram(initialModel())
if _, err := p.Run(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
}
}Where to go next
The tutorial covers the basics of an interactive terminal UI. Real programs also need I/O, which the README points to in the Command Tutorial. The README also links to Bubble Tea examples and Go docs. The Bubbles repository offers common UI components such as text inputs.
- Command Tutorial for I/O.
- Bubble Tea examples in the repository.
- Go docs on pkg.go.dev.
- Bubbles, a library of UI components.
What people use it for
- Building a shopping or to-do list that you navigate with arrow keys or j and k.
- Creating an interactive command-line tool with a visual, keyboard-driven interface.
- Writing terminal apps that need keyboard and mouse input.
- Learning terminal UI basics in Go by following the official tutorial.
Frequently asked questions
Is Bubble Tea free to use?
Yes. Bubble Tea is released under the MIT licence, as listed on its repository page. Check the licence file in the repository for the full terms.
What do I need to use Bubble Tea?
You need Go, since Bubble Tea is a framework only for Go code. The tutorial assumes working knowledge of Go. Fetch the library into a Go module with go mod tidy.
How do I install Bubble Tea?
The README's install step is to fetch the library into a Go module using go mod tidy, after you have written an import of charm.land/bubbletea/v2 in your code. The tutorial's imports show the path to use.
Can Bubble Tea handle mouse input?
Yes. The README lists keyboard and mouse handling among its features, and the view can declare mouse tracking as an optional terminal feature.
What are alternatives to Bubble Tea?
The comparable projects listed for this item are tview, termui and Termbox-go. They are also Go libraries for building terminal interfaces, so you can compare them against Bubble Tea for your project.
Does Bubble Tea work for graphical desktop or web apps?
No. Bubble Tea targets terminals, so it is not suited to projects that need a graphical desktop or web interface.
New agent skills, repos and AI tools — every week
The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.
Our verdict
Bubble Tea suits Go developers who want to build interactive command-line tools with a clear, state-driven structure and keyboard or mouse input. It is not a good choice if you do not write Go, if you want a finished app rather than a library, or if you need a graphical or web interface.
Install options & downloads