Documentation
¶
Overview ¶
Package tui hosts gskill's interactive surfaces, rendered over the app service layer and refusing to launch without a TTY: the dashboard (a bubbles table stacked over a glamour SKILL.md preview viewport), the guided onboarding wizard (a step state machine whose agents and version steps are huh forms, while the source and skill-picker steps stay custom where the keyboard contract demands it), and the bounded, filterable multi-select skill picker. One Theme feeds every surface — and the CLI's styled output — so the looks cannot drift apart.
Index ¶
- func AccentColor() lipgloss.AdaptiveColor
- func InstallCounterLine(sum app.InstallSummary) string
- func InstallHeadline(sum app.InstallSummary) string
- func OrDash(s string) string
- func PhaseTitle(p app.InstallPhase) string
- func PlannedTitle(action string) string
- func Preview(markdown string, width int) (string, error)
- func Run(rows []SkillRow, isTTY bool) error
- func Sanitize(s string) string
- func SelectSkills(items []SkillItem, isTTY bool) ([]int, error)
- type InstallProgress
- type InstallResults
- func (m InstallResults) Cursor() int
- func (m InstallResults) HasRows() bool
- func (m InstallResults) Hints() string
- func (m InstallResults) SetSize(w, h int) InstallResults
- func (m InstallResults) Summary() app.InstallSummary
- func (m InstallResults) Update(msg tea.KeyMsg) (InstallResults, bool)
- func (m InstallResults) View() string
- type LockWizardConfig
- type LockWizardOutcome
- type LockWizardPhases
- type LockWizardSkill
- type Session
- type SkillItem
- type SkillRow
- type Theme
- type WizardConfig
- type WizardOutcome
- type WizardPhases
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AccentColor ¶ added in v0.3.0
func AccentColor() lipgloss.AdaptiveColor
AccentColor returns the theme's adaptive accent for components that need a color rather than a style.
func InstallCounterLine ¶ added in v0.3.2
func InstallCounterLine(sum app.InstallSummary) string
InstallCounterLine renders the non-zero counters unstyled ("" when all are zero); the glyphs are plain text so the line reads identically without color (FR-027). The plain CLI consumes this directly.
func InstallHeadline ¶ added in v0.3.2
func InstallHeadline(sum app.InstallSummary) string
InstallHeadline maps a run's outcome onto the summary headline. One copy of this user-facing contract text serves the TUI and the plain CLI.
func OrDash ¶ added in v0.3.2
OrDash substitutes — for an empty untrusted value, sanitizing otherwise: the single FR-014 placeholder rule shared by every renderer (TUI and CLI).
func PhaseTitle ¶ added in v0.3.2
func PhaseTitle(p app.InstallPhase) string
PhaseTitle returns the display text for a phase.
func PlannedTitle ¶ added in v0.3.2
PlannedTitle returns the display text for a dry-run planned action; unknown actions render their wire value so a new action is never hidden. Shared by the TUI table and the plain CLI renderer.
func Preview ¶
Preview renders SKILL.md markdown for terminal display, sanitizing untrusted escape sequences before rendering so remote content cannot inject terminal control codes (FR-045).
func Run ¶
Run launches the interactive dashboard. It refuses to start without a TTY, returning a usage error that points at the equivalent CLI commands (FR-041).
func Sanitize ¶
Sanitize strips terminal control sequences and non-printable control characters from untrusted content before it is rendered, defending against terminal-injection via remote SKILL.md content (FR-045). Newlines and tabs are preserved.
func SelectSkills ¶ added in v0.1.0
SelectSkills runs the interactive multi-select picker and returns the indices of the chosen skills. It refuses to start without a TTY. A cancelled picker returns an empty selection and a nil error (the caller treats that as "no skill selected").
Types ¶
type InstallProgress ¶ added in v0.3.2
type InstallProgress struct {
// contains filtered or unexported fields
}
InstallProgress renders a run's live progress. It is a value type in the Bubble Tea style: Observe and SetWidth return the updated copy.
func NewInstallProgress ¶ added in v0.3.2
func NewInstallProgress() InstallProgress
NewInstallProgress builds the component with the shared theme and the same accent-filled bar construction the CLI's fetch renderer uses.
func (InstallProgress) Done ¶ added in v0.3.2
func (m InstallProgress) Done() bool
Done reports whether every skill has a terminal result.
func (InstallProgress) Observe ¶ added in v0.3.2
func (m InstallProgress) Observe(e app.InstallProgressEvent) InstallProgress
Observe folds one lifecycle event into the model. Run-scoped events (SkillName == "") never count toward progress or replace the current skill (contract guarantee 6).
func (InstallProgress) Percent ¶ added in v0.3.2
func (m InstallProgress) Percent() int
Percent is the terminal-driven progress percentage (0 for an empty run).
func (InstallProgress) SetWidth ¶ added in v0.3.2
func (m InstallProgress) SetWidth(w int) InstallProgress
SetWidth adapts the layout (and bar width) to the terminal width.
func (InstallProgress) View ¶ added in v0.3.2
func (m InstallProgress) View() string
View renders the wide or compact layout depending on the last SetWidth.
type InstallResults ¶ added in v0.3.2
type InstallResults struct {
// contains filtered or unexported fields
}
InstallResults renders the result screen. Value semantics, Bubble Tea style: Update and SetSize return the modified copy.
func NewInstallResults ¶ added in v0.3.2
func NewInstallResults(results []app.LockSkillResult) InstallResults
NewInstallResults aggregates the run's results and selects the table rows: unsuccessful entries only (clarification #2), or every entry with its planned action on a dry run (FR-017 exception).
func (InstallResults) Cursor ¶ added in v0.3.2
func (m InstallResults) Cursor() int
Cursor exposes the selected row index for tests and hosts.
func (InstallResults) HasRows ¶ added in v0.3.2
func (m InstallResults) HasRows() bool
HasRows reports whether the table has anything to show.
func (InstallResults) Hints ¶ added in v0.3.2
func (m InstallResults) Hints() string
Hints returns the footer hint line for the current mode.
func (InstallResults) SetSize ¶ added in v0.3.2
func (m InstallResults) SetSize(w, h int) InstallResults
SetSize adapts the table to the terminal. Unchanged dimensions are a no-op so resize-event bursts don't rebuild identical tables.
func (InstallResults) Summary ¶ added in v0.3.2
func (m InstallResults) Summary() app.InstallSummary
Summary exposes the aggregated counters.
func (InstallResults) Update ¶ added in v0.3.2
func (m InstallResults) Update(msg tea.KeyMsg) (InstallResults, bool)
Update handles the result screen's keys (FR-018). exit=true means the host should leave the screen.
func (InstallResults) View ¶ added in v0.3.2
func (m InstallResults) View() string
View renders the summary plus the table or the selected row's detail.
type LockWizardConfig ¶ added in v0.3.0
type LockWizardConfig struct {
LockPath string
Skills []LockWizardSkill
Phases LockWizardPhases
}
LockWizardConfig configures a lock-install wizard run.
type LockWizardOutcome ¶ added in v0.3.0
type LockWizardOutcome struct {
Cancelled bool // user quit before approving: zero writes (CodeCancelled)
NoAgents bool // nothing to select: zero writes (CodeUnsupportedAgent)
Executed bool
AgentIDs []string
Result app.InstallFromLockResult
Err error
}
LockWizardOutcome is what a finished flow reports back to the CLI.
func RunLockWizard ¶ added in v0.3.0
func RunLockWizard(ctx context.Context, cfg LockWizardConfig, isTTY bool) (LockWizardOutcome, error)
RunLockWizard runs the lock-install flow on the terminal. It refuses to start without a TTY (the CLI gates on interactivity before calling this).
type LockWizardPhases ¶ added in v0.3.0
type LockWizardPhases struct {
Agents func(context.Context) ([]app.AgentChoice, error)
Execute func(context.Context, []string, func(app.InstallProgressEvent)) (app.InstallFromLockResult, error)
}
LockWizardPhases are the app-layer use-cases the flow drives, injected by the CLI so the wizard stays view-pure and unit-testable. Execute receives the wizard's progress callback so the run streams install lifecycle events into the live progress view (spec 014 US1).
type LockWizardSkill ¶ added in v0.3.0
type LockWizardSkill struct {
Name string
Source string
// Agents is the entry's currently recorded gskill.agents (nil for a raw,
// unmanaged entry), used to compute the kept/added/removed plan the
// preview screen shows before the user confirms (spec 013 FR-006).
Agents []string
}
LockWizardSkill is one lock entry shown in the flow.
type Session ¶ added in v0.3.0
type Session struct {
Source string
SourceAnswered bool
Selected []discovery.DiscoveredSkill
SkillsAnswered bool
// Requested version pin (one of Version/RefSpec/Commit), plus a display
// label for the preview.
Version string
RefSpec string
Commit string
VersionLabel string
VersionAnswered bool
AgentIDs []string
AgentsAnswered bool
// ApprovalAnswered maps --yes: the approval step auto-approves a
// conflict-free plan (it never bypasses a conflicted one, FR-016).
ApprovalAnswered bool
}
Session is the user's answers accumulated across steps (data-model.md). The *Answered flags mark answers supplied on the command line (FR-004): those steps are skipped, both forward and when navigating back.
type SkillItem ¶ added in v0.1.0
type SkillItem struct {
ID string
DisplayName string
Description string
RepoPath string
Valid bool
// InvalidReason is the first error-severity diagnostic for an invalid
// skill, shown when the cursor is on its row (FR-011).
InvalidReason string
}
SkillItem is one selectable skill in the interactive picker.
type SkillRow ¶
type SkillRow struct {
Name string
Version string
Source string
Status string
Markdown string // SKILL.md content for the preview pane
}
SkillRow is one entry shown in the dashboard.
type Theme ¶ added in v0.3.0
type Theme struct {
Title lipgloss.Style // step/screen headings
Subtitle lipgloss.Style // secondary heading line
Accent lipgloss.Style // source names, counts, selections
Hint lipgloss.Style // keyboard hint footers
Cursor lipgloss.Style // the "❯" row cursor
Selected lipgloss.Style // chosen items / active option
Invalid lipgloss.Style // non-selectable rows
Success lipgloss.Style // confirmation lines
Warning lipgloss.Style // degraded notes, warnings
Error lipgloss.Style // failures, conflicts
Badge lipgloss.Style // step-position badge ("step 2/6")
Border lipgloss.Style // panel borders
TableHeader lipgloss.Style // column header rows
}
Theme is the package-wide visual vocabulary (design 2026-07-08). Every color is a lipgloss.AdaptiveColor so light and dark terminals both read well, and lipgloss's automatic color-profile detection (via termenv) degrades to reduced palettes or plain text on NO_COLOR/dumb terminals — no capability probing of our own. One Theme feeds every surface: the wizard (directly and via Huh()), the dashboard (via TableStyles()), and the CLI's styled output, so the surfaces cannot drift apart.
func DefaultTheme ¶ added in v0.3.0
func DefaultTheme() Theme
DefaultTheme returns the indigo-minimal palette.
func (Theme) HealthCell ¶ added in v0.3.0
HealthCell renders an active-layer or agent-target health state with its semantic glyph and color (internal/active and internal/app/health.go vocabularies). Unknown states render plain so a new state is never hidden or miscolored.
func (Theme) Huh ¶ added in v0.3.0
Huh adapts the theme for huh forms (the agents and version steps), mapping the wizard vocabulary onto huh's FieldStyles.
func (Theme) InstallStatusCell ¶ added in v0.3.2
InstallStatusCell renders an install-result status with its semantic glyph and color (spec 014 status vocabulary, internal/app/installprogress.go). State is never communicated by color alone — the textual status is always part of the cell — and unknown statuses render plain so a new status is never hidden or miscolored.
func (Theme) Panel ¶ added in v0.3.0
Panel returns a thin bordered panel style in the theme's border color.
func (Theme) StatusCell ¶ added in v0.3.0
StatusCell renders a drift status with its semantic glyph and color (internal/integrity/driftstatus.go vocabulary). Unknown statuses render plain so a new status is never hidden or miscolored.
func (Theme) TableStyles ¶ added in v0.3.0
TableStyles adapts the theme for bubbles/table: subtle bold headers over a thin rule and a foreground-accent (not background-highlight) cursor row, per the indigo-minimal design. Cell keeps bubbles' default Padding(0,1) — Header carries the same padding, so replacing Cell with an unpadded style would shift every header right of its column and delete the gutters.
type WizardConfig ¶ added in v0.3.0
type WizardConfig struct {
Session Session
Phases WizardPhases
// SourceSuggestions are configured sources offered as a pick list on the
// source step (US5), above the free-form input.
SourceSuggestions []string
}
WizardConfig configures a wizard run.
type WizardOutcome ¶ added in v0.3.0
WizardOutcome is what a finished wizard reports back to the CLI.
func RunWizard ¶ added in v0.3.0
func RunWizard(ctx context.Context, cfg WizardConfig, isTTY bool) (WizardOutcome, error)
RunWizard runs the guided flow on the terminal. It refuses to start without a TTY (FR-003; the CLI gates on interactivity before calling this).
type WizardPhases ¶ added in v0.3.0
type WizardPhases struct {
Discover func(context.Context) (app.DiscoverResult, error)
Versions func(context.Context) (app.VersionList, error)
Agents func(context.Context) ([]app.AgentChoice, error)
Plan func(context.Context, *Session) (app.InstallPlan, error)
Execute func(context.Context, app.InstallPlan, func(app.InstallProgressEvent)) (app.AddResult, error)
// ValidateSource vets typed source input on the source step (US5).
ValidateSource func(string) error
// ResolveSelection, when set, resolves flag-given skill selectors against
// the discovery result; the selection step is then skipped (FR-004).
ResolveSelection func(context.Context, app.DiscoverResult) ([]discovery.DiscoveredSkill, error)
// SourceChosen, when set, is called with the source accepted on the
// source step, before discovery starts — the CLI's phase closures read
// the chosen source through it (US5).
SourceChosen func(string)
}
WizardPhases are the app-layer use-cases the wizard drives, injected by the CLI so the wizard stays view-pure and unit-testable (contracts/app-phases.md). Versions and Agents are optional; a nil closure skips that step.