PHOENIX(1)

NAME

phoenixHigh-performance TUI framework for Go with DDD + Rich model inspired architecture, perfect Unicode, and Elm-inspired…

SYNOPSIS

$https://github.com/phoenix-tui/phoenix/releases

INFO

22 stars
1 forks
0 views

DESCRIPTION

High-performance TUI framework for Go with DDD + Rich model inspired architecture, perfect Unicode, and Elm-inspired design. Modern alternative to Bubbletea/Lipgloss.

README

Phoenix TUI Framework

Phoenix TUI Framework

Go Version Release CI Go Report Card License GoDoc codecov

Multi-module monorepo - 10 independent libraries. Full metrics in CI.

Next-generation Terminal User Interface framework for Go

Organization: github.com/phoenix-tui Go Version: 1.25+

Why Phoenix?

Phoenix rises from the ashes of legacy TUI frameworks, solving critical problems:

  • Perfect Unicode/Emoji support - No more layout bugs
  • High Performance - Differential rendering, caching, zero allocations
  • DDD Architecture - Clean, testable, extendable
  • Rich Component Library - Everything you need out of the box
  • Public Cursor API - Full control for shell applications
  • Inline & Alt-Screen rendering - Per-line diffing without alt screen, or full-screen mode
  • TTY Control - Run editors, shells, and other processes from within your TUI
  • Easy Migration from Charm - Comprehensive migration guide included

Libraries

Phoenix is a modular framework with 10 independent libraries:

LibraryDescription
phoenix/coreTerminal primitives, Unicode/Emoji support (correct width calculation)
phoenix/terminalANSI terminal operations, raw mode, capabilities
phoenix/styleCSS-like styling + Theme System (presets, runtime switching)
phoenix/layoutFlexbox & grid layout (box model, responsive sizing)
phoenix/teaElm Architecture + TTY Control + Inline Renderer
phoenix/renderHigh-performance differential renderer
phoenix/componentsUI components: TextArea, TextInput, List, Viewport, Table, Modal, Progress, Select, MultiSelect, Confirm, Form
phoenix/mouseMouse events (click, scroll, drag-drop, right-click)
phoenix/clipboardCross-platform clipboard (OSC 52 for SSH)
phoenix/testingMock terminal and test utilities

Installation

Install All Libraries (Recommended for new projects)

go get github.com/phoenix-tui/phoenix@latest

This installs the umbrella module with convenient access to all Phoenix libraries through a single import:

import "github.com/phoenix-tui/phoenix"

// Use convenience API term := phoenix.AutoDetectTerminal() style := phoenix.NewStyle().Foreground("#00FF00").Bold() p := phoenix.NewProgram(myModel, phoenix.WithAltScreenMyModel)

Install Individual Libraries (For existing projects or selective use)

go get github.com/phoenix-tui/phoenix/tea@latest        # Elm Architecture
go get github.com/phoenix-tui/phoenix/components@latest # UI Components
go get github.com/phoenix-tui/phoenix/style@latest      # Styling
go get github.com/phoenix-tui/phoenix/core@latest       # Terminal primitives

Individual imports give you more control and smaller dependencies:

import (
    tea "github.com/phoenix-tui/phoenix/tea/api"
    "github.com/phoenix-tui/phoenix/components/input/api"
)

Quick Start

Using the Umbrella Module

go get github.com/phoenix-tui/phoenix@latest
package main

import ( "fmt" "os" "github.com/phoenix-tui/phoenix" tea "github.com/phoenix-tui/phoenix/tea/api" )

type Model struct { count int }

func (m Model) Init() tea.Cmd { return nil }

func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: if msg.String() == "q" { return m, phoenix.Quit() } m.count++ } return m, nil }

func (m Model) View() string { style := phoenix.NewStyle().Foreground("#00FF00").Bold() return style.Render(fmt.Sprintf("Count: %d\n", m.count)) }

