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 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 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 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 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) (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.
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) 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.ProgressEvent)) (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.