ui

package
v0.54.0 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package ui provides terminal styling for beads CLI output.

Package ui provides terminal styling and pager support for beads CLI output.

Package ui provides terminal styling for beads CLI output. Uses the Ayu color theme with adaptive light/dark mode support.

Package ui provides terminal styling and output helpers for beads CLI.

Index

Constants

View Source
const (
	IconPass = "✓"
	IconWarn = "⚠"
	IconFail = "✖"
	IconSkip = "-"
	IconInfo = "ℹ"
)

Status icons - consistent semantic indicators

View Source
const (
	StatusIconOpen       = "○" // available to work (hollow circle)
	StatusIconInProgress = "◐" // active work (half-filled)
	StatusIconBlocked    = "●" // needs attention (filled circle)
	StatusIconClosed     = "✓" // completed (checkmark)
	StatusIconDeferred   = "❄" // scheduled for later (snowflake)
	StatusIconPinned     = "📌" // elevated priority
)

Issue status icons - used consistently across all commands Design principle: icons > text labels for scannability IMPORTANT: Use small Unicode symbols, NOT emoji-style icons (🔴🟠 etc.) Emoji blobs cause cognitive overload and break visual consistency

View Source
const (
	TreeChild  = "⎿ "  // child indicator
	TreeLast   = "└─ " // last child / detail line
	TreeIndent = "  "  // 2-space indent per level
)

Tree characters for hierarchical display

View Source
const (
	SeparatorLight = "" /* 126-byte string literal not displayed */
	SeparatorHeavy = "" /* 126-byte string literal not displayed */
)

Separators

View Source
View Source
const PriorityIcon = "●"

Priority icon - small filled circle, colored by priority level IMPORTANT: Use this small circle, NOT emoji blobs (🔴🟠🟡🔵⚪)

Variables

View Source
var (
	// Core semantic colors (Ayu theme - adaptive light/dark)
	ColorPass = lipgloss.AdaptiveColor{
		Light: "#86b300",
		Dark:  "#c2d94c",
	}
	ColorWarn = lipgloss.AdaptiveColor{
		Light: "#f2ae49",
		Dark:  "#ffb454",
	}
	ColorFail = lipgloss.AdaptiveColor{
		Light: "#f07171",
		Dark:  "#f07178",
	}
	ColorMuted = lipgloss.AdaptiveColor{
		Light: "#828c99",
		Dark:  "#6c7680",
	}
	ColorAccent = lipgloss.AdaptiveColor{
		Light: "#399ee6",
		Dark:  "#59c2ff",
	}

	// === Workflow Status Colors ===
	// Only actionable states get color - open/closed match standard text
	ColorStatusOpen = lipgloss.AdaptiveColor{
		Light: "",
		Dark:  "",
	}
	ColorStatusInProgress = lipgloss.AdaptiveColor{
		Light: "#f2ae49",
		Dark:  "#ffb454",
	}
	ColorStatusClosed = lipgloss.AdaptiveColor{
		Light: "#9099a1",
		Dark:  "#8090a0",
	}
	ColorStatusBlocked = lipgloss.AdaptiveColor{
		Light: "#f07171",
		Dark:  "#f26d78",
	}
	ColorStatusPinned = lipgloss.AdaptiveColor{
		Light: "#d2a6ff",
		Dark:  "#d2a6ff",
	}
	ColorStatusHooked = lipgloss.AdaptiveColor{
		Light: "#59c2ff",
		Dark:  "#59c2ff",
	}

	// === Priority Colors ===
	// Only P0/P1 get color - they need attention
	// P2/P3/P4 are neutral (medium/low/backlog don't need visual urgency)
	ColorPriorityP0 = lipgloss.AdaptiveColor{
		Light: "#f07171",
		Dark:  "#f07178",
	}
	ColorPriorityP1 = lipgloss.AdaptiveColor{
		Light: "#ff8f40",
		Dark:  "#ff8f40",
	}
	ColorPriorityP2 = lipgloss.AdaptiveColor{
		Light: "#e6b450",
		Dark:  "#e6b450",
	}
	ColorPriorityP3 = lipgloss.AdaptiveColor{
		Light: "",
		Dark:  "",
	}
	ColorPriorityP4 = lipgloss.AdaptiveColor{
		Light: "",
		Dark:  "",
	}

	// === Issue Type Colors ===
	// Bugs and epics get color - they need attention
	// All other types use standard text
	ColorTypeBug = lipgloss.AdaptiveColor{
		Light: "#f07171",
		Dark:  "#f26d78",
	}
	ColorTypeFeature = lipgloss.AdaptiveColor{
		Light: "",
		Dark:  "",
	}
	ColorTypeTask = lipgloss.AdaptiveColor{
		Light: "",
		Dark:  "",
	}
	ColorTypeEpic = lipgloss.AdaptiveColor{
		Light: "#d2a6ff",
		Dark:  "#d2a6ff",
	}
	ColorTypeChore = lipgloss.AdaptiveColor{
		Light: "",
		Dark:  "",
	}

	// === Issue ID Color ===
	// IDs use standard text color - subtle, not attention-grabbing
	ColorID = lipgloss.AdaptiveColor{
		Light: "",
		Dark:  "",
	}
)