func main() { p := phoenix.NewProgram(Model{}, phoenix.WithAltScreenModel) if err := p.Run(); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } }

Using Individual Libraries

go get github.com/phoenix-tui/phoenix/tea@latest
package main

import ( "fmt" "os" "github.com/phoenix-tui/phoenix/tea/api" )

type Model struct { count int }

func (m Model) Init() api.Cmd { return nil }

func (m Model) Update(msg api.Msg) (Model, api.Cmd) { switch msg := msg.(type) { case api.KeyMsg: if msg.String() == "q" { return m, api.Quit() } m.count++ } return m, nil }

func (m Model) View() string { return fmt.Sprintf("Count: %d\nPress any key to increment, 'q' to quit\n", m.count) }

func main() { p := api.New(Model{}, api.WithAltScreenModel) if err := p.Run(); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } }

Documentation

Key Features

1. Perfect Unicode/Emoji Support

Problem: Charm's Lipgloss has broken emoji width calculation (issue #562) Solution: Phoenix uses grapheme cluster detection with correct East Asian Width (UAX #11)

// Phoenix: CORRECT
text := "Hello 👋 World 🌍"
width := style.Width(text)  // Returns 17 (correct!)

// Charm Lipgloss: BROKEN width := lipgloss.Width(text) // Returns 19 (wrong!)

2. High Performance

Techniques: Differential rendering, virtual buffer, caching, zero allocations on hot paths

3. DDD Architecture

library/
├── domain/        # Business logic (highest coverage)
├── application/   # Use cases
├── infrastructure/ # Technical details
└── api/           # Public interface

4. Public Cursor API

Problem: Bubbles TextArea has private cursor - syntax highlighting impossible Solution: Phoenix TextInput exposes CursorPosition() and ContentParts()

// Phoenix: PUBLIC API (syntax highlighting works!)
before, at, after := input.ContentParts()
highlighted := syntax.Highlight(before) +
               cursor.Render(at) +
               syntax.Highlight(after)

// Bubbles: PRIVATE (syntax highlighting impossible!) // cursor is internal field - no access

5. TTY Control

Run external processes (vim, shells, pagers) from within your TUI:

case api.KeyMsg:
    if msg.String() == "e" {
        return m, api.ExecProcess("vim", "file.txt")
    }
case api.ExecProcessFinishedMsg:
    // Editor closed, TUI restored automatically

6. Inline Rendering

Run without alt screen - per-line diffing renders updates in place:

p := api.New(myModel) // inline mode by default - no alt screen needed

7. Mouse & Clipboard Support

Mouse: All buttons (Left, Right, Middle, Wheel), drag-drop, click detection (single/double/triple) Clipboard: Cross-platform (Windows/macOS/Linux), SSH support (OSC 52)

8. Progress Component

Progress bars and 15 animated spinner styles:

import progress "github.com/phoenix-tui/phoenix/components/progress/api"

bar := progress.NewBar(100).SetWidth(40).SetLabel("Downloading").SetValue(65) spinner := progress.NewSpinner(progress.SpinnerDots).SetLabel("Loading")

Comparison with Charm Ecosystem

FeaturePhoenixCharm (Bubbletea/Lipgloss)
Unicode/EmojiCorrect width (UAX #11)Broken (#562)
Type SafetyGeneric constraintsinterface{} casts
Inline RenderingPer-line diffingBasic
TTY ControlExecProcess + Suspend/ResumeExecProcess only
Cursor APIPublicPrivate
ArchitectureDDD layersMonolithic
Theme SystemBuilt-in (4 presets)Manual

Contributing

Phoenix is part of an active development effort. See CONTRIBUTING.md for contribution guidelines and GoDoc for API documentation.

License

MIT License - see LICENSE file for details

Special Thanks

Professor Ancha Baranova - This project would not have been possible without her invaluable help and support. Her assistance was crucial in bringing Phoenix to life.


Rising from the ashes of legacy TUI frameworks

SEE ALSO

clihub3/6/2026PHOENIX(1)