tui

package
v0.24.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 44 Imported by: 0

Documentation

Index

Constants

View Source
const (
	SegmentModel       = "model"
	SegmentThinking    = "thinking"
	SegmentPermissions = "permissions"
	SegmentPathScope   = "pathscope"
	SegmentPlan        = "plan"
	SegmentGoal        = "goal"
	SegmentTasks       = "tasks"
	SegmentCost        = "cost"
	SegmentCache       = "cache"
	SegmentCacheCold   = "cache_cold" // prompt cache has gone cold since last run
	SegmentContext     = "context"
	SegmentMCP         = "mcp"         // configured MCP servers; red only when one really failed
	SegmentUsage       = "usage"       // plan quota (5h + weekly windows)
	SegmentUsageExtra  = "usage_extra" // pay-as-you-go spend alert
	SegmentOverage     = "overage"     // this session is drawing on extra usage NOW
	SegmentVersion     = "version"
)

Segment keys for built-in segments. Extensions should use their own unique keys.

View Source
const (
	PriorityModel       = 10
	PriorityThinking    = 20
	PriorityPermissions = 30
	PriorityPathScope   = 35
	PriorityPlan        = 40
	PriorityGoal        = 42
	PriorityTasks       = 45
	PriorityUsageExtra  = 33 // prominent: near permissions, since it means real spend
	PriorityOverage     = 34 // right after extra spend: "you're on extra right now"
	PriorityCost        = 80
	PriorityCache       = 85
	PriorityCacheCold   = 86 // right after the cache-hit meter it replaces
	PriorityUsage       = 87 // grouped with the other meters
	PriorityContext     = 90 // rightmost of the built-ins
	PriorityMCP         = 88 // grouped with the meters, before context
	PriorityVersion     = 100
)

Segment priorities (lower = further left).

Variables

View Source
var ActiveTheme = CatppuccinMocha

ActiveTheme is the current color palette used by all TUI styles. Change this and call RebuildUI() to apply a new theme.

View Source
var CatppuccinMocha = Theme{
	Base:      lipgloss.Color("#1e1e2e"),
	Mantle:    lipgloss.Color("#181825"),
	Crust:     lipgloss.Color("#11111b"),
	Surface0:  lipgloss.Color("#313244"),
	Surface1:  lipgloss.Color("#45475a"),
	Surface2:  lipgloss.Color("#585b70"),
	Text:      lipgloss.Color("#cdd6f4"),
	Subtext1:  lipgloss.Color("#bac2de"),
	Subtext0:  lipgloss.Color("#a6adc8"),
	Overlay2:  lipgloss.Color("#9399b2"),
	Overlay1:  lipgloss.Color("#7f849c"),
	Overlay0:  lipgloss.Color("#6c7086"),
	Rosewater: lipgloss.Color("#f5e0dc"),
	Flamingo:  lipgloss.Color("#f2cdcd"),
	Pink:      lipgloss.Color("#f5c2e7"),
	Mauve:     lipgloss.Color("#cba6f7"),
	Red:       lipgloss.Color("#f38ba8"),
	Maroon:    lipgloss.Color("#eba0ac"),
	Peach:     lipgloss.Color("#fab387"),
	Yellow:    lipgloss.Color("#f9e2af"),
	Green:     lipgloss.Color("#a6e3a1"),
	Teal:      lipgloss.Color("#94e2d5"),
	Sky:       lipgloss.Color("#89dceb"),
	Sapphire:  lipgloss.Color("#74c7ec"),
	Blue:      lipgloss.Color("#89b4fa"),
	Lavender:  lipgloss.Color("#b4befe"),
}

CatppuccinMocha is the default dark theme.

Functions

func FormatUserMessage

func FormatUserMessage(text string) string

FormatUserMessage renders a user message using the active layout. Kept as a compatibility shim for external callers.

func New

func New(ctx context.Context, cfg Config) appModel

New creates the TUI model. All interaction goes through the bus runtime.

func ParseCommand

func ParseCommand(text string) (string, bool)

ParseCommand returns (command string with args, true) only if text starts with a known /command. The returned string includes any arguments (e.g., "/model sonnet" → "model sonnet").

func RebuildStyles

