Open-Source Wikis

/

Bubble Tea

/

How to contribute

/

Debugging

charmbracelet/bubbletea

Debugging

Bubble Tea apps own stdin and stdout, so traditional fmt.Println debugging does not work. The library ships three escape hatches.

LogToFile

The simplest option. Add a few lines at the start of main to redirect Go's default logger to a file:

if path := os.Getenv("DEBUG"); path != "" {
    f, err := tea.LogToFile("debug.log", "debug")
    if err != nil {
        fmt.Println("fatal:", err)
        os.Exit(1)
    }
    defer f.Close()
}

Then tail -f debug.log while the program runs. LogToFile opens the file in append-mode (logging.go) and sets log's output and prefix. LogToFileWith accepts any logger that satisfies the LogOptionsSetter interface — useful for charm's log package.

TEA_TRACE

When the env var TEA_TRACE is set to a writable file path, Program configures an internal trace logger (tea.go near tracePath, traceOk := os.LookupEnv("TEA_TRACE")). The trace records every byte the renderer flushes to stdout and every input event the cancel reader receives. Useful for diagnosing tearing, off-by-one cursor moves, and "why did my program emit that escape?".

TEA_TRACE=/tmp/tea.log ./myapp

The file is opened with O_APPEND, so multiple runs accumulate. Rotate it manually.

TEA_DEBUG (panic dumps)

When TEA_DEBUG=1 and a panic occurs, recoverFromPanic writes a bubbletea-panic-<unix>.log next to the working directory containing the message and stack trace. The terminal is restored before the stack trace is written, so it is also visible inline.

Delve (headless)

Because Bubble Tea takes over the TTY, you cannot run dlv debug ./myapp in the same terminal you are debugging. Run delve in headless mode and connect from another shell:

# Terminal A
dlv debug --headless --api-version=2 --listen=127.0.0.1:43000 .

# Terminal B
dlv connect 127.0.0.1:43000

The README's "Debugging with Delve" section captures this verbatim.

Common gotchas

  • Panics leave the terminal cooked: this only happens if you set WithoutCatchPanics(). The default panic recovery resets the TTY before printing the stack.
  • Garbled output after tea.Exec: confirm your ExecCommand is actually setting stdout/stderr; the runtime defaults them to the program's TTY in osExecCommand.SetStdout / SetStderr (exec.go).
  • Mouse not working in tmux: mouse mode is requested via DEC modes; tmux must have set -g mouse on. The renderer cannot fix this for you.
  • Focus events missing in tmux: tmux requires set -g focus-events on.
  • Windows resize is missed: signals_windows.go is a stub — Windows does not deliver SIGWINCH. The runtime polls in checkResize (tty.go) instead.
  • Suspend (Ctrl+Z) does nothing on Windows: suspendSupported is false on Windows; sending SuspendMsg becomes a no-op.

Logging selected events

Rather than logging every message, gate on type:

case tea.KeyPressMsg:
    log.Printf("key: %s mod=%v", msg.String(), msg.Mod)

Msg is the ultraviolet.Event interface, so %T prints the underlying type — handy for "what kind of message is this?" debugging.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Debugging – Bubble Tea wiki | Factory