Ultraviolet
<img width="400" alt="Charm Ultraviolet" src="https://github.com/user-attachments/assets/3484e4b0-3741-4e8c-bebf-9ea51f5bb49c" /
<p <a href="https://pkg.go.dev/github.com/charmbracelet/ultraviolet?tab=doc"<img src="https://godoc.org/github.com/charmbracelet/ultraviolet?status.svg" alt="GoDoc"</a <a href="https://github.com/charmbracelet/ultraviolet/actions"<img src="https://github.com/charmbracelet/ultraviolet/actions/workflows/build.yml/badge.svg" alt="Build Status"</a </p
Ultraviolet is a set of primitives for building terminal user interfaces in Go. It provides cell-based rendering, cross-platform input handling, and a diffing renderer inspired by ncurses—without the need for terminfo or termcap databases.
Ultraviolet powers [Bubble Tea v2][bbt] and [Lip Gloss v2][lg]. It replaces the ad-hoc terminal primitives from earlier versions with a cohesive, imperative API that can also be used standalone.
[bbt]: https://github.com/charmbracelet/bubbletea [lg]: https://github.com/charmbracelet/lipgloss
Install
go get github.com/charmbracelet/ultraviolet@latestQuick Start
package main
import (
"log"
uv "github.com/charmbracelet/ultraviolet"
"github.com/charmbracelet/ultraviolet/screen"
)
func main() {
t := uv.DefaultTerminal()
scr := t.Screen()scr.EnterAltScreen()
if err := t.Start(); err != nil { log.Fatalf("failed to start terminal: %v", err) } defer t.Stop()
ctx := screen.NewContext(scr) text := "Hello, World!" textWidth := scr.StringWidth(text)
display := func() { screen.Clear(scr) bounds := scr.Bounds() x := (bounds.Dx() - textWidth) / 2 y := bounds.Dy() / 2 ctx.DrawString(text, x, y) scr.Render() scr.Flush() }
for ev := range t.Events() { switch ev := ev.(type) { case uv.WindowSizeEvent: scr.Resize(ev.Width, ev.Height) display() case uv.KeyPressEvent: if ev.MatchString("q", "ctrl+c") { return } } } }
## Architecture
Ultraviolet is organized as a set of layered primitives:
- **Terminal** — manages the application lifecycle: raw mode, input event loop,
start/stop. Create one with `DefaultTerminal()` or `NewTerminal(console, opts)`.
- **TerminalScreen** — the screen state manager. Handles rendering, alternate
screen buffer, cursor, mouse modes, keyboard enhancements, bracketed paste,
window title, and more. Access it via `terminal.Screen()`.
WidthMethod) implemented by TerminalScreen, Buffer, Window, and ScreenBuffer. Write code against Screen to stay decoupled from the terminal.
- Buffer / Window — off-screen cell buffers. Buffer is a flat grid of