Ayu theme color palette Dark: https://terminalcolors.com/themes/ayu/dark/ Light: https://terminalcolors.com/themes/ayu/light/ Source: https://github.com/ayu-theme/ayu-colors

View Source
var (
	PassStyle   = lipgloss.NewStyle().Foreground(ColorPass)
	WarnStyle   = lipgloss.NewStyle().Foreground(ColorWarn)
	FailStyle   = lipgloss.NewStyle().Foreground(ColorFail)
	MutedStyle  = lipgloss.NewStyle().Foreground(ColorMuted)
	AccentStyle = lipgloss.NewStyle().Foreground(ColorAccent)
)

Core styles - consistent across all commands

View Source
var (
	StatusOpenStyle       = lipgloss.NewStyle().Foreground(ColorStatusOpen)
	StatusInProgressStyle = lipgloss.NewStyle().Foreground(ColorStatusInProgress)
	StatusClosedStyle     = lipgloss.NewStyle().Foreground(ColorStatusClosed)
	StatusBlockedStyle    = lipgloss.NewStyle().Foreground(ColorStatusBlocked)
	StatusPinnedStyle     = lipgloss.NewStyle().Foreground(ColorStatusPinned)
	StatusHookedStyle     = lipgloss.NewStyle().Foreground(ColorStatusHooked)
)

Status styles for workflow states

View Source
var (
	PriorityP0Style = lipgloss.NewStyle().Foreground(ColorPriorityP0).Bold(true)
	PriorityP1Style = lipgloss.NewStyle().Foreground(ColorPriorityP1)
	PriorityP2Style = lipgloss.NewStyle().Foreground(ColorPriorityP2)
	PriorityP3Style = lipgloss.NewStyle().Foreground(ColorPriorityP3)
	PriorityP4Style = lipgloss.NewStyle().Foreground(ColorPriorityP4)
)

Priority styles

View Source
var (
	TypeBugStyle     = lipgloss.NewStyle().Foreground(ColorTypeBug)
	TypeFeatureStyle = lipgloss.NewStyle().Foreground(ColorTypeFeature)
	TypeTaskStyle    = lipgloss.NewStyle().Foreground(ColorTypeTask)
	TypeEpicStyle    = lipgloss.NewStyle().Foreground(ColorTypeEpic)
	TypeChoreStyle   = lipgloss.NewStyle().Foreground(ColorTypeChore)
)

Type styles for issue categories

View Source
var (
	TableHeaderStyle = lipgloss.NewStyle().
						Bold(true).
						Foreground(ColorAccent).
						Align(lipgloss.Center)

	TableWarningStyle = lipgloss.NewStyle().
						Foreground(ColorWarn)

	TableSuccessStyle = lipgloss.NewStyle().
						Foreground(ColorPass)

	TableFailStyle = lipgloss.NewStyle().
					Foreground(ColorFail)

	TableHintStyle = lipgloss.NewStyle().
					Foreground(ColorMuted)

	TableBorderStyle = lipgloss.NewStyle().
						Foreground(ColorMuted)
)

Table Styles

View Source
var BoldStyle = lipgloss.NewStyle().Bold(true)

BoldStyle for emphasis

View Source
var CategoryStyle = lipgloss.NewStyle().Bold(true).Foreground(ColorAccent)

CategoryStyle for section headers - bold with accent color

View Source
var CommandStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{
	Light: "#5c6166",
	Dark:  "#bfbdb6",
})

CommandStyle for command names - subtle contrast, not attention-grabbing

View Source
var IDStyle = lipgloss.NewStyle().Foreground(ColorID)

Issue ID style

Functions

func BuildEntityTree

func BuildEntityTree(graph *queries.EntityGraph) *tree.Tree

