Documentation
¶
Overview ¶
Package clikit is a shared visual layer for terminal CLIs — one palette and a set of lipgloss/Bubble Tea helpers, plus an opt-in agent PromptBox behind a small capability contract, so every tool built on it looks and feels like it came from the same dev. Extracted from its first proven consumer (code, the oh-my-pi launcher) and grown as new CLIs need more.
Index ¶
- Constants
- Variables
- func ClipLines(content string, width int) string
- func Meter(label, glyph, fill string, n int) string
- func NewHelp() help.Model
- func Pad(s string, n int) string
- func PadLeft(s string, n int) string
- func Panel(width int, content string) string
- func PanelContentWidth(width int) int
- func Rule(width int) string
- func Run(app App, opts ...RunOption) (tea.Model, error)
- func Scrollbar(total, h, start int) string
- func SeparatedSections(width int, sections ...string) string
- func WindowList(lines []string, cursor, h, w int) string
- func WrapHelp(h help.Model, width int, items []HelpItem) string
- type Action
- type ActionsConfirmedMsg
- type ActionsProposedMsg
- type ActionsRevertedMsg
- type App
- type AppliedActionsMsg
- type Askable
- type Asker
- type BoxCloseMsg
- type Commandable
- type Commander
- type DocCorpus
- type Documented
- type HelpItem
- type Loadable
- type MessageFilter
- type PromptBox
- func (b PromptBox) Busy() bool
- func (b *PromptBox) Focus() tea.Cmd
- func (b PromptBox) Init() tea.Cmd
- func (b *PromptBox) SetAsker(a Asker)
- func (b *PromptBox) SetCommander(c Commander)
- func (b *PromptBox) SetSize(w, maxH int)
- func (b *PromptBox) SetTitle(s string)
- func (b PromptBox) Update(msg tea.Msg) (PromptBox, tea.Cmd)
- func (b PromptBox) View() string
- type RunOption
- type WorkspaceID
- type WorkspaceItem
- type WorkspaceNav
Constants ¶
const ( CDim = "#78829b" CGrp = "#69727e" CAcc = "#ff9f52" CBord = "#3a4453" CHead = "#9aa4b1" CSelBg = "#1b212b" CGptSoft = "#6e91be" CClaSoft = "#c3a078" CRed = "#d05c60" CGreen = "#78c8aa" CEmpty = "#404757" // unused meter pips — dimmer than CDim, so the fill reads )
Palette — colour tokens and semantic roles shared across the CLIs.
const ( GWarn = "⚠︎" GBroken = "✗︎" GReset = "↻︎" )
Text-presentation glyphs (trailing U+FE0E) so terminals render them 1-cell, matching the width layout math assumes.
const ( GMemory = "" // nf-fa-memory — the local model chip GToggleOn = "" // resident in RAM GToggleOff = "" // evicted )
Nerd Font glyphs for the model-residency indicator: a memory chip plus an on/off toggle. Require a Nerd Font (the CLIs already assume one).
Variables ¶
var ( StDim = lipgloss.NewStyle().Foreground(lipgloss.Color(CDim)) StGrp = lipgloss.NewStyle().Foreground(lipgloss.Color(CGrp)) StHead = lipgloss.NewStyle().Foreground(lipgloss.Color(CHead)) StWarn = lipgloss.NewStyle().Foreground(lipgloss.Color(CAcc)) StBrk = lipgloss.NewStyle().Foreground(lipgloss.Color(CRed)) StOk = lipgloss.NewStyle().Foreground(lipgloss.Color(CGreen)) StStruck = lipgloss.NewStyle().Strikethrough(true).Faint(true).Foreground(lipgloss.Color(CDim)) )
Shared styles built from the palette.
var MeterRamp = [6]string{"", CGreen, "#a6c56e", "#d8c368", "#d89a5c", CRed}
MeterRamp colours a 1..5 meter green→red; index 1 is best (green), 5 is worst (red). A "higher is better" meter reverses the lookup (6-n) so fast/good reads green and slow/bad reads red.
Functions ¶
func Meter ¶
Meter renders a labelled 1..5 scale — n glyphs in the fill colour, the rest in the dim "empty" colour — always five glyphs, so the fill (and the headroom) read at a glance. Pair with MeterRamp to colour the fill by score.
func NewHelp ¶
NewHelp returns Bubble Tea's help model with the shared CLI palette applied. Consumers keep their own key maps and layout policies while keys, descriptions, separators, and truncation use one visual language.
func PadLeft ¶
PadLeft indents every line of s by n spaces. Safe on styled (ANSI) strings — the spaces sit before any escape codes.
func Panel ¶
Panel renders clipped content inside cli-kit's shared rounded chrome. The returned block never exceeds width, preventing terminal auto-wrap from moving footers below the viewport.
func PanelContentWidth ¶
PanelContentWidth reports the usable content width inside Panel.
func Run ¶
Run starts app under a cli-kit host that auto-mounts capabilities: Askable gets a prompt box in Ask mode, Commandable in Act mode (precedence), Documented grounds the backend; an app implementing none simply runs as-is. It returns the app's final model (unwrapped from the host) so callers can read end state.
func Scrollbar ¶
Scrollbar renders a 1-column, h-line track with a proportional thumb; when the content fits (total ≤ h) it is a blank column, keeping the layout width stable.
func SeparatedSections ¶
SeparatedSections stacks every non-empty section behind a full-width Rule. The result always begins with a boundary, so callers can attach it below any independently laid-out body without allowing adjacent sections to run together. Empty sections are omitted along with their boundary.
func WindowList ¶
WindowList clips a list to h lines, scrolled to keep the cursor visible, fixes the width, and appends a 1-column scrollbar (blank when everything fits) — so the column is always exactly h lines tall and w wide, and shows its scroll pos.
Types ¶
type Action ¶
Action is one host-validated mutation the agent proposes in Act mode. Its meaning is the host's: for the code generator an Action is {facet, value}. The closed set a Commander returns IS the tool's agent-facing API surface.
func ParseActions ¶
ParseActions extracts the JSON object from a model's output (tolerating any surrounding prose) and turns it into a key-sorted Action set — sorted so the proposal is deterministic regardless of JSON/map ordering. Backends share it so every Commander parses proposals the same way.
type ActionsConfirmedMsg ¶
type ActionsConfirmedMsg struct{ Prompt string }
ActionsConfirmedMsg is emitted when the user KEEPS the applied proposal. Prompt is the text they submitted, so a host can carry it forward (e.g. as the first message of the session it launches). The actions were already applied via ActionsProposedMsg.
type ActionsProposedMsg ¶
type ActionsProposedMsg struct{ Actions []Action }
ActionsProposedMsg is emitted as soon as a proposal is parsed. The host applies it immediately as a live preview (saving prior state), so the change is visible in the tool's own UI while the box shows keep/revert.
type ActionsRevertedMsg ¶
type ActionsRevertedMsg struct{}
ActionsRevertedMsg is emitted when the user rejects the applied proposal; the host restores the state it saved on ActionsProposedMsg.
type App ¶
App is the baseline a cli-kit TUI implements: a Bubble Tea model. It opts into extra capabilities (Askable/Commandable/Documented) by also implementing those interfaces; Run detects them and mounts the matching UI.
type AppliedActionsMsg ¶
type AppliedActionsMsg struct{ Actions []Action }
AppliedActionsMsg lets the host replace what the box lists as "applied" with the authoritative set it actually applied — which may differ from the parsed proposal (e.g. the host derives extra changes, or repairs/validates some). Optional: a host that applies actions verbatim need never send it.
type Askable ¶
type Askable interface{ Asker() Asker }
Askable enables the PromptBox in read-only Ask mode.
type Asker ¶
Asker answers a prompt read-only, streaming the answer as string chunks on the returned channel and closing it when the answer is complete. Cancelling ctx MUST stop the underlying work (e.g. kill the omp subprocess) and close the channel; a non-nil error reports a failure to start.
type BoxCloseMsg ¶
type BoxCloseMsg struct{}
BoxCloseMsg is emitted when the user dismisses an idle box (esc while editing). A host (see Run) listens for it to hide the box.
type Commandable ¶
type Commandable interface{ Commander() Commander }
Commandable additionally enables Act mode (propose → diff → confirm).
type Commander ¶
type Commander interface {
Propose(ctx context.Context, prompt string) (<-chan string, error)
Parse(output string) ([]Action, error)
}
Commander proposes changes for a prompt in two parts so the box can show the model working: Propose streams the model's raw output (rationale + result) for live display, and Parse turns the completed output into a closed set of typed actions the host validates and applies. Cancelling ctx stops the work.
type DocCorpus ¶
type DocCorpus string
DocCorpus is grounding text a Documented host exposes; a real Asker backend injects it into the model's system prompt so answers are tool-specific.
type Documented ¶
type Documented interface{ Docs() DocCorpus }
Documented supplies grounding for Ask/Act.
type Loadable ¶
type Loadable interface {
Load(ctx context.Context) error
Unload(ctx context.Context) error
Loaded(ctx context.Context) (bool, error)
}
Loadable is an optional backend capability for a local model that can be held resident in memory. A backend that implements it lets the PromptBox offer a toggle key (load/unload) and show residency state, so the user decides when the model occupies RAM rather than it lingering unbidden. Load pins the model, Unload evicts it, and Loaded reports whether it is resident now. All three take a context so the call can be cancelled/timed out.
type MessageFilter ¶
MessageFilter runs before Bubble Tea dispatches a message. Returning nil drops the message before Update and View, which is useful for coalescing high-rate input that would otherwise trigger redundant redraws. The model passed to the filter is the consumer app, not cli-kit's host wrapper.
type PromptBox ¶
type PromptBox struct {
// contains filtered or unexported fields
}
PromptBox is a value type — Update returns an updated copy, matching the bubbles convention.
func NewPromptBox ¶
func NewPromptBox() PromptBox
NewPromptBox builds a box in the editing state. Call SetAsker to give it a backend and SetSize before rendering.
func (*PromptBox) SetAsker ¶
SetAsker wires the read-only backend. Without one, submitting is a no-op. A backend that is also Loadable enables the load/unload toggle.
func (*PromptBox) SetCommander ¶
SetCommander wires the Act-mode backend. When set, submitting asks the Commander for a proposal (streamed live, then shown for confirmation) instead of streaming a plain answer; it takes precedence over an Asker. A Commander that is also Loadable enables the load/unload toggle.
func (*PromptBox) SetSize ¶
SetSize lays the box out within w outer cells, with maxH the tallest the box may grow to (the host caps it so it never eats the whole screen). The box is content-sized: the input grows with what's typed and the answer pane fits its text, so an idle box is a single line rather than a half-screen panel.
func (*PromptBox) SetTitle ¶
SetTitle sets an optional header line (e.g. "prompt → profile · gpt-5.6-luna") so the user can see what the box is doing / which model it uses.
type RunOption ¶
type RunOption func(*host)
RunOption configures Run.
func WithAltScreen ¶
func WithAltScreen() RunOption
WithAltScreen runs the program in the alternate screen buffer.
func WithMessageFilter ¶
func WithMessageFilter(filter MessageFilter) RunOption
WithMessageFilter installs a pre-dispatch Bubble Tea message filter.
func WithMouseCellMotion ¶
func WithMouseCellMotion() RunOption
WithMouseCellMotion enables cell-motion mouse reporting (e.g. wheel scroll).
func WithToggleKey ¶
WithToggleKey overrides the key that opens the prompt box (default "ctrl+o").
type WorkspaceID ¶
type WorkspaceID string
WorkspaceID identifies one persistent destination in a TUI shell. IDs are application-defined; cli-kit only owns ordering and navigation semantics.
type WorkspaceItem ¶
type WorkspaceItem struct {
ID WorkspaceID
Label string
Shortcut string
}
WorkspaceItem describes one destination shown by a TUI shell.
type WorkspaceNav ¶
type WorkspaceNav struct {
// contains filtered or unexported fields
}
WorkspaceNav is a domain-free, persistent workspace navigator. It deliberately owns no rendering or Bubble Tea messages so applications can keep their local state while sharing one predictable navigation model.
func NewWorkspaceNav ¶
func NewWorkspaceNav(items ...WorkspaceItem) WorkspaceNav
NewWorkspaceNav constructs a navigator in declaration order. Empty and duplicate IDs are ignored so Active always identifies an unambiguous item.
func (WorkspaceNav) Active ¶
func (n WorkspaceNav) Active() WorkspaceID
Active returns the selected workspace ID, or the empty ID for an empty nav.
func (WorkspaceNav) ActiveItem ¶
func (n WorkspaceNav) ActiveItem() (WorkspaceItem, bool)
ActiveItem returns the selected declaration and whether one exists.
func (WorkspaceNav) Items ¶
func (n WorkspaceNav) Items() []WorkspaceItem
Items returns a copy of the ordered workspace declarations.
func (*WorkspaceNav) Next ¶
func (n *WorkspaceNav) Next() WorkspaceID
Next advances one destination, wrapping at the end.
func (*WorkspaceNav) Previous ¶
func (n *WorkspaceNav) Previous() WorkspaceID
Previous moves back one destination, wrapping at the beginning.
func (*WorkspaceNav) Select ¶
func (n *WorkspaceNav) Select(id WorkspaceID) bool
Select activates id. Unknown IDs leave the navigator unchanged.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package ollama provides a clikit Act backend that talks to a local ollama daemon over HTTP.
|
Package ollama provides a clikit Act backend that talks to a local ollama daemon over HTTP. |
|
Package omp provides clikit backends that shell out to the oh-my-pi CLI (https://github.com/can1357/oh-my-pi).
|
Package omp provides clikit backends that shell out to the oh-my-pi CLI (https://github.com/can1357/oh-my-pi). |