func RebuildStyles()

RebuildStyles is a backward-compatible alias for RebuildUI.

func RebuildUI

func RebuildUI()

RebuildUI derives all styles from ActiveTheme. Called once at init; call again after swapping ActiveTheme at startup.

func RegisterLayout

func RegisterLayout(name string, l Layout) error

RegisterLayout adds a layout to the registry. Returns error on name collision.

func SetLayout

func SetLayout(name string) error

SetLayout activates a registered layout by name. Must be called before TUI starts.

func SetLayoutDirect

func SetLayoutDirect(l Layout) error

SetLayoutDirect activates a layout instance directly (for extensions providing custom layouts). Returns error if l is nil.

Types

type Config

type Config struct {
	Runtime               *bus.SessionRuntime                     // required — the session bus runtime
	SessionStore          session.SessionStore                    // persistence backend (nil = no persistence)
	Session               *session.Session                        // session to resume (nil = fresh start)
	StartInSessionBrowser bool                                    // open the session browser before entering chat
	CWD                   string                                  // working directory for session metadata
	PinnedModels          []string                                // model IDs pre-pinned for Ctrl+P cycling
	OnPinnedModelsChange  func([]string) error                    // called when the user changes pinned models
	PromptTemplates       []promptpkg.Template                    // available prompt templates
	Transcriber           core.Transcriber                        // speech-to-text for voice input (nil = disabled)
	STTLanguage           string                                  // ISO-639-1 language hint for STT ("" = auto-detect)
	STTModel              string                                  // STT model id ("" = provider default)
	STTVocabulary         []string                                // words the transcriber tends to get wrong (names, jargon)
	CacheTTL              time.Duration                           // prompt-cache retention (Anthropic); drives the "cache cold" hint
	UsagePoller           *usage.Poller                           // plan usage poller (nil = usage tracking disabled)
	ProviderFactory       func(core.Model) (core.Provider, error) // one-shot LLM calls (auto-titling); nil disables
	ReleaseInfo           release.Info                            // build metadata shown immediately in the status line
	UpdateChecker         *release.Checker                        // optional stable-release checker
	UpdateCheckEnabled    bool                                    // false disables the asynchronous check
	MCPController         *mcp.Controller                         // shared MCP controller (nil = no MCP servers / picker hidden)
}

Config configures the TUI. All fields are optional except Runtime.

type FlatLayout

type FlatLayout struct{}

FlatLayout renders a flat design with single-tone tool blocks and an inline "running…" indicator.

func (FlatLayout) RenderAssistantText

func (FlatLayout) RenderAssistantText(glamourRendered string, _ int) string

func (FlatLayout) RenderError

func (FlatLayout) RenderError(text string, _ int, theme Theme) string

func (FlatLayout) RenderLiveNotice

func (FlatLayout) RenderLiveNotice(text string, width int, theme Theme) string

func (FlatLayout) RenderStatus

func (FlatLayout) RenderStatus(text string, _ int, theme Theme) string

func (FlatLayout) RenderThinking

func (FlatLayout) RenderThinking(text string, width int, theme Theme) string

func (FlatLayout) RenderToolBlock

func (FlatLayout) RenderToolBlock(block ToolBlockData, width int, theme Theme) string

func (FlatLayout) RenderUserMessage

func (FlatLayout) RenderUserMessage(text string, width int, theme Theme) string

type Layout

type Layout interface {
	RenderUserMessage(text string, width int, theme Theme) string
	RenderThinking(text string, width int, theme Theme) string
	RenderAssistantText(glamourRendered string, width int) string
	RenderToolBlock(block ToolBlockData, width int, theme Theme) string
	RenderError(text string, width int, theme Theme) string
	RenderStatus(text string, width int, theme Theme) string
	RenderLiveNotice(text string, width int, theme Theme) string
}

Layout controls how each block type is rendered to a string. Implementations receive the active Theme so they can build styles on demand. All methods receive width for consistent line-filling behavior.

Startup-time only: set the active layout before the TUI starts.

func GetActiveLayout

func GetActiveLayout() Layout

GetActiveLayout returns the current layout. Never nil after init.

type Segment