BuildEntityTree constructs a lipgloss/tree for an EntityGraph

func GetStatusIcon

func GetStatusIcon(status string) string

GetStatusIcon returns just the icon character without styling Useful when you need to apply custom styling or for non-TTY output

func GetStatusStyle

func GetStatusStyle(status string) lipgloss.Style

GetStatusStyle returns the lipgloss style for a given status Use this when you need to apply the semantic color to custom text Example: ui.GetStatusStyle("in_progress").Render(myCustomText)

func GetWidth

func GetWidth() int

GetWidth returns the width of the terminal or a default value.

func IsAgentMode

func IsAgentMode() bool

IsAgentMode returns true if the CLI is running in agent-optimized mode. This is triggered by:

  • BD_AGENT_MODE=1 environment variable (explicit)
  • CLAUDE_CODE environment variable (auto-detect Claude Code)

Agent mode provides ultra-compact output optimized for LLM context windows.

func IsTerminal

func IsTerminal() bool

IsTerminal returns true if stdout is connected to a terminal (TTY).

func NewSearchTable

func NewSearchTable(width int) *table.Table

NewSearchTable creates a new table with default search styling

func Prompt

func Prompt(question, defaultValue string) string

Prompt for simple string input

func PromptYesNo

func PromptYesNo(question string, defaultYes bool) bool

PromptYesNo displays a yes/no question and returns the user's answer. It defaults to the `defaultYes` value if the user just presses Enter or in non-interactive mode.

func RenderAccent

func RenderAccent(s string) string

RenderAccent renders text with accent (blue) styling

func RenderBold

func RenderBold(s string) string

RenderBold renders text in bold

func RenderCategory

func RenderCategory(s string) string

RenderCategory renders a category header in uppercase with accent color

func RenderClosedLine

func RenderClosedLine(line string) string

RenderClosedLine renders an entire line in the closed/dimmed style

func RenderCommand

func RenderCommand(s string) string

RenderCommand renders a command name with subtle styling

func RenderCooccurrenceTable

func RenderCooccurrenceTable(target string, coNodes []queries.CooccurrenceNode, width int) string

RenderCooccurrenceTable renders a list of entities frequently mentioned together

func RenderEntitiesTable

func RenderEntitiesTable(title string, entities [][]string, width int) string

RenderEntitiesTable renders a list of entities and their counts

func RenderEntityTree

func RenderEntityTree(graph *queries.EntityGraph) string

RenderEntityTree renders an EntityGraph using lipgloss/tree

func RenderEvalReport

func RenderEvalReport(runs []EvalRun, width int) string

func RenderFail

func RenderFail(s string) string

RenderFail renders text with fail (red) styling

func RenderFailIcon

func RenderFailIcon() string

RenderFailIcon renders the fail icon with styling

func RenderGraphTable

func RenderGraphTable(query string, matches []struct {
	Name  string
	Graph *queries.EntityGraph
}, width int) string

RenderGraphTable renders multiple trees inside a single structured table

func RenderID

func RenderID(id string) string

RenderID renders an issue ID with semantic styling

func RenderImpactTable

func RenderImpactTable(target string, deps []string, width int) string

RenderImpactTable renders the impact of an entity using a Lipgloss table

func RenderInfoIcon

func RenderInfoIcon() string

RenderInfoIcon renders the info icon with styling

func RenderInitLogo() string

RenderInitLogo returns the stylized ASCII logo for initialization

func RenderInitReport

func RenderInitReport(res InitResult, width int) string

RenderInitReport generates a professional Lipgloss report for the init command

func RenderIssueCompact

func RenderIssueCompact(id string, priority int, issueType, status, title string) string

RenderIssueCompact renders a compact one-line issue summary Format: ID [Priority] [Type] Status - Title When status is "closed", the entire line is dimmed to show it's done

func RenderMarkdown

func RenderMarkdown(markdown string) string

