Documentation
¶
Overview ¶
Package components contains the bubbletea sub-views that compose the App.
Each file in this package exports one component as a simple struct with a View(...) method. The components are intentionally NOT tea.Model implementations: the App owns the state machine; components are pure presentation layers.
Index ¶
- func ColorForSubagentType(typeName string) color.Color
- func HighlightMentions(s string, style lipgloss.Style) string
- func HighlightPastedInputMarkers(s string, style lipgloss.Style) string
- func HighlightURL(s, hoveredURL string, style lipgloss.Style) string
- func LinkifyURLs(s string) string
- func ModalContentWidth(containerWidth int) int
- func RandomWorkingVerb() string
- func SessionLabel(slug, firstMsgPreview, id string) string
- func ThemeGlamourStyle(t *styles.Styles) glamouransi.StyleConfig
- type APIKeyKey
- type APIKeyModal
- type APIKeyModalMsg
- type Breadcrumb
- type CloseAPIKeyModal
- type CloseMemoryModal
- type CloseMessageActionModal
- type CloseModelModal
- type CloseRememberScopeModal
- type CloseSessionsModal
- type CloseThemeModal
- type CommandPalette
- type CompactionBanner
- type CompactionModal
- type CopyMessageAction
- type DeleteSessionAction
- type DiffView
- type Footer
- type ForgetMemoryAction
- type ForkMessageAction
- type ForkSessionAction
- type Input
- type MemoryKey
- type MemoryModal
- type MemoryModalMsg
- type MentionItem
- type MentionPalette
- type MessageActionKey
- type MessageActionModal
- type MessageActionModalMsg
- type MessageList
- type MessageRole
- type ModelKey
- type ModelModal
- type ModelModalMsg
- type ModelOption
- type NewSessionAction
- type OnboardingClose
- type OnboardingGeneratePrompt
- type OnboardingGeneratedPromptReady
- type OnboardingKey
- type OnboardingMsg
- type OnboardingSaveResult
- type OnboardingSaved
- type OnboardingStep
- type OnboardingSubagentDraft
- type OnboardingWizard
- type PermissionModal
- type PermissionRequest
- type QuestionModal
- type QuestionOption
- type QuestionRequest
- type RememberScopeAction
- type RememberScopeKey
- type RememberScopeModal
- type RememberScopeModalMsg
- type RenameSessionAction
- type SaveAPIKeyAction
- type SelectModelAction
- type SelectThemeAction
- type SessionsKey
- type SessionsModal
- type SessionsModalMsg
- type Sidebar
- type SidebarMCPStatus
- type SidebarTodo
- type SidebarTodoStatus
- type StatusPills
- type SubagentBlock
- type SubagentHitZone
- type SubagentState
- type SwitchSessionAction
- type ThemeKey
- type ThemeModal
- type ThemeModalMsg
- type ThinkingHitZone
- type ToggleFavoriteModelAction
- type ToolHitZone
- type ToolStatus
- type UIMessage
- type URLHitZone
- type URLPosition
- type UserMsgHitZone
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ColorForSubagentType ¶
ColorForSubagentType returns a deterministic color derived from a subagent type name. Uses a curated palette of distinct ANSI-256 colors that are visible on both dark and light backgrounds.
func HighlightMentions ¶
HighlightMentions applies style to @ mention tokens in already-rendered text.
func HighlightPastedInputMarkers ¶
HighlightPastedInputMarkers applies style to collapsed multi-line paste markers.
func HighlightURL ¶ added in v0.12.1
HighlightURL styles the visible text for the given URL in s. It is intended for hover feedback after hit testing has identified the URL under the mouse.
func LinkifyURLs ¶ added in v0.12.1
LinkifyURLs wraps every plain http(s):// URL found in s with an OSC 8 terminal hyperlink sequence so that supporting terminals render the URL as a clickable link while keeping the visible text unchanged.
The function operates on the raw string including any ANSI CSI styling already applied; it will not match URLs that appear inside an ANSI escape sequence because those sequences contain \x1b which cannot be part of a valid URL match.
func ModalContentWidth ¶ added in v0.11.0
ModalContentWidth returns the inner content width for modal boxes, clamped to a readable range shared by modal components.
func RandomWorkingVerb ¶
func RandomWorkingVerb() string
RandomWorkingVerb selects one busy footer label. Callers should store the returned value and rotate it deliberately so spinner ticks do not change the label every frame.
func SessionLabel ¶
SessionLabel returns the display label for a session, preferring slug over first-message preview over short id. Used by the App to build Breadcrumb segments.
func ThemeGlamourStyle ¶ added in v0.10.0
func ThemeGlamourStyle(t *styles.Styles) glamouransi.StyleConfig
ThemeGlamourStyle builds a glamour ansi.StyleConfig from the active Hygge theme. It starts from the standard dark config (deterministic, no OSC 11 query) and overrides only the key color fields that map cleanly to theme atoms:
- Heading color ← AtomPrimary
- H1 background ← AtomAccent
- Link color ← AtomAccent
- LinkText color ← AtomPrimary
- Inline code fg ← AtomCodeFg
- Inline code bg ← AtomCodeBg
When t is nil the unmodified DarkStyleConfig is returned.
Types ¶
type APIKeyModal ¶
type APIKeyModal struct {
Width, Height int
Theme *styles.Styles
Provider string
HasExisting bool
Value string
}
APIKeyModal renders and updates the provider API-key dialog.
func (APIKeyModal) HandleKey ¶
func (m APIKeyModal) HandleKey(k APIKeyKey) (APIKeyModal, APIKeyModalMsg)
HandleKey updates dialog state for one key and may emit an action message.
func (APIKeyModal) View ¶
func (m APIKeyModal) View() string
View renders the dialog into a centered terminal string.
type APIKeyModalMsg ¶
type APIKeyModalMsg interface {
// contains filtered or unexported methods
}
APIKeyModalMsg is emitted when the dialog wants the App to perform an action.
type Breadcrumb ¶
type Breadcrumb struct {
// Segments is the ordered list of navigation labels, root first.
Segments []string
// Width is the maximum column width of the rendered line. 0 means 80.
Width int
// Theme is the active theme; nil is accepted (plain style used).
Theme *styles.Styles
}
Breadcrumb renders a navigation path of the form "root › child › grandchild".
It is shown above the message list whenever the foreground-stack depth is greater than 1 (i.e. the user has followed into a sub-session via Ctrl+G). When depth is 1 (root only), the breadcrumb is empty — View returns "".
Width is the maximum character width of the rendered line. If the natural rendering would exceed Width, middle segments are elided:
"root › … › 2 more › leaf"
Segments are user-visible labels for each stack entry:
- The session's slug if non-empty.
- Otherwise the first 24 characters of the first user message preview.
- Otherwise "sess_" + the first 8 characters of the session id.
func (Breadcrumb) View ¶
func (b Breadcrumb) View() string
View renders the breadcrumb, or "" when there is nothing to show. A single-segment stack (just the root) returns "". Downstream callers do NOT need to special-case the empty string — a zero-height string does not occupy layout space.
type CloseAPIKeyModal ¶
type CloseAPIKeyModal struct{}
CloseAPIKeyModal requests closing the API-key dialog without saving.
type CloseMemoryModal ¶ added in v0.5.0
type CloseMemoryModal struct{}
CloseMemoryModal requests closing the memory dialog.
type CloseMessageActionModal ¶ added in v0.13.1
type CloseMessageActionModal struct{}
CloseMessageActionModal is emitted when the user dismisses the modal.
type CloseModelModal ¶
type CloseModelModal struct{}
CloseModelModal requests closing the model dialog without changing model.
type CloseRememberScopeModal ¶ added in v0.5.0
type CloseRememberScopeModal struct{}
CloseRememberScopeModal requests closing the remember scope picker.
type CloseSessionsModal ¶
type CloseSessionsModal struct{}
CloseSessionsModal asks the App to close the modal.
type CloseThemeModal ¶
type CloseThemeModal struct{}
CloseThemeModal requests closing the theme dialog without changing theme.
type CommandPalette ¶
type CommandPalette struct {
// Width is the rendered width in cells (matches the input width).
Width int
// Theme is the active theme. Nil falls back to default lipgloss
// styles — the palette stays usable but loses muted/accent
// distinction.
Theme *styles.Styles
// Matches is the prefix-filtered command list, sorted by Name.
Matches []command.Command
// Highlight is the index into Matches that is currently selected.
// Clamped into [0, len(Matches)) at render time so the App does
// not need to. An out-of-range value (e.g. -1) renders as "no
// row highlighted" — useful when the buffer has not yet picked a
// row.
Highlight int
// QueryAfterSlash is the user's typed buffer minus the leading
// slash. Used only for the optional hint row at the bottom; the
// actual filtering happens upstream.
QueryAfterSlash string
}
CommandPalette is the inline autocomplete popover shown above the input whenever the user's buffer starts with `/`. It is a pure view-model: the App owns lookup state (matches, highlight index) and feeds it in; the palette has no event-handling logic of its own.
Filtering is done by the App via command.Registry.LookupPrefix so this component is also reusable for non-slash menus in the future.
Anchor: the App draws the palette as a floating layer above the editor. The palette draws its own rounded border so it visually floats above the input border.
func (CommandPalette) Empty ¶
func (p CommandPalette) Empty() bool
Empty reports whether the palette has no matches to render. The App uses this to skip the popover entirely (no border, no blank padding) when the user has typed `/` plus characters that don't match anything.
func (CommandPalette) View ¶
func (p CommandPalette) View() string
View renders the palette. Returns an empty string when there are no matches AND no query: this lets the App unconditionally concatenate the palette into the layout without worrying about reserving vertical space.
When there are no matches BUT the user has typed a query (e.g. `/foo`) we render a single "no commands match" row so the user has feedback rather than a silently disappearing popover.
type CompactionBanner ¶
type CompactionBanner struct {
Width int
Theme *styles.Styles
Visible bool
Pct float64 // context usage percentage (0–100)
}
CompactionBanner is the thin advisory banner shown above the input when context usage crosses the configured threshold. It is non-blocking: the user can dismiss it with Ctrl+X without triggering compaction.
Dismiss semantics (managed by the App, not here):
Ctrl+X — dismiss for this crossing (hidden until re-crossing
after hysteresis or compaction).
CompactionCompleted event — auto-cleared by the App.
func (CompactionBanner) View ¶
func (b CompactionBanner) View() string
View renders the banner as a single line, or "" when not visible.
type CompactionModal ¶
type CompactionModal struct {
Width int
Height int
Theme *styles.Styles
Toast string // optional transient line (e.g. warning text)
// SessionID is the foreground session being compacted.
SessionID string
// MessageCount is the number of messages since the last compaction marker.
// When < 4 the modal disables the [y] key and shows a "nothing to compact"
// notice.
MessageCount int
// ContextPct is the current context-window usage as a percentage (0–100).
ContextPct float64
// ContextWindow is the model's maximum context size in tokens. Shown in
// the modal body.
ContextWindow int64
}
CompactionModal renders the confirmation dialog shown when the user runs /compact. It displays the message count, context usage, and a brief explanation before asking the user to confirm or cancel.
Keybinds (handled by the App, not here):
y / Y — confirm compaction n / N — cancel esc — cancel
func (CompactionModal) NothingToCompact ¶
func (m CompactionModal) NothingToCompact() bool
NothingToCompact reports whether there are fewer than 4 messages since the last marker. When true the [y] key is disabled.
func (CompactionModal) View ¶
func (m CompactionModal) View() string
View renders the modal centred in a Width×Height box.
type CopyMessageAction ¶ added in v0.13.1
type CopyMessageAction struct {
Text string // raw message text to copy
}
CopyMessageAction is emitted when the user selects "Copy message".
type DeleteSessionAction ¶
type DeleteSessionAction struct{ ID string }
DeleteSessionAction asks the App to soft-delete a session.
type DiffView ¶
DiffView renders unified-diff-like text with line-level add/delete styling.
func (DiffView) IsTruncated ¶ added in v0.6.0
IsTruncated reports whether the diff exceeds its configured preview line limit. For wide views (side-by-side), pair-preservation may extend the rendered range to the end of the diff, in which case truncation is false even if the raw line count exceeds MaxLines.
type Footer ¶
type Footer struct {
// with the active mode highlighted. Empty when only one mode exists.
ModeIndicator string
Busy bool
SpinnerView string
// between periodic rotations rather than changing on every spinner frame.
WorkingVerb string
}
Footer renders the bottom-of-screen identity line.
Layout (segments separated by ` · `):
{AgentType Capitalized} · {ModelName} · {Provider Capitalized} · {ReasoningLevel}
type ForgetMemoryAction ¶ added in v0.5.0
type ForgetMemoryAction struct {
Scope session.MemoryScope
ID string
}
ForgetMemoryAction requests deleting a memory by scope and id.
type ForkMessageAction ¶ added in v0.13.1
type ForkMessageAction struct {
SessionID string // session to fork from
MessageID string // message ID to fork at
}
ForkMessageAction is emitted when the user selects "Fork from here".
type ForkSessionAction ¶
ForkSessionAction asks the App to fork a session. MessageID == "" means fork at the latest user message.
type Input ¶
type Input struct {
Textarea textarea.Model
Styles *styles.Styles
PasteMarkerStyle lipgloss.Style
BorderColor color.Color
VerticalPadding int
Focused bool
// contains filtered or unexported fields
}
Input wraps a bubbles textarea with dynamic height, custom prompts, and theme-aware styling.
Keybind contract:
- Enter submits (handled by the App, not the textarea).
- Shift+Enter and Alt+Enter insert a newline.
- Ctrl+C, Ctrl+L handled by the App.
func (*Input) HeightChanged ¶
HeightChanged reports whether the textarea height changed since the last check. Call this after Update to know if layout needs recalculation.
type MemoryKey ¶ added in v0.5.0
MemoryKey is the dialog-local key event shape used by tests and the UI app.
type MemoryModal ¶ added in v0.5.0
type MemoryModal struct {
Width, Height int
Theme *styles.Styles
Memories []*session.Memory
Query string
Cursor int
ForgetOnly bool
}
MemoryModal renders active memories grouped by scope.
func (MemoryModal) Filtered ¶ added in v0.5.0
func (m MemoryModal) Filtered() []*session.Memory
Filtered returns active memories after applying the current search query.
func (MemoryModal) HandleKey ¶ added in v0.5.0
func (m MemoryModal) HandleKey(k MemoryKey) (MemoryModal, MemoryModalMsg)
HandleKey updates dialog state for one key and may emit an action message.
func (MemoryModal) View ¶ added in v0.5.0
func (m MemoryModal) View() string
View renders the dialog into a centered terminal string.
type MemoryModalMsg ¶ added in v0.5.0
type MemoryModalMsg interface {
// contains filtered or unexported methods
}
MemoryModalMsg is emitted when the memory dialog wants the App to act.
type MentionItem ¶
MentionItem is one selectable @ mention candidate.
type MentionPalette ¶
type MentionPalette struct {
Width int
Theme *styles.Styles
Matches []MentionItem
Highlight int
Query string
}
MentionPalette is the inline autocomplete popover shown above the input while the user is typing an @ mention.
func (MentionPalette) View ¶
func (p MentionPalette) View() string
View renders the mention autocomplete popover.
type MessageActionKey ¶ added in v0.13.1
MessageActionKey is a key event routed to MessageActionModal.HandleKey.
type MessageActionModal ¶ added in v0.13.1
type MessageActionModal struct {
Width int
Height int
Theme *styles.Styles
SessionID string // current foreground session id
MessageID string // message id clicked
MessageText string // raw text of the clicked message
Cursor int // selected row (0=copy, 1=fork)
}
MessageActionModal is a lightweight two-action modal shown when the user clicks on a user message bubble. It offers copy and fork actions.
Following the components convention the modal is a pure value type: HandleKey returns an updated copy plus an optional action message. The App owns the mutable state.
func (MessageActionModal) HandleKey ¶ added in v0.13.1
func (m MessageActionModal) HandleKey(k MessageActionKey) (MessageActionModal, MessageActionModalMsg)
HandleKey processes a key press and returns the updated modal plus an optional action. Returns nil msg when no action was triggered.
func (MessageActionModal) View ¶ added in v0.13.1
func (m MessageActionModal) View() string
View renders the modal centered in Width×Height.
type MessageActionModalMsg ¶ added in v0.13.1
type MessageActionModalMsg interface {
// contains filtered or unexported methods
}
MessageActionModalMsg is the sealed interface for messages emitted by MessageActionModal.HandleKey.
type MessageList ¶
type MessageList struct {
Width int
CollapseLines int // 0 → 8 (tool result collapse threshold)
Theme *styles.Styles
Styles *styles.Styles
Messages []UIMessage
Subagents map[string]*SubagentState
// AnimFor, when non-nil, maps SubSessionID to the running Anim for
// that sub-agent. Passed through to SubagentBlock so the running
// state can display the animated spinner.
AnimFor map[string]*anim.Anim
// Now is the wall-clock to use for elapsed-time math inside
// nested SubagentBlocks. Zero means time.Now (production
// path); tests override it for deterministic output.
Now time.Time
// HoverSubagentID is the subagent currently under the mouse cursor.
// When set, that subagent's bubble renders with highlight styling.
HoverSubagentID string
// HoverURL is the URL currently under the mouse cursor. When set, matching
// visible URL text in user/assistant bubbles renders with hover styling.
HoverURL string
// HoverUserMsgID is the user message currently under the mouse cursor.
// When set, that user bubble renders with clickable hover styling.
HoverUserMsgID string
// ExpandedTools is the set of ToolUseIDs whose output is fully expanded
// (not truncated). Nil means all tools are collapsed.
ExpandedTools map[string]bool
// ExpandedThinking is the set of message indices whose thinking block is
// fully expanded (not truncated). Nil means all thinking is collapsed.
ExpandedThinking map[int]bool
// MessageIndexOffset is added to rendered message indices before looking up
// ExpandedThinking. It keeps expansion state stable when scrollback is capped
// and a synthetic notice is prepended to the rendered slice.
MessageIndexOffset int
// Compact enables compact layout mode: tighter message spacing, no separate
// assistant header row with model metadata (mode name goes inside the bubble),
// tool output hidden until explicitly expanded, subagent blocks two lines.
Compact bool
// contains filtered or unexported fields
}
MessageList renders the conversation history.
Width is the terminal width; the gutter (`▌user`, etc.) is prepended to the first line of each message. Tool result blocks are collapsed to the first CollapseLines lines, with a hint when the rest is hidden.
Subagents, when populated, is a map from sub-session id to the rendering state of an in-flight or completed sub-agent. Messages whose SubagentID is a key in this map get a nested SubagentBlock rendered under them.
func (MessageList) View ¶
func (m MessageList) View() string
View renders all messages joined with a blank line between them. The pre-pass groups consecutive compact RoleTool entries into a single tool-calls bubble. Bash, edit, and write tools render as standalone tool blocks so expandable output and large file diffs have their own hit zone.
func (MessageList) ViewWithHitZones ¶
func (m MessageList) ViewWithHitZones() (string, []SubagentHitZone, []ToolHitZone, []ThinkingHitZone, []URLHitZone, []UserMsgHitZone)
ViewWithHitZones renders all messages and returns both the rendered content and the line ranges of clickable subagent bubbles.
type MessageRole ¶
type MessageRole string
MessageRole is the participant role for a rendered message.
const ( RoleUser MessageRole = "user" RoleAssistant MessageRole = "assistant" RoleTool MessageRole = "tool" RoleSystem MessageRole = "system" // RoleMarker renders a prominent banner-style section break produced // by a compaction event. It shows the summary and tokens-saved count. RoleMarker MessageRole = "marker" )
Recognised roles for rendering purposes. Mirrors session.Role but kept separate so the components package does not import session.
type ModelModal ¶
type ModelModal struct {
Width, Height int
Theme *styles.Styles
Current string
Query string
Cursor int
Models []ModelOption
// Favorites is the ordered list of "provider/model" refs the user has
// starred. Loaded from global state when the modal opens; toggled via
// ctrl+f. Favorites are shown first under a "Favorites" heading.
Favorites []string
}
ModelModal renders and updates the model-selection dialog.
func (ModelModal) Filtered ¶
func (m ModelModal) Filtered() []ModelOption
Filtered returns the model list after applying the current search query. Favorite models appear first (sorted within their group), followed by the remaining models sorted by provider then model id.
func (ModelModal) HandleKey ¶
func (m ModelModal) HandleKey(k ModelKey) (ModelModal, ModelModalMsg)
HandleKey updates dialog state for one key and may emit an action message.
func (ModelModal) View ¶
func (m ModelModal) View() string
View renders the dialog into a centered terminal string.
type ModelModalMsg ¶
type ModelModalMsg interface {
// contains filtered or unexported methods
}
ModelModalMsg is emitted when the dialog wants the App to perform an action.
type ModelOption ¶
ModelOption is one selectable catalog model in the model picker.
func ConfiguredModelOption ¶ added in v0.6.0
func ConfiguredModelOption(provider, model string) ModelOption
ConfiguredModelOption builds a selectable entry for a configured model that is missing from the catalog snapshot.
type NewSessionAction ¶
type NewSessionAction struct{}
NewSessionAction asks the App to start a fresh session. Emitted when the user presses 'n' in the empty-list picker.
type OnboardingClose ¶ added in v0.7.0
type OnboardingClose struct{}
OnboardingClose is emitted when the user presses Esc on the welcome step.
type OnboardingGeneratePrompt ¶ added in v0.7.0
type OnboardingGeneratePrompt struct {
ProviderName string
ModelName string
APIKey string
Idea string
ForSubagent bool
}
OnboardingGeneratePrompt asks the App to call GeneratePrompt asynchronously (provider/model are ready in wizard state).
type OnboardingGeneratedPromptReady ¶ added in v0.7.0
OnboardingGeneratedPromptReady is sent back to the wizard by the App after generation completes. Err is non-nil on failure.
type OnboardingKey ¶ added in v0.7.0
OnboardingKey is the wizard-local key event.
type OnboardingMsg ¶ added in v0.7.0
type OnboardingMsg interface {
// contains filtered or unexported methods
}
OnboardingMsg is emitted when the wizard needs the App to act.
type OnboardingSaveResult ¶ added in v0.7.0
type OnboardingSaveResult struct {
ProviderName string
ProviderAPIKey string
Mode config.ModeConfig
Subagents []OnboardingSubagentDraft
}
OnboardingSaveResult asks the App to persist the final wizard output.
type OnboardingSaved ¶ added in v0.7.0
type OnboardingSaved struct{ Err error }
OnboardingSaved is sent back to the wizard when the App has finished persisting the result (Err non-nil on failure).
type OnboardingStep ¶ added in v0.7.0
type OnboardingStep int
OnboardingStep enumerates the wizard steps.
const ( OnboardStepWelcome OnboardingStep = iota OnboardStepAPIKey OnboardStepProviderMore OnboardStepPickModel OnboardStepModeName OnboardStepModeIdea OnboardStepPromptReview OnboardStepSubagentOffer OnboardStepSubagentName OnboardStepSubagentIdea OnboardStepSubagentPromptReview OnboardStepDone )
Wizard step constants.
type OnboardingSubagentDraft ¶ added in v0.7.0
OnboardingSubagentDraft holds wizard state for a single subagent being built.
type OnboardingWizard ¶ added in v0.7.0
type OnboardingWizard struct {
Width, Height int
Theme *styles.Styles
Providers []string // known provider names
Step OnboardingStep
// step 0/1: provider + API key
ProviderCursor int
ProviderName string
APIKey string
ProviderKeys map[string]string
ConfiguredProviders map[string]bool
// step 2: model pick
Models []string // filled after provider is confirmed
ModelCursor int
ModelQuery string
ModelName string
ModelNameRaw string // typed entry
// step 3: mode name
ModeName string
// step 4: mode behavior idea
ModeIdea string
// step 5: generated prompt for mode
ModePrompt string
PromptLoading bool
PromptLoadErr string
PromptEditing bool
PromptEditBuf string
// subagent wizard
SubagentDrafts []OnboardingSubagentDraft
CurrentSubagent OnboardingSubagentDraft
SubagentLoading bool
SubagentLoadErr string
SubagentEditing bool
SubagentEditBuf string
// saving tracks whether the final save is in progress
Saving bool
SaveError string
// contains filtered or unexported fields
}
OnboardingWizard is the onboarding wizard component. It is a pure state machine: HandleKey advances state and emits messages; View renders the current step.
func (OnboardingWizard) ApplyGeneratedPrompt ¶ added in v0.7.0
func (w OnboardingWizard) ApplyGeneratedPrompt(msg OnboardingGeneratedPromptReady) OnboardingWizard
ApplyGeneratedPrompt feeds a completed prompt-generation result back.
func (OnboardingWizard) HandleKey ¶ added in v0.7.0
func (w OnboardingWizard) HandleKey(k OnboardingKey) (OnboardingWizard, OnboardingMsg)
HandleKey advances wizard state, returns updated wizard and optional message.
func (OnboardingWizard) View ¶ added in v0.7.0
func (w OnboardingWizard) View() string
View renders the wizard overlay.
type PermissionModal ¶
type PermissionModal struct {
Width int
Height int
Theme *styles.Styles
Request PermissionRequest
}
PermissionModal renders the centered modal that gates tool execution.
func (PermissionModal) View ¶
func (m PermissionModal) View() string
View renders the modal centered in a Width×Height box. Caller is responsible for not calling View when no request is active.
type PermissionRequest ¶
type PermissionRequest struct {
RequestID string
ToolName string
Category string
Target string
Why string // optional rationale
}
PermissionRequest is the data the modal needs to render. Mirrors bus.PermissionAsked so components does not import bus.
type QuestionModal ¶ added in v0.4.0
type QuestionModal struct {
Width int
Height int
Theme *styles.Styles
Request QuestionRequest
SelectedIndex int
}
QuestionModal renders a centered multiple-choice prompt for model questions.
func (QuestionModal) View ¶ added in v0.4.0
func (m QuestionModal) View() string
View renders the modal centered in a Width×Height box.
type QuestionOption ¶ added in v0.4.0
QuestionOption is one selectable answer in a question modal.
type QuestionRequest ¶ added in v0.4.0
type QuestionRequest struct {
RequestID string
ToolName string
Question string
Options []QuestionOption
}
QuestionRequest is the data the modal needs to render. Mirrors bus.QuestionAsked so components does not import bus.
type RememberScopeAction ¶ added in v0.5.0
type RememberScopeAction struct {
Scope session.MemoryScope
Content string
}
RememberScopeAction requests saving the draft content at a chosen scope.
type RememberScopeKey ¶ added in v0.5.0
type RememberScopeKey struct {
Name string
}
RememberScopeKey is the dialog-local key event shape used by tests and the UI app.
type RememberScopeModal ¶ added in v0.5.0
RememberScopeModal lets the user choose where a no-scope /remember should save.
func (RememberScopeModal) HandleKey ¶ added in v0.5.0
func (m RememberScopeModal) HandleKey(k RememberScopeKey) (RememberScopeModal, RememberScopeModalMsg)
HandleKey updates dialog state for one key and may emit an action message.
func (RememberScopeModal) View ¶ added in v0.5.0
func (m RememberScopeModal) View() string
View renders the dialog into a centered terminal string.
type RememberScopeModalMsg ¶ added in v0.5.0
type RememberScopeModalMsg interface {
// contains filtered or unexported methods
}
RememberScopeModalMsg is emitted when the scope picker wants the App to act.
type RenameSessionAction ¶
RenameSessionAction asks the App to rename a session.
type SaveAPIKeyAction ¶
type SaveAPIKeyAction struct{ Provider, APIKey string }
SaveAPIKeyAction requests saving APIKey for Provider.
type SelectModelAction ¶
type SelectModelAction struct{ Provider, Model string }
SelectModelAction requests switching to Provider/Model for the current session.
type SelectThemeAction ¶
type SelectThemeAction struct{ Name string }
SelectThemeAction requests switching to Name for the current session.
type SessionsKey ¶
SessionsKey is the subset of keys the modal handles.
type SessionsModal ¶
type SessionsModal struct {
// Sessions is the full unfiltered session list (newest first).
// The modal renders only the rows that survive the filter.
Sessions []*session.Session
// ForegroundID is the currently active session's id. That row is
// highlighted differently.
ForegroundID string
// Cursor is the currently highlighted row index into the filtered list.
Cursor int
// FilterValue is the active substring filter.
FilterValue string
// FilterFocused is true when keyboard input goes to the filter field.
FilterFocused bool
// ShowSubagents controls whether subagent rows are visible.
ShowSubagents bool
// ShowDeleted controls whether soft-deleted rows are visible.
ShowDeleted bool
// RenameMode is true when the inline rename field is open.
RenameMode bool
// RenameValue is the current value in the rename input.
RenameValue string
// ConfirmDelete is true when the delete-confirmation prompt is open.
ConfirmDelete bool
// ShowHelp toggles the inline keybind cheatsheet.
ShowHelp bool
// Toast is an ephemeral single-line message (error / info).
Toast string
// Width is the available terminal width.
Width int
// Height is the available terminal height.
Height int
// Theme is the active theme.
Theme *styles.Styles
// Now is the wall-clock used for "N ago" labels.
Now time.Time
// AllowNew, when true, shows a "No sessions yet. [n] new session [esc] cancel"
// affordance when the filtered list is empty. Used when the picker is
// opened on start (resume_default="ask", or `hygge resume` in an empty project).
AllowNew bool
}
SessionsModal is the bubbletea-style component for the session management overlay. It is a pure-view struct: the App owns the state (sessions list, cursor, filter) and calls Update then View on each tick.
The modal supports keyboard navigation, substring filtering, and the following actions: switch, rename, fork at latest, delete.
All user-input / action messages emitted by the modal are returned as tea.Msg values; the App applies the side effects.
func (SessionsModal) FilteredCount ¶
func (m SessionsModal) FilteredCount() int
FilteredCount returns the number of sessions that would survive the current filter/visibility settings. Used by the App to clamp the cursor after a delete.
func (SessionsModal) HandleKey ¶
func (m SessionsModal) HandleKey(k SessionsKey) (SessionsModal, SessionsModalMsg)
HandleKey processes one key press in the modal. Returns (newState, emittedMsg). emittedMsg is nil when no action was triggered.
func (SessionsModal) HumanAgo ¶
HumanAgo renders the elapsed time since t as a compact human string. Exposed as a method for testability.
func (SessionsModal) View ¶
func (m SessionsModal) View() string
View renders the modal centered in Width×Height.
type SessionsModalMsg ¶
type SessionsModalMsg interface {
// contains filtered or unexported methods
}
SessionsModalMsg is the tagged union of messages the modal emits.
type Sidebar ¶
type Sidebar struct {
// Width is the total column width including the left border.
Width int
// Height is the total height of the sidebar column.
Height int
// SessionTitle is the display title for the current session.
// Empty means no active session — the section is omitted entirely.
SessionTitle string
// Usage and context data.
UsedTokens int64
MaxTokens int64
PctUsed float64
CostUSD float64
BilledInputTokens int64 // cumulative input+cache tokens billed
BilledOutputTokens int64 // cumulative output tokens billed
// MCPs is the list of configured MCP server statuses.
MCPs []SidebarMCPStatus
// Todos is the agent's lightweight todo list for the current session.
// Nil or empty renders "—" (the fallback stub).
Todos []SidebarTodo
// ProjectPath is the tilde-collapsed project directory path.
ProjectPath string
// GitBranch is the current git branch (may be empty).
GitBranch string
// AppName is the application name, e.g. "Hygge".
AppName string
// Version is the application version string, e.g. "v0.1.0-dev".
Version string
// Theme is the active theme. Nil is accepted (plain styles used).
Theme *styles.Styles
Styles *styles.Styles
// NerdFonts controls whether to use the nerd-font git-branch glyph.
NerdFonts bool
}
Sidebar renders the fixed-width right-side panel containing session context, MCPs, todos, and footer identity.
Layout (top to bottom):
Session title (1–2 lines, bold)
Context (section header)
{usedTok} tokens
{pctUsed}% used
${costDollars}
MCPs (section header)
● server-a · N tools
○ server-b
Todos (section header)
✓ completed item
→ in-progress item
○ pending item
(flex space)
~/path…:branch
● Hygge v0.1.0-dev
The left edge carries a single │ border in the sidebar border color. Inner padding: 1 cell on each side so content doesn't touch the divider.
type SidebarMCPStatus ¶
SidebarMCPStatus is the UI-side representation of one MCP server's runtime status. Populated at the wiring layer (runTUI) from the CLI's MCPServerStatus type so the sidebar has no import dependency on cmd/.
type SidebarTodo ¶
type SidebarTodo struct {
// Title is the human-readable todo text.
Title string
// Status drives the leading glyph and color.
Status SidebarTodoStatus
}
SidebarTodo is one row in the sidebar Todos section.
type SidebarTodoStatus ¶
type SidebarTodoStatus string
SidebarTodoStatus is the rendering status for a single sidebar todo row. Mirrors session.TodoStatus values; defined here so the components package has no import dependency on internal/session.
const ( // SidebarTodoPending is a queued, not-yet-started item. SidebarTodoPending SidebarTodoStatus = "pending" // SidebarTodoInProgress is the currently-active item. SidebarTodoInProgress SidebarTodoStatus = "in_progress" // SidebarTodoCompleted is a finished item. SidebarTodoCompleted SidebarTodoStatus = "completed" // SidebarTodoCancelled is an abandoned item. SidebarTodoCancelled SidebarTodoStatus = "cancelled" )
Sidebar todo status constants.
type StatusPills ¶
type StatusPills struct {
Width int
Theme *styles.Styles
QueueCount int
QueuedPrompts []string
QueuedEditable bool
}
StatusPills renders compact input-adjacent status chips.
func (StatusPills) View ¶
func (p StatusPills) View() string
View renders a single row of pills. Empty state renders nothing so the input keeps its current layout when no status exists.
type SubagentBlock ¶
type SubagentBlock struct {
State *SubagentState
Width int
Theme *styles.Styles
Now time.Time
Anim *anim.Anim
Hovered bool
// Compact, when true, renders the block as only two lines (heading +
// subtitle) without the blank spacer line or ctrl+g hint.
Compact bool
}
SubagentBlock renders a single nested sub-agent state in the compact heading + subtitle + hint layout.
Layout (rendered inside a distinct bubble by wrapSubagentBubble):
{Type} Subagent — {Description}
{subtitle}
ctrl+g view subagent
Width is the available column count for the parent message list; Theme is the active theme; Now is the wall-clock used for elapsed-time math while the state is still running. Anim is the optional animation component for the running state (nil renders a static placeholder).
func (SubagentBlock) View ¶
func (b SubagentBlock) View() string
View renders the compact block. Returns the empty string when State is nil. The output has no leading │ gutter — the surrounding bubble border provides the visual containment.
type SubagentHitZone ¶
type SubagentHitZone struct {
StartLine int // inclusive, relative to message list content
EndLine int // exclusive
SubSessionID string
// contains filtered or unexported fields
}
SubagentHitZone maps a range of content lines to a subagent session ID.
type SubagentState ¶
type SubagentState struct {
// SubSessionID is the sub-session's id; the map key in App.
SubSessionID string
// ParentSessionID is the dispatching session. Used to filter
// events when the foreground session changes (a sub-agent of
// session A should not render in session B's view).
ParentSessionID string
// ParentMessageID is the parent's task tool_use_id. The
// message-list uses this to find the UIMessage to anchor the
// nested block under. Empty when the dispatcher did not
// supply one.
ParentMessageID string
// Type is the sub-agent type name (e.g. "general").
Type string
// Description is the short mission label shown in the heading.
Description string
// Model is the resolved provider/model string shown in the compact block
// and detail view accessed via Ctrl+G.
Model string
// StartedAt and EndedAt bound the wall-clock elapsed time.
// EndedAt is the zero value while the sub-agent is still running.
StartedAt time.Time
EndedAt time.Time
// Cost / InputTokens / OutputTokens are running totals tagged
// to the sub-session. Stage C derives these from
// bus.CostUpdated events that arrive with the sub-session id;
// the Completed event's totals override them at the end.
Cost float64
InputTokens int64
OutputTokens int64
// Messages is the streaming buffer of nested sub-messages,
// in chronological order. Used to derive the tool-count
// subtitle and the latest-tool hint in the running state.
Messages []UIMessage
// Expanded is retained for Ctrl+T toggle compatibility.
// In the compact layout it controls whether the transcript view
// is shown when the user follows into the subagent via Ctrl+G.
Expanded bool
}
SubagentState is the rendering view of one in-flight or completed sub-agent invocation. The App owns the source of truth; this struct is a snapshot the message-list renders.
Lifecycle:
- Created when bus.SubagentStarted arrives. StartedAt set, EndedAt zero, Messages empty.
- Updated as the sub-session's events flow through (text deltas, tool calls, cost updates). Caller appends to Messages and overwrites Cost / InputTokens / OutputTokens.
- Finalised when bus.SubagentCompleted arrives. EndedAt is set.
func (*SubagentState) IsRunning ¶
func (s *SubagentState) IsRunning() bool
IsRunning is true while no Completed event has arrived yet. Used by the App to drive the elapsed-time tick.
type SwitchSessionAction ¶
type SwitchSessionAction struct{ ID string }
SwitchSessionAction asks the App to switch the foreground session.
type ThemeModal ¶
type ThemeModal struct {
Width, Height int
Theme *styles.Styles
Current string
Query string
Cursor int
Themes []string
PreviewTheme func(string) *styles.Styles
}
ThemeModal renders and updates the theme-selection dialog.
func (ThemeModal) Filtered ¶
func (m ThemeModal) Filtered() []string
Filtered returns the theme list after applying the current search query.
func (ThemeModal) HandleKey ¶
func (m ThemeModal) HandleKey(k ThemeKey) (ThemeModal, ThemeModalMsg)
HandleKey updates dialog state for one key and may emit an action message.
func (ThemeModal) View ¶
func (m ThemeModal) View() string
View renders the dialog into a centered terminal string.
type ThemeModalMsg ¶
type ThemeModalMsg interface {
// contains filtered or unexported methods
}
ThemeModalMsg is emitted when the dialog wants the App to perform an action.
type ThinkingHitZone ¶ added in v0.11.0
type ThinkingHitZone struct {
StartLine int
EndLine int
MsgIndex int
// contains filtered or unexported fields
}
ThinkingHitZone maps a range of content lines to a message index for click-to-expand thinking blocks. MsgIndex is the index of the UIMessage in the slice that was passed to ViewWithHitZones; it is used as a stable key into App.expandedThinking.
type ToggleFavoriteModelAction ¶ added in v0.15.0
type ToggleFavoriteModelAction struct{ Provider, Model string }
ToggleFavoriteModelAction requests adding or removing the given model from the global favorites list.
type ToolHitZone ¶
type ToolHitZone struct {
StartLine int
EndLine int
ToolUseID string
// contains filtered or unexported fields
}
ToolHitZone maps a range of content lines to a tool use ID for click-to-expand.
type ToolStatus ¶
type ToolStatus int
ToolStatus is the execution lifecycle state of a single tool call. Only meaningful on UIMessage entries where Role == RoleTool.
const ( // ToolStatusUnknown is the zero value; no status text is rendered. // Used for hydrated orphan tool-use entries (tool_use with no matching // result — interrupted run). Should not occur in well-formed sessions. ToolStatusUnknown ToolStatus = iota // ToolStatusPending means the agent requested the tool call; no permission // decision has been asked yet. Rarely visible — transitions quickly. ToolStatusPending // ToolStatusAwaitingPermission means the permission engine published a // PermissionAsked event; the user has not yet responded. The modal is // visible; the inline row shows "Requesting permission…". ToolStatusAwaitingPermission // ToolStatusRunning means permission was granted (or not required); the tool // is executing. The inline row shows "Waiting for tool response…". ToolStatusRunning // ToolStatusCompleted means the tool finished without error. No status text. ToolStatusCompleted // ToolStatusError means the tool finished with an error. Inline row shows "error". ToolStatusError // ToolStatusCancelled means permission was denied or the user cancelled. // Inline row shows "cancelled". ToolStatusCancelled )
type UIMessage ¶
type UIMessage struct {
Role MessageRole
ToolName string // populated for RoleTool
ToolUseID string // optional provider-assigned tool_use_id; lets the
// view correlate this message with a SubagentState
Target string // optional tool target hint (path/cmd)
ToolArgs json.RawMessage // raw tool arguments for rich rendering
Raw string // raw text (streaming buffer or plain content)
FinalMarkdown string // cached glamour output once streaming completes
IsStreaming bool
IsError bool // tool result error flag
// Status is the execution lifecycle state for RoleTool messages.
// Set by handleBusEvent transitions; hydrated from persisted state.
Status ToolStatus
// SubagentID is the SubSessionID of a sub-agent dispatched by this
// message. When non-empty and the matching SubagentState is in
// MessageList.Subagents, the view renders a nested block under this
// message. Set on the parent `task` tool UIMessage when
// bus.SubagentStarted arrives.
SubagentID string
// MarkerSummary is the post-compaction context summary, populated on
// RoleMarker messages.
MarkerSummary string
// MarkerTokensSaved is the number of input tokens saved by the
// compaction, populated on RoleMarker messages.
MarkerTokensSaved int64
// Timestamp is the wall-clock time the message was created.
// Populated for RoleUser and RoleAssistant messages.
Timestamp time.Time
// Thinking holds the assistant's reasoning content (inline thinking).
// Populated for RoleAssistant messages that carry thinking blocks.
// Rendered in muted italic style at the top of the assistant bubble.
Thinking string
// OutputTokens is the number of output tokens for an assistant message.
// Zero while streaming or when the provider did not report usage.
OutputTokens int64
// CostUSD is the per-message cost in USD for an assistant message.
// Zero while streaming or when cost data is unavailable.
CostUSD float64
// DurationMs is the wall-clock elapsed milliseconds for an assistant message.
// Zero while streaming.
DurationMs int64
// AgentType is the agent identity label for the assistant bubble header-left.
// Defaults to "General" when empty.
AgentType string
// ModelName is the model name for the assistant bubble header-right metadata.
ModelName string
// ModeColor is the per-mode accent color for the bubble border/header.
// When non-nil, overrides the theme's default agent border color.
ModeColor color.Color
// SubagentColor is a deterministic accent color for subagent bubbles.
// Derived from the subagent type name. When non-nil, used for both
// the sidebar bar and header text.
SubagentColor color.Color
// VisibleRaw is the streaming assistant text that has been revealed by the
// typing animation. Raw keeps the full accumulated provider text; VisibleRaw
// lags behind it while IsStreaming is true so new text can animate in.
VisibleRaw string
// IsPlaceholder marks an assistant bubble as a transient "waiting for the
// next response" indicator. Used after a subagent completes so the user
// sees feedback near the chat content while the parent's next LLM call is
// still pending its first token. The first real assistant delta clears
// the placeholder content before appending.
IsPlaceholder bool
// MessageID is the store-assigned identifier for this message.
// Populated when the message is finalized from a bus.MessageAppended
// event or hydrated from the store. Used to detect and suppress
// duplicate insertions when the same MessageAppended event is processed
// more than once (e.g. around tool calls or subagent boundaries where
// the event may be replayed or arrive after the bubble was already
// flushed). Empty for messages that were never persisted (placeholders,
// system error rows).
MessageID string
}
UIMessage is one entry in the conversation view.
FinalMarkdown is the glamour-rendered output. Set by flushAssistantStream (and hydration/resize paths) once streaming completes; empty while streaming.
type URLHitZone ¶ added in v0.12.1
type URLHitZone struct {
// Line is the content line index (same coordinate space as SubagentHitZone
// StartLine), i.e. offset from the top of the rendered message list including
// viewport scroll offset.
Line int
StartCol int // inclusive visual column (0-indexed screen column)
EndCol int // exclusive visual column
URL string // validated http(s) URL, trailing punctuation stripped
}
URLHitZone maps a single screen line + column range to a clickable URL found in user or assistant message output. Clicking within [StartCol, EndCol) on the content line should open the URL with the OS default browser.
type URLPosition ¶ added in v0.12.1
type URLPosition struct {
Line int // zero-indexed line within the rendered part
StartCol int // zero-indexed column where URL text begins
EndCol int // zero-indexed column just past the last URL character
URL string // the matched URL (trailing punctuation stripped)
}
URLPosition records a URL's location within a block of rendered text. Line and StartCol/EndCol are zero-indexed visual positions in the ANSI-stripped text.
func ExtractURLPositions ¶ added in v0.12.1
func ExtractURLPositions(rendered string) []URLPosition
ExtractURLPositions scans a rendered (potentially ANSI-styled) text block and returns the visual line/column position of every http(s):// URL found. It strips ANSI sequences before matching so escape codes do not shift column indices. Duplicate URLs on the same line are each returned separately.
type UserMsgHitZone ¶ added in v0.13.1
type UserMsgHitZone struct {
StartLine int // inclusive, relative to message-list content
EndLine int // exclusive
StartCol int // inclusive visual column within the chat column
EndCol int // exclusive visual column within the chat column
MessageID string
MessageText string // raw message text (for copy action)
// contains filtered or unexported fields
}
UserMsgHitZone maps a rendered user bubble rectangle to a user message.
Source Files
¶
- api_key_modal.go
- breadcrumb.go
- command_palette.go
- compaction_banner.go
- compaction_modal.go
- diff_view.go
- footer.go
- glamour_style.go
- input.go
- memory_modal.go
- mention_highlight.go
- mention_palette.go
- message_action_modal.go
- messagelist.go
- modal_helpers.go
- model_modal.go
- onboarding_wizard.go
- paste_highlight.go
- permission_modal.go
- question_modal.go
- remember_scope_modal.go
- sessions_modal.go
- sidebar.go
- status_pills.go
- subagent_block.go
- theme_modal.go
- url_highlight.go
- working_verbs.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package anim provides a compact colored-runes animation component for use in terminal UIs built with bubbletea v2.
|
Package anim provides a compact colored-runes animation component for use in terminal UIs built with bubbletea v2. |
|
Package bubble provides the Bubble rendering primitive for the chat-bubble UI redesign (Phase 1).
|
Package bubble provides the Bubble rendering primitive for the chat-bubble UI redesign (Phase 1). |