type Segment struct {
	Key      string // stable segment identifier, used for special rendering rules
	Text     string // rendered text (may include ANSI via lipgloss)
	Priority int    // sort order: lower = further left
}

Segment is a single piece of the status line, rendered at a given priority. Lower priority values render further left.

type SplitLayout

type SplitLayout struct{}

SplitLayout renders the split design with per-verb accent colors, right-aligned status badges, and generous spacing.

Tool blocks use a single Surface0 background (matching the HTML mockup).

func (SplitLayout) RenderAssistantText

func (SplitLayout) RenderAssistantText(glamourRendered string, _ int) string

func (SplitLayout) RenderError

func (SplitLayout) RenderError(text string, _ int, theme Theme) string

func (SplitLayout) RenderLiveNotice

func (SplitLayout) RenderLiveNotice(text string, width int, theme Theme) string

func (SplitLayout) RenderStatus

func (SplitLayout) RenderStatus(text string, _ int, theme Theme) string

func (SplitLayout) RenderThinking

func (SplitLayout) RenderThinking(text string, width int, theme Theme) string

func (SplitLayout) RenderToolBlock

func (SplitLayout) RenderToolBlock(block ToolBlockData, width int, theme Theme) string

func (SplitLayout) RenderUserMessage

func (SplitLayout) RenderUserMessage(text string, width int, theme Theme) string

type StatusLine

type StatusLine struct {
	// contains filtered or unexported fields
}

StatusLine renders a horizontal bar composed of ordered segments. Designed for extensibility: segments can be added/removed/replaced by key.

Thread-safe: segments can be updated from any goroutine (e.g., agent event subscribers). The View renders a consistent snapshot.

func NewStatusLine

func NewStatusLine(style lipgloss.Style) *StatusLine

NewStatusLine creates an empty status line with the given base style.

func (*StatusLine) Clear

func (sl *StatusLine) Clear()

Clear removes all segments.

func (*StatusLine) IsEmpty

func (sl *StatusLine) IsEmpty() bool

IsEmpty returns true if no segments are set.

func (*StatusLine) Remove

func (sl *StatusLine) Remove(key string)

Remove deletes a segment by key.

func (*StatusLine) Set

func (sl *StatusLine) Set(key, text string, priority int)

Set adds or replaces a segment by key.

func (*StatusLine) UpdateCacheColdSegment

func (sl *StatusLine) UpdateCacheColdSegment(show bool)

UpdateCacheColdSegment shows a hint that the prompt cache has gone cold, so the next message pays a fresh cache-write. When shown it replaces the normal cache-hit meter (they share the same slot conceptually); the next run's accumulateCacheStats repopulates the hit meter. Uses the "medium" warning color.

func (*StatusLine) UpdateCacheSegment

func (sl *StatusLine) UpdateCacheSegment(pct int)

UpdateCacheSegment sets the cache hit rate segment. pct is 0-100. Only shown when > 0.

func (*StatusLine) UpdateContextSegment

func (sl *StatusLine) UpdateContextSegment(pct int)

UpdateContextSegment sets the context usage segment. pct is 0-100. Color changes based on usage level.

func (*StatusLine) UpdateCostSegment

func (sl *StatusLine) UpdateCostSegment(cost float64)

UpdateCostSegment sets the session cost segment.

func (*StatusLine) UpdateGoalSegment

func (sl *StatusLine) UpdateGoalSegment(label string)

UpdateGoalSegment sets the goal-mode segment. Pass "" to remove.

func (*StatusLine) UpdateMCPSegment

func (sl *StatusLine) UpdateMCPSegment(total, unhealthy, disabled int)

UpdateMCPSegment sets the MCP servers segment: a plain count, turning red only when a server that should be running actually failed/exited (unhealthy > 0). A deliberately disabled server is neutral — it never reddens the status line. total == 0 removes the segment (no servers configured).

func (*StatusLine) UpdateModelSegment

func (sl *StatusLine) UpdateModelSegment(name string)

UpdateModelSegment sets the model segment.

func (*StatusLine) UpdateOverageSegment

func (sl *StatusLine) UpdateOverageSegment(onOverage bool)

UpdateOverageSegment flags that the current request was served from extra usage (drawing on pay-as-you-go). Shown only while active, in red; removed otherwise so it never clutters the normal state.

