Skip to main content

Overview

The Program type is the core of a Bubble Tea application. It manages the event loop, rendering, input handling, and lifecycle of your terminal user interface.

Creating a Program

NewProgram

Creates a new Program with the given model and options.
model
Model
required
The initial model for the program. This is the only required parameter.
opts
...ProgramOption
Variable number of options to configure the program. See ProgramOption for available options.
Program
*Program
A pointer to the newly created Program instance.
func NewProgram(model Model, opts ...ProgramOption) *Program
Example:
p := tea.NewProgram(initialModel)
Example with options:
p := tea.NewProgram(
    initialModel,
    tea.WithInput(os.Stdin),
    tea.WithOutput(os.Stdout),
)

Program Methods

Run

Initializes the program and runs its event loops, blocking until it gets terminated.
func (p *Program) Run() (Model, error)
Model
Model
The final model state when the program exits.
error
error
An error if the program was terminated abnormally. Common errors include:
  • ErrProgramPanic: Program recovered from a panic
  • ErrProgramKilled: Program was killed
  • ErrInterrupted: Program received SIGINT or InterruptMsg
Example:
p := tea.NewProgram(model)
finalModel, err := p.Run()
if err != nil {
    log.Fatal(err)
}

Send

Sends a message to the main update function, allowing messages to be injected from outside the program.
func (p *Program) Send(msg Msg)
msg
Msg
required
The message to send to the update function.
Example:
// From outside the program
p.Send(MyCustomMsg{Data: "hello"})
If the program hasn’t started yet, this will be a blocking operation. If the program has already terminated, this will be a no-op.

Quit

Convenience function for quitting Bubble Tea programs from outside.
func (p *Program) Quit()
Example:
// Quit the program from outside
p.Quit()
To quit from within a Bubble Tea program, use the Quit() command in your Update function instead.

Kill

Stops the program immediately and restores the former terminal state. The final render is skipped.
func (p *Program) Kill()
Example:
p.Kill()
This skips the final render and immediately restores terminal state. Use Quit() for graceful shutdown.

Wait

Waits/blocks until the underlying Program finishes shutting down.
func (p *Program) Wait()
Example:
go func() {
    p.Run()
}()

// Do other work...

// Wait for the program to finish
p.Wait()

Println

Prints above the Program. This output is unmanaged and will persist across renders.
func (p *Program) Println(args ...any)
args
...any
Values to print, similar to fmt.Println.
Example:
p.Println("This message appears above the TUI")
If the altscreen is active, no output will be printed.

Printf

Prints above the Program with formatting. Similar to log.Printf, the message is printed on its own line.
func (p *Program) Printf(template string, args ...any)
template
string
required
Format template string.
args
...any
Values for the format template.
Example:
p.Printf("Received %d items", count)

ReleaseTerminal

Restores the original terminal state and cancels the input reader. Use with RestoreTerminal() to temporarily release control.
func (p *Program) ReleaseTerminal() error
error
error
Error if terminal state restoration fails.
Example:
if err := p.ReleaseTerminal(); err != nil {
    log.Fatal(err)
}
// Run another process...
if err := p.RestoreTerminal(); err != nil {
    log.Fatal(err)
}

RestoreTerminal

Reinitializes the Program’s input reader and restores the terminal to the state when the program was running.
func (p *Program) RestoreTerminal() error
error
error
Error if terminal restoration fails.

ProgramOption

Program options are functions that configure a Program. They are passed to NewProgram.

WithContext

Specifies a context in which to run the Program. Useful for cancellation from outside.
func WithContext(ctx context.Context) ProgramOption
Example:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

p := tea.NewProgram(model, tea.WithContext(ctx))

WithInput

Sets the input source (defaults to os.Stdin). Pass nil to disable input entirely.
func WithInput(input io.Reader) ProgramOption
Example:
p := tea.NewProgram(model, tea.WithInput(nil)) // Disable input

WithOutput

Sets the output destination (defaults to os.Stdout).
func WithOutput(output io.Writer) ProgramOption
Example:
var buf bytes.Buffer
p := tea.NewProgram(model, tea.WithOutput(&buf))

WithEnvironment

Sets environment variables that the program will use. Useful for remote sessions (e.g., SSH).
func WithEnvironment(env []string) ProgramOption
Example:
env := []string{"TERM=xterm-256color", "COLORTERM=truecolor"}
p := tea.NewProgram(model, tea.WithEnvironment(env))

WithoutSignalHandler

Disables the signal handler that Bubble Tea sets up. Use when you want to handle signals yourself.
func WithoutSignalHandler() ProgramOption
Example:
p := tea.NewProgram(model, tea.WithoutSignalHandler())

WithoutCatchPanics

Disables panic catching. If disabled, the terminal will be unusable after a panic.
func WithoutCatchPanics() ProgramOption
Use with caution. Without panic catching, your terminal may be left in an unusable state.

WithoutRenderer

Disables the renderer. Output and log statements are sent plainly to stdout without rendering logic.
func WithoutRenderer() ProgramOption
Example:
// Use Bubble Tea for non-TUI mode
p := tea.NewProgram(model, tea.WithoutRenderer())

WithFilter

Supplies an event filter invoked before Bubble Tea processes messages. Return nil to ignore a message.
func WithFilter(filter func(Model, Msg) Msg) ProgramOption
Example:
filter := func(m tea.Model, msg tea.Msg) tea.Msg {
    if _, ok := msg.(tea.QuitMsg); ok {
        model := m.(myModel)
        if model.hasUnsavedChanges {
            return nil // Prevent quit
        }
    }
    return msg
}

p := tea.NewProgram(model, tea.WithFilter(filter))

WithFPS

Sets a custom maximum FPS for the renderer (default: 60, max: 120).
func WithFPS(fps int) ProgramOption
Example:
p := tea.NewProgram(model, tea.WithFPS(30))

WithColorProfile

Forces a specific color profile instead of auto-detection.
func WithColorProfile(profile colorprofile.Profile) ProgramOption
Example:
import "github.com/charmbracelet/colorprofile"

p := tea.NewProgram(model, tea.WithColorProfile(colorprofile.TrueColor))

WithWindowSize

Sets the initial terminal window size. Useful for testing or non-interactive environments.
func WithWindowSize(width, height int) ProgramOption
Example:
p := tea.NewProgram(model, tea.WithWindowSize(80, 24))

Error Types

The following errors can be returned by Program.Run():

ErrProgramPanic

var ErrProgramPanic = errors.New("program experienced a panic")
Returned when the program recovers from a panic.

ErrProgramKilled

var ErrProgramKilled = errors.New("program was killed")
Returned when the program gets killed via Kill() or context cancellation.

ErrInterrupted

var ErrInterrupted = errors.New("program was interrupted")
Returned when the program receives SIGINT or an InterruptMsg.

Build docs developers (and LLMs) love