RenderMarkdown renders markdown text using glamour with beads theme colors. Returns the rendered markdown or the original text if rendering fails. Word wraps at terminal width (or 80 columns if width can't be detected).

func RenderMuted

func RenderMuted(s string) string

RenderMuted renders text with muted (gray) styling

func RenderNoResults

func RenderNoResults(query string, suggestions []string, width int) string

RenderNoResults renders the no results view

func RenderPass

func RenderPass(s string) string

RenderPass renders text with pass (green) styling

func RenderPassIcon

func RenderPassIcon() string

RenderPassIcon renders the pass icon with styling

func RenderPath

func RenderPath(path []queries.PathStep, width int) string

RenderPath renders a path between two entities

func RenderPriority

func RenderPriority(priority int) string

RenderPriority renders a priority level with semantic styling Format: ● P0 (icon + label) P0/P1 get color; P2/P3/P4 use standard text

func RenderPriorityCompact

func RenderPriorityCompact(priority int) string

RenderPriorityCompact renders just the priority label without icon Use when space is constrained or icon would be redundant

func RenderPriorityForStatus

func RenderPriorityForStatus(priority int, status string) string

RenderPriorityForStatus renders priority with color only if not closed

func RenderResultsWithContext

func RenderResultsWithContext(query string, results []SearchResultItem, related []string, neighbors []string, width int, strategy string, explain bool) string

RenderResultsWithContext renders the search results with headers and tables

func RenderSeparator

func RenderSeparator() string

RenderSeparator renders the light separator line in muted color

func RenderSkipIcon

func RenderSkipIcon() string

RenderSkipIcon renders the skip icon with styling

func RenderStatus

func RenderStatus(status string) string

RenderStatus renders a status with semantic styling in_progress/blocked/pinned get color; open/closed use standard text

func RenderStatusIcon

func RenderStatusIcon(status string) string

RenderStatusIcon returns the appropriate icon for a status with semantic coloring This is the canonical source for status icon rendering - use this everywhere

func RenderType

func RenderType(issueType string) string

RenderType renders an issue type with semantic styling bugs and epics get color; all other types use standard text Note: Gas Town-specific types (agent, role, rig) now fall through to default

func RenderTypeForStatus

func RenderTypeForStatus(issueType, status string) string

RenderTypeForStatus renders type with color only if not closed

func RenderTypoCorrection

func RenderTypoCorrection(query, corrected string, results []SearchResultItem, width int) string

RenderTypoCorrection renders the typo correction view

func RenderWarn

func RenderWarn(s string) string

RenderWarn renders text with warning (yellow) styling

func RenderWarnIcon

func RenderWarnIcon() string

RenderWarnIcon renders the warning icon with styling

func ShouldUseColor

func ShouldUseColor() bool

ShouldUseColor determines if ANSI color codes should be used. Respects standard conventions:

  • NO_COLOR: https://no-color.org/ - disables color if set
  • CLICOLOR=0: disables color
  • CLICOLOR_FORCE: forces color even in non-TTY
  • Falls back to TTY detection

func ShouldUseEmoji

func ShouldUseEmoji() bool

ShouldUseEmoji determines if emoji decorations should be used. Disabled in non-TTY mode to keep output machine-readable. Can be controlled with BD_NO_EMOJI environment variable.

func ToPager

func ToPager(content string, opts PagerOptions) error

ToPager pipes content to a pager if appropriate. If pager should not be used (not a TTY, --no-pager, etc.), prints directly. If content fits in terminal, prints directly without pager.

Types

type EvalRun

type EvalRun struct {
	ID         string
	Strategy   string
	Tools      string
	TokenCost  string
	TimeSpent  string
	Pass       string
	Score      int
	Efficiency string // 🔴, 🟠, 🟢
}

EvalRun represents a single session's data for the report

type InitResult

type InitResult struct {
	// Database info
	DBPath  string
	Prefix  string
	RepoID  string
	CloneID string

	// Step results
	OrchestrationFiles   []string
	DevlogSpaceStatus    string
	DevlogPromptStatus   string
	AgentRules           []string
	DevlogHooks          []string
	HooksInstalled       bool
	MergeDriverInstalled bool

	// Diagnostics
	DoctorIssues []string

	// Next steps
	QuickstartCommands []string
}

InitResult aggregates all information from the initialization process

type PagerOptions

type PagerOptions struct {
	// NoPager disables pager for this command (--no-pager flag)
	NoPager bool
}

PagerOptions controls pager behavior

type SearchResultItem

type SearchResultItem struct {
	ID        string
	Title     string
	Date      string
	Narrative string
	Reason    string

	// Explanation fields
	Score        float64
	BM25         float64
	PhraseBonus  float64
	NearBonus    float64
	EntityBonus  float64
	RecencyBonus float64

	IsLowConfidence bool

	// Lifecycle fields
	LifecycleStatus string
	StatusReason    string
	IsValidated     bool
	Author          string
	AuthorEmail     string
	Agent           string
	Branch          string
}

SearchResultItem represents a search result for rendering

Jump to

Keyboard shortcuts

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