func (*StatusLine) UpdatePathScopeSegment

func (sl *StatusLine) UpdatePathScopeSegment(scope string)

UpdatePathScopeSegment sets the filesystem path scope segment. scope should be "workspace", "ws+N", or "unrestricted".

func (*StatusLine) UpdatePermissionsSegment

func (sl *StatusLine) UpdatePermissionsSegment(mode string)

UpdatePermissionsSegment sets the permissions mode segment.

func (*StatusLine) UpdatePlanSegment

func (sl *StatusLine) UpdatePlanSegment(mode string)

UpdatePlanSegment sets the plan mode segment. Pass "" to remove.

func (*StatusLine) UpdateTasksSegment

func (sl *StatusLine) UpdateTasksSegment(done, total int)

UpdateTasksSegment sets the task progress segment.

func (*StatusLine) UpdateThinkingSegment

func (sl *StatusLine) UpdateThinkingSegment(level string)

UpdateThinkingSegment sets the thinking level segment.

func (*StatusLine) UpdateUsageExtraSegment

func (sl *StatusLine) UpdateUsageExtraSegment(used float64, symbol string, enabled bool)

UpdateUsageExtraSegment sets the pay-as-you-go spend segment. used is in major currency units and symbol is the currency symbol. Removed when extra usage is disabled; shown muted at zero and in red once credits are spent.

func (*StatusLine) UpdateUsageSegment

func (sl *StatusLine) UpdateUsageSegment(fiveHPct, weekPct int)

UpdateUsageSegment sets the plan quota segment (5h + weekly windows). Pass -1 for a window that is not reported. Removed when neither is reported.

func (*StatusLine) UpdateVersionSegment

func (sl *StatusLine) UpdateVersionSegment(current, latest string)

UpdateVersionSegment shows the build version, optionally with a newer stable release indicator. The check itself is performed asynchronously by appModel.

func (*StatusLine) View

func (sl *StatusLine) View(width int) string

View renders the status line. Returns empty string if no segments.

type Theme

type Theme struct {
	// Backgrounds (darkest → lightest)
	Base     lipgloss.Color
	Mantle   lipgloss.Color
	Crust    lipgloss.Color
	Surface0 lipgloss.Color
	Surface1 lipgloss.Color
	Surface2 lipgloss.Color

	// Text hierarchy (brightest → dimmest)
	Text     lipgloss.Color
	Subtext1 lipgloss.Color
	Subtext0 lipgloss.Color
	Overlay2 lipgloss.Color
	Overlay1 lipgloss.Color
	Overlay0 lipgloss.Color

	// Accents
	Rosewater lipgloss.Color
	Flamingo  lipgloss.Color
	Pink      lipgloss.Color
	Mauve     lipgloss.Color
	Red       lipgloss.Color
	Maroon    lipgloss.Color
	Peach     lipgloss.Color
	Yellow    lipgloss.Color
	Green     lipgloss.Color
	Teal      lipgloss.Color
	Sky       lipgloss.Color
	Sapphire  lipgloss.Color
	Blue      lipgloss.Color
	Lavender  lipgloss.Color
}

Theme defines the color palette for the TUI. Follows the Catppuccin naming convention: base/surface for backgrounds, text/subtext/overlay for text hierarchy, and named accents.

Set ActiveTheme and call RebuildUI() before the TUI starts to apply a new theme.

type ToolBlockData

type ToolBlockData struct {
	ToolName   string
	Action     string // verb: "write", "bash", "read", "edit", "search", "fetch"
	Target     string // path, command, query
	Header     string // tail-truncation notice (above body) — may be empty
	Body       string // content — may be empty (e.g. running tool with no output yet)
	Footer     string // head-truncation notice (below body) — may be empty
	IsDiff     bool   // true when Body contains unified diff (color +/- lines)
	Done       bool
	IsError    bool
	IsRejected bool
	Note       string // optional note shown in footer area (feedback/reason)
	Generating bool   // true while LLM is streaming args (before execution)
}

ToolBlockData is the layout-facing view of a tool block. All content is pre-processed (truncated/extracted). Layout only arranges it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL