overlay

package
v0.12.21 Latest Latest
Warning

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

Go to latest
Published: Mar 25, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package overlay provides a terminal overlay system for agnt. It renders a status indicator bar and popup menus using ANSI escape sequences, while passing through input/output to the underlying PTY.

Index

Constants

View Source
const (
	// Cursor control
	CursorHide     = "\x1b[?25l"
	CursorShow     = "\x1b[?25h"
	CursorSave     = "\x1b[s"
	CursorRestore  = "\x1b[u"
	CursorHome     = "\x1b[H"
	CursorToFormat = "\x1b[%d;%dH" // row;col (1-indexed)

	// Screen control
	ClearScreen    = "\x1b[2J"
	ClearLine      = "\x1b[2K"
	ClearToEOL     = "\x1b[K"
	ScrollRegion   = "\x1b[%d;%dr" // top;bottom
	ResetScroll    = "\x1b[r"
	EnterAltScreen = "\x1b[?1049h"
	ExitAltScreen  = "\x1b[?1049l"

	// Text attributes
	Reset     = "\x1b[0m"
	Bold      = "\x1b[1m"
	Dim       = "\x1b[2m"
	Italic    = "\x1b[3m"
	Underline = "\x1b[4m"
	Blink     = "\x1b[5m"
	Reverse   = "\x1b[7m"

	// Foreground colors (basic)
	FgBlack   = "\x1b[30m"
	FgRed     = "\x1b[31m"
	FgGreen   = "\x1b[32m"
	FgYellow  = "\x1b[33m"
	FgBlue    = "\x1b[34m"
	FgMagenta = "\x1b[35m"
	FgCyan    = "\x1b[36m"
	FgWhite   = "\x1b[37m"
	FgDefault = "\x1b[39m"

	// Bright foreground colors
	FgBrightBlack   = "\x1b[90m"
	FgBrightRed     = "\x1b[91m"
	FgBrightGreen   = "\x1b[92m"
	FgBrightYellow  = "\x1b[93m"
	FgBrightBlue    = "\x1b[94m"
	FgBrightMagenta = "\x1b[95m"
	FgBrightCyan    = "\x1b[96m"
	FgBrightWhite   = "\x1b[97m"

	// Background colors (basic)
	BgBlack   = "\x1b[40m"
	BgRed     = "\x1b[41m"
	BgGreen   = "\x1b[42m"
	BgYellow  = "\x1b[43m"
	BgBlue    = "\x1b[44m"
	BgMagenta = "\x1b[45m"
	BgCyan    = "\x1b[46m"
	BgWhite   = "\x1b[47m"
	BgDefault = "\x1b[49m"

	// Bright background colors
	BgBrightBlack = "\x1b[100m"
)

ANSI escape sequences.

View Source
const (
	BoxHorizontal       = "─"
	BoxVertical         = "│"
	BoxTopLeft          = "┌"
	BoxTopRight         = "┐"
	BoxBottomLeft       = "└"
	BoxBottomRight      = "┘"
	BoxVerticalRight    = "├"
	BoxVerticalLeft     = "┤"
	BoxHorizontalDown   = "┬"
	BoxHorizontalUp     = "┴"
	BoxCross            = "┼"
	BoxDoubleHorizontal = "═"
	BoxDoubleVertical   = "║"

	// Rounded box drawing characters (niri-style).
	RoundTopLeft     = "╭"
	RoundTopRight    = "╮"
	RoundBottomLeft  = "╰"
	RoundBottomRight = "╯"
)

Box drawing characters (Unicode).

View Source
const (
	IconConnected    = "●"
	IconDisconnected = "○"
	IconError        = "✗"
	IconWarning      = "⚠"
	IconProcess      = "⚙"
	IconProxy        = "⇄"
	IconOK           = "✓"
)

Status icons.

View Source
const (
	RegionMenu  = "menu"
	RegionInput = "input"
)

Overlay region names for tracking.

Variables

View Source
var DebugWin32Input = false

DebugWin32Input enables logging of win32-input-mode parsing

Functions

func NeedsAggressiveMode added in v0.12.19

func NeedsAggressiveMode() bool

NeedsAggressiveMode detects whether the current terminal needs aggressive filtering. Returns true for ConPTY (Windows Terminal, VS Code terminal) where DECSTBM scroll regions are unreliable. Returns false for Unix PTYs, WSL, mintty, and other terminals with proper DECSTBM support.

func NormalizeListenAddr added in v0.12.0

func NormalizeListenAddr(addr string) string

NormalizeListenAddr converts wildcard and loopback addresses to localhost for clickable URLs. This is the most reliable option since LAN IPs can be unreliable in virtual environments (WSL2, Docker, etc.). Users who need LAN access can check the detailed proxy output.

func ScanWin32Input added in v0.6.3

func ScanWin32Input(r io.Reader) iter.Seq[byte]

ScanWin32Input returns an iterator that reads from r and yields parsed bytes. It handles Windows Terminal win32-input-mode escape sequences, extracting the unicode character values and yielding them as individual bytes. Buffer boundaries are handled internally - incomplete sequences at the end of a read are held and combined with the next read.

func StateColorCode added in v0.8.0

func StateColorCode(state string) string

StateColorCode returns the ANSI color code for a process state.

Types

type Action

type Action int

Action represents an action that can be triggered from the menu.

const (
	ActionNone Action = iota
	ActionRunScript
	ActionBashCommand
	ActionStartProxy
	ActionStopProxy
	ActionShowProcesses
	ActionShowProxies
	ActionShowLogs
	ActionRefreshStatus
	ActionToggleIndicator
	ActionConnectDaemon
	ActionSummarize
	ActionClose
)

type ActivityMonitor

type ActivityMonitor struct {
	// contains filtered or unexported fields
}

ActivityMonitor wraps an io.Writer to monitor output activity. It detects when data is being written (active) and when writing stops (idle). It can also broadcast output previews (recent lines) to connected browsers. It handles animated output (like Ink spinners) by detecting carriage returns and debouncing rapid updates to prevent scroll spam.

func NewActivityMonitor

func NewActivityMonitor(w io.Writer, cfg ActivityMonitorConfig) *ActivityMonitor

NewActivityMonitor creates a new activity monitor wrapping the given writer.

func (*ActivityMonitor) IsActive

func (am *ActivityMonitor) IsActive() bool

IsActive returns true if currently active.

func (*ActivityMonitor) State

func (am *ActivityMonitor) State() ActivityState

State returns the current activity state.

func (*ActivityMonitor) Stop

func (am *ActivityMonitor) Stop()

Stop stops the activity monitor.

func (*ActivityMonitor) Write

func (am *ActivityMonitor) Write(p []byte) (n int, err error)

Write implements io.Writer and tracks activity.

type ActivityMonitorConfig

type ActivityMonitorConfig struct {
	// IdleTimeout is how long to wait with no output before transitioning to idle.
	// Default: 2 seconds
	IdleTimeout time.Duration

	// OnStateChange is called when activity state changes.
	OnStateChange func(ActivityState)

	// MinActiveBytes is the minimum bytes written to trigger active state.
	// This prevents brief flickers of activity for small outputs.
	// Default: 10
	MinActiveBytes int

	// OnOutputPreview is called with recent output lines for browser display.
	// Lines are debounced to avoid overwhelming the browser.
	OnOutputPreview func(lines []string)

	// PreviewMaxLines is the maximum number of lines to keep for preview.
	// Default: 5
	PreviewMaxLines int

	// PreviewDebounce is the minimum time between output preview broadcasts.
	// Default: 200ms
	PreviewDebounce time.Duration

	// AnimationDebounce is how long to wait after the last update to an animating
	// line before flushing it. This prevents rapid updates (like Ink spinners)
	// from appearing as scrolling lines. Default: 100ms
	AnimationDebounce time.Duration

	// ShowDoneMessage adds a persistent "Done" message when activity goes idle.
	// Default: true
	ShowDoneMessage bool

	// DoneMessage is the message to show when activity goes idle.
	// Default: "✓ Done"
	DoneMessage string

	// OnOutputLine is called with each complete, cleaned line of output.
	// Used by AlertScanner to detect error/warning patterns.
	OnOutputLine func(string)
}

ActivityMonitorConfig configures the activity monitor.

func DefaultActivityMonitorConfig

func DefaultActivityMonitorConfig() ActivityMonitorConfig

DefaultActivityMonitorConfig returns the default configuration.

type ActivityState

type ActivityState int

ActivityState represents the current activity state.

const (
	ActivityIdle ActivityState = iota
	ActivityActive
)

type AlertBatch added in v0.11.5

type AlertBatch struct {
	Matches  []*AlertMatch
	ScriptID string
}

AlertBatch is a collection of alert matches to be delivered together.

func (*AlertBatch) Format added in v0.11.5

func (b *AlertBatch) Format() string

Format renders the batch as a human-readable message for the AI agent.

func (*AlertBatch) MaxSeverity added in v0.11.5

func (b *AlertBatch) MaxSeverity() AlertSeverity

MaxSeverity returns the highest severity in the batch.

type AlertMatch added in v0.11.5

type AlertMatch struct {
	Pattern   *AlertPattern
	Line      string
	Timestamp time.Time
	ScriptID  string
}

AlertMatch represents a single matched alert from process output.

type AlertPattern added in v0.11.5

type AlertPattern struct {
	ID          string
	Pattern     *regexp.Regexp
	Severity    AlertSeverity
	Category    string // e.g. "dotnet", "webpack", "go", "generic"
	Description string
}

AlertPattern defines a regex pattern to match against process output.

func DefaultAlertPatterns added in v0.11.5

func DefaultAlertPatterns() []*AlertPattern

DefaultAlertPatterns returns the built-in set of alert patterns for common dev server frameworks and languages.

type AlertScanner added in v0.11.5

type AlertScanner struct {
	// contains filtered or unexported fields
}

AlertScanner matches process output lines against known error/warning patterns, deduplicates, batches, and delivers alerts through a callback.

func NewAlertScanner added in v0.11.5

func NewAlertScanner(cfg AlertScannerConfig) *AlertScanner

NewAlertScanner creates and starts a new AlertScanner with the given config.

func (*AlertScanner) AddPattern added in v0.11.5

func (s *AlertScanner) AddPattern(p *AlertPattern)

AddPattern registers an additional alert pattern.

func (*AlertScanner) DisablePattern added in v0.11.5

func (s *AlertScanner) DisablePattern(id string)

DisablePattern disables a pattern by ID.

func (*AlertScanner) ProcessLine added in v0.11.5

func (s *AlertScanner) ProcessLine(line string, scriptID string)

ProcessLine checks a single line of output against all enabled patterns.

func (*AlertScanner) RecentMatches added in v0.12.0

func (s *AlertScanner) RecentMatches(since time.Time) []*AlertMatch

RecentMatches returns matches from the ring buffer with timestamp >= since. If since is the zero time, all buffered matches are returned. Results are ordered oldest-to-newest.

func (*AlertScanner) SetEnabled added in v0.11.5

func (s *AlertScanner) SetEnabled(enabled bool)

SetEnabled enables or disables the scanner.

func (*AlertScanner) Stop added in v0.11.5

func (s *AlertScanner) Stop()

Stop stops the scanner and flushes any pending alerts.

type AlertScannerConfig added in v0.11.5

type AlertScannerConfig struct {
	// Patterns are additional custom patterns to register.
	Patterns []*AlertPattern

	// DisabledIDs is a set of pattern IDs to disable.
	DisabledIDs []string

	// BatchWindow is how long to collect alerts before flushing.
	// Default: 3 seconds.
	BatchWindow time.Duration

	// DedupeWindow is how long to suppress duplicate alerts.
	// Default: 60 seconds.
	DedupeWindow time.Duration

	// ActivityState returns the current activity state of the AI agent.
	// If non-nil and returns ActivityActive, flush is deferred.
	ActivityState func() ActivityState

	// OnAlert is called when a batch of alerts is ready for delivery.
	OnAlert func(*AlertBatch)
}

AlertScannerConfig configures the AlertScanner.

type AlertSeverity added in v0.11.5

type AlertSeverity string

AlertSeverity indicates the severity of an alert match.

const (
	AlertSeverityError   AlertSeverity = "error"
	AlertSeverityWarning AlertSeverity = "warning"
	AlertSeverityInfo    AlertSeverity = "info"
)

type AuditData added in v0.8.0

type AuditData struct {
	AuditType string          `json:"auditType"`
	Label     string          `json:"label"`
	Summary   string          `json:"summary"`
	Result    json.RawMessage `json:"result"`
}

AuditData represents the audit data to summarize.

type AuditSummarizer added in v0.8.0

type AuditSummarizer struct {
	// contains filtered or unexported fields
}

AuditSummarizer uses an AI channel to generate high-quality audit reports.

func NewAuditSummarizer added in v0.8.0

func NewAuditSummarizer(config AuditSummarizerConfig) *AuditSummarizer

NewAuditSummarizer creates a new audit summarizer.

func (*AuditSummarizer) IsAvailable added in v0.8.0

func (s *AuditSummarizer) IsAvailable() bool

IsAvailable returns true if the AI channel is available.

func (*AuditSummarizer) SummarizeAudit added in v0.8.0

func (s *AuditSummarizer) SummarizeAudit(ctx context.Context, audit AuditData, userMessage string) (string, error)

SummarizeAudit generates a high-quality report from audit data. It also saves the full audit data to .agnt/audit/ for later reference.

type AuditSummarizerConfig added in v0.8.0

type AuditSummarizerConfig struct {
	// Agent type for AI summarization (default: uses API mode with Anthropic)
	Agent aichannel.AgentType
	// Optional custom command (overrides agent default)
	Command string
	// Optional additional args
	Args []string
	// Timeout for AI response (default 30 seconds)
	Timeout time.Duration

	// --- API Mode Configuration ---
	// UseAPI forces API mode (default: true for audit summarization)
	UseAPI bool
	// LLMProvider specifies which provider to use (auto-detected if empty)
	LLMProvider aichannel.LLMProvider
	// APIKey overrides environment variable lookup
	APIKey string
	// Model overrides the provider's default model
	Model string
}

AuditSummarizerConfig configures the audit summarizer.

type BashRunner

type BashRunner interface {
	RunBashCommand(command string) (processID string, err error)
}

BashRunner is an interface for running bash commands via the daemon.

type BrowserSession

type BrowserSession struct {
	ProxyID      string
	SessionID    string
	URL          string
	Interactions int
	Mutations    int
	LastActivity time.Time
}

BrowserSession holds information about a connected browser.

type Config

type Config struct {
	// Hotkey to toggle overlay (default: Ctrl+L = 0x0C)
	Hotkey byte

	// Whether to show indicator bar by default
	ShowIndicator bool

	// Status refresh interval
	StatusRefreshInterval time.Duration

	// Version string to display in dashboard
	Version string

	// Action callback
	OnAction func(Action) error

	// Freeze/unfreeze callbacks for screen management
	OnFreeze   func() // Called when menu opens (freeze PTY output)
	OnUnfreeze func() // Called when menu closes (send SIGWINCH to redraw)
}

Config holds overlay configuration.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default overlay configuration.

type ConnectionStatus

type ConnectionStatus int

ConnectionStatus represents daemon connection state.

const (
	ConnectionUnknown ConnectionStatus = iota
	ConnectionConnected
	ConnectionDisconnected
	ConnectionError
)

type DaemonBashRunner

type DaemonBashRunner struct {
	// contains filtered or unexported fields
}

DaemonBashRunner implements BashRunner using a shared daemon connection.

func NewDaemonBashRunner

func NewDaemonBashRunner(conn *daemon.Conn) *DaemonBashRunner

NewDaemonBashRunner creates a new DaemonBashRunner using a shared connection.

func (*DaemonBashRunner) RunBashCommand

func (r *DaemonBashRunner) RunBashCommand(command string) (string, error)

RunBashCommand runs a bash command via the daemon and returns the process ID.

type DaemonConnector

type DaemonConnector interface {
	// Connect attempts to connect to the daemon, auto-starting it if needed.
	// Returns nil on success, or an error describing why the connection failed.
	Connect() error
	// IsConnected returns true if currently connected to the daemon.
	IsConnected() bool
}

DaemonConnector is an interface for connecting to and managing the daemon.

type DaemonConnectorImpl

type DaemonConnectorImpl struct {
	// contains filtered or unexported fields
}

DaemonConnectorImpl implements DaemonConnector using a shared connection.

func NewDaemonConnector

func NewDaemonConnector(conn *daemon.Conn) *DaemonConnectorImpl

NewDaemonConnector creates a new DaemonConnector using a shared connection.

func (*DaemonConnectorImpl) Connect

func (c *DaemonConnectorImpl) Connect() error

Connect attempts to connect to the daemon, auto-starting it if needed.

func (*DaemonConnectorImpl) IsConnected

func (c *DaemonConnectorImpl) IsConnected() bool

IsConnected returns true if currently connected to the daemon.

type DaemonOutputFetcher

type DaemonOutputFetcher struct {
	// contains filtered or unexported fields
}

DaemonOutputFetcher implements ProcessOutputFetcher using a shared daemon connection.

func NewDaemonOutputFetcher

func NewDaemonOutputFetcher(conn *daemon.Conn) *DaemonOutputFetcher

NewDaemonOutputFetcher creates a new DaemonOutputFetcher using a shared connection.

func (*DaemonOutputFetcher) GetProcessOutput

func (f *DaemonOutputFetcher) GetProcessOutput(processID string, tailLines int) (string, error)

GetProcessOutput fetches the last N lines of output for a process.

func (*DaemonOutputFetcher) GetScriptOutput added in v0.12.16

func (f *DaemonOutputFetcher) GetScriptOutput(scriptName string, tailLines int) (string, error)

GetScriptOutput fetches the last N lines of output for a script by name.

type ErrorInfo

type ErrorInfo struct {
	Source    string // "proxy", "process", "daemon"
	Message   string
	Timestamp time.Time
}

ErrorInfo holds recent error information.

type EscapeSequenceReader

type EscapeSequenceReader struct {
	// contains filtered or unexported fields
}

EscapeSequenceReader helps parse escape sequences from input.

func NewEscapeSequenceReader

func NewEscapeSequenceReader() *EscapeSequenceReader

NewEscapeSequenceReader creates a new escape sequence reader.

func (*EscapeSequenceReader) Feed

func (r *EscapeSequenceReader) Feed(b byte) (key string, complete bool)

Feed feeds a byte into the reader and returns any recognized key.

func (*EscapeSequenceReader) IsPending

func (r *EscapeSequenceReader) IsPending() bool

IsPending returns true if we're in the middle of parsing an escape sequence.

func (*EscapeSequenceReader) Reset

func (r *EscapeSequenceReader) Reset()

Reset resets the reader state.

func (*EscapeSequenceReader) Timeout

func (r *EscapeSequenceReader) Timeout() (key string, hadPending bool)

Timeout should be called when no more input arrives after starting an escape sequence. This allows treating a lone Escape key press as "Escape".

type FilterConfig

type FilterConfig struct {
	// ProtectBottomRows is the number of rows to protect at the bottom.
	// Scroll region will be set to exclude these rows.
	ProtectBottomRows int

	// AggressiveMode enables full cursor clamping, manual scroll, and alt screen
	// blocking. Required for terminals where DECSTBM is unreliable (ConPTY).
	// When false (default), only scroll region enforcement and DA1 suppression
	// are active — cursor positioning passes through unchanged.
	// Use NeedsAggressiveMode() to detect automatically.
	AggressiveMode bool

	// RedrawInterval is how often to check if indicator needs redrawing.
	// Set to 0 to disable periodic redraw.
	RedrawInterval time.Duration

	// OnRedraw is called when the indicator should be redrawn.
	OnRedraw func()
}

FilterConfig configures the PTY output filter behavior.

type InputRouter

type InputRouter struct {
	// contains filtered or unexported fields
}

InputRouter routes input between the PTY and the overlay.

func NewInputRouter

func NewInputRouter(ptmx PtyReadWriter, overlay *Overlay, hotkey byte) *InputRouter

NewInputRouter creates a new InputRouter.

func (*InputRouter) GetLastDaemonError

func (r *InputRouter) GetLastDaemonError() string

GetLastDaemonError returns the last error from daemon connection attempt.

func (*InputRouter) Run

func (r *InputRouter) Run() error

Run starts routing input from stdin to either the overlay or PTY. This blocks until stdin is closed or Stop is called.

func (*InputRouter) SetBashRunner

func (r *InputRouter) SetBashRunner(runner BashRunner)

SetBashRunner sets the bash runner for executing bash commands via the daemon.

func (*InputRouter) SetDaemonConnector

func (r *InputRouter) SetDaemonConnector(connector DaemonConnector)

SetDaemonConnector sets the daemon connector for connecting to the daemon.

func (*InputRouter) SetOutputFetcher

func (r *InputRouter) SetOutputFetcher(fetcher ProcessOutputFetcher)

SetOutputFetcher sets the output fetcher for viewing process output.

func (*InputRouter) SetStatusFetcher

func (r *InputRouter) SetStatusFetcher(fetcher *StatusFetcher)

SetStatusFetcher sets the status fetcher for refreshing after connection.

func (*InputRouter) SetSummarizer

func (r *InputRouter) SetSummarizer(summarizer StatusSummarizer)

SetSummarizer sets the summarizer for generating AI summaries.

func (*InputRouter) Stop

func (r *InputRouter) Stop()

Stop stops the input router.

type Menu struct {
	Title string
	Items []MenuItem
}

Menu represents a popup menu.

func DisconnectedMenu

func DisconnectedMenu() Menu

DisconnectedMenu returns a menu for when the daemon is not connected.

func ErrorMenu

func ErrorMenu(title, message string) Menu

ErrorMenu creates a menu displaying an error message with a retry option.

func MainMenu() Menu

MainMenu returns the main overlay menu.

func ProcessListMenu

func ProcessListMenu(processes []ProcessInfo) Menu

ProcessListMenu creates a menu showing running processes.

func ProxyListMenu

func ProxyListMenu(proxies []ProxyInfo) Menu

ProxyListMenu creates a menu showing running proxies.

func ScriptMenu

func ScriptMenu(scripts []string) Menu

ScriptMenu creates a menu of available scripts.

type MenuItem struct {
	Label    string
	Shortcut rune   // Single character shortcut (0 for none)
	Action   Action // Action to trigger
	SubMenu  *Menu  // Sub-menu (nil if none)
}

MenuItem represents a single menu item.

type OutputGate

type OutputGate struct {
	// contains filtered or unexported fields
}

OutputGate wraps a writer and can freeze/unfreeze output. When frozen, all writes are discarded. When unfrozen, writes pass through. This is used to prevent PTY output from corrupting the overlay menu.

func NewOutputGate

func NewOutputGate(out io.Writer) *OutputGate

NewOutputGate creates a new OutputGate.

func (*OutputGate) Freeze

func (og *OutputGate) Freeze()

Freeze stops writing to the underlying writer (discards writes). Calls onFreeze callback if set and not already frozen. The callback runs after the lock is released to prevent deadlock when the callback writes to this gate.

func (*OutputGate) IsFrozen

func (og *OutputGate) IsFrozen() bool

IsFrozen returns whether the gate is currently frozen.

func (*OutputGate) SetCallbacks

func (og *OutputGate) SetCallbacks(onFreeze, onUnfreeze func())

SetCallbacks sets the freeze/unfreeze callbacks.

func (*OutputGate) Unfreeze

func (og *OutputGate) Unfreeze()

Unfreeze resumes writing to the underlying writer. Calls onUnfreeze callback if set and was frozen. The callback runs after the lock is released to prevent deadlock when the callback writes to this gate (e.g. EnforceScrollRegion).

func (*OutputGate) Write

func (og *OutputGate) Write(p []byte) (n int, err error)

Write writes to the underlying writer if not frozen. When frozen, writes are discarded but return success.

func (*OutputGate) WriteDirect added in v0.12.11

func (og *OutputGate) WriteDirect(p []byte) (n int, err error)

WriteDirect writes to the underlying writer regardless of freeze state, while holding the gate's mutex. This is used by the overlay renderer to write indicator/menu content without interleaving with PTY output.

type Overlay

type Overlay struct {
	// contains filtered or unexported fields
}

Overlay manages the terminal overlay display.

func New

func New(ptmx PtyReadWriter, width, height int, cfg Config) *Overlay

New creates a new Overlay.

func (*Overlay) DrawStatusBarMessage added in v0.7.8

func (o *Overlay) DrawStatusBarMessage(message string)

DrawStatusBarMessage draws a message on the status bar. This is used for transient messages like spinner updates. Note: The caller should call Redraw() or DrawIndicator() when done to restore the normal status bar.

func (*Overlay) GetStatus

func (o *Overlay) GetStatus() Status

GetStatus returns the current status.

func (*Overlay) Hide

func (o *Overlay) Hide()

Hide hides the overlay.

func (*Overlay) IsActive

func (o *Overlay) IsActive() bool

IsActive returns true if the overlay is capturing input.

func (*Overlay) Redraw

func (o *Overlay) Redraw()

Redraw forces a redraw of the overlay.

func (*Overlay) RedrawIndicator added in v0.7.8

func (o *Overlay) RedrawIndicator()

RedrawIndicator redraws just the status bar indicator with current status.

func (*Overlay) SetAltScreenChecker added in v0.12.0

func (o *Overlay) SetAltScreenChecker(fn func() bool)

SetAltScreenChecker sets a callback that reports whether the child process is currently in the alternate screen buffer. Used to decide whether the overlay can safely use alt screen for menus (only when child is on main screen).

func (*Overlay) SetGate

func (o *Overlay) SetGate(gate *OutputGate)

SetGate sets the output gate for freeze/unfreeze control.

func (*Overlay) SetRedrawPaused added in v0.12.0

func (o *Overlay) SetRedrawPaused(paused bool)

SetRedrawPaused pauses or resumes indicator redraws. Status updates are still stored — just not rendered until unpaused.

func (*Overlay) SetSize

func (o *Overlay) SetSize(width, height int)

SetSize updates the terminal dimensions.

func (*Overlay) Show

func (o *Overlay) Show()

Show shows the overlay menu.

func (*Overlay) ShowIndicator

func (o *Overlay) ShowIndicator() bool

ShowIndicator returns whether the indicator bar is visible.

func (*Overlay) State

func (o *Overlay) State() State

State returns the current overlay state.

func (*Overlay) Toggle

func (o *Overlay) Toggle()

Toggle toggles the overlay menu visibility.

func (*Overlay) ToggleIndicator

func (o *Overlay) ToggleIndicator()

ToggleIndicator toggles the indicator bar visibility.

func (*Overlay) UpdateStatus

func (o *Overlay) UpdateStatus(status Status)

UpdateStatus updates the displayed status.

type OverlayStack

type OverlayStack struct {
	// contains filtered or unexported fields
}

OverlayStack manages a stack of overlays for proper z-order handling.

func NewOverlayStack

func NewOverlayStack(sm *ScreenManager) *OverlayStack

NewOverlayStack creates a new overlay stack.

func (*OverlayStack) Clear

func (os *OverlayStack) Clear()

Clear removes all overlays from the stack without clearing screen regions. Use this when relying on another mechanism (like SIGWINCH) to redraw.

func (*OverlayStack) Depth

func (os *OverlayStack) Depth() int

Depth returns the number of overlays on the stack.

func (*OverlayStack) Pop

func (os *OverlayStack) Pop()

Pop removes and restores the top overlay.

func (*OverlayStack) PopAll

func (os *OverlayStack) PopAll()

PopAll removes and restores all overlays.

func (*OverlayStack) Push

func (os *OverlayStack) Push(name string, region ScreenRegion)

Push adds an overlay to the stack.

type PanelItem added in v0.12.7

type PanelItem struct {
	Type         string // "overview", "process", "proxy"
	ID           string // process or proxy ID
	Label        string // short display label for tab bar
	Content      string // cached output content (accumulates across restarts)
	ScrollOffset int    // lines scrolled up from bottom (0 = pinned to bottom)
	ProcessState string // last known process state ("running", "failed", "stopped", "")
	// contains filtered or unexported fields
}

PanelItem represents a navigable panel in the horizontal panel view. Process panels persist until explicitly closed by the user.

func (*PanelItem) AppendContent added in v0.12.15

func (p *PanelItem) AppendContent(text, separator string, maxLines int)

AppendContent appends text to the panel content with a separator and caps at maxLines.

func (*PanelItem) ContentLines added in v0.12.15

func (p *PanelItem) ContentLines() int

ContentLines returns the cached number of lines in the panel's content.

func (*PanelItem) IsDone added in v0.12.15

func (p *PanelItem) IsDone() bool

IsDone returns true if the process has stopped and the panel can be closed.

func (*PanelItem) SetContent added in v0.12.15

func (p *PanelItem) SetContent(content string)

SetContent replaces the panel content and updates the cached line count.

type ProcessInfo

type ProcessInfo struct {
	ID            string
	Command       string
	State         string
	Runtime       time.Duration
	LastOutput    string   // Last line of output (trimmed)
	URLs          []string // URLs parsed from recent output
	LinkedProxyID string   // ID of proxy targeting this process (if any)
	HasAlerts     bool     // Whether process has recent alerts/errors
}

ProcessInfo holds information about a running process.

type ProcessOutputFetcher

type ProcessOutputFetcher interface {
	// GetProcessOutput fetches the last N lines of output for a process.
	GetProcessOutput(processID string, tailLines int) (string, error)
	// GetScriptOutput fetches the last N lines of output for a script by name.
	GetScriptOutput(scriptName string, tailLines int) (string, error)
}

ProcessOutputFetcher is an interface for fetching process output from the daemon.

type ProcessSummary

type ProcessSummary struct {
	ID        string
	Command   string
	State     string
	HasErrors bool
	Output    string // Last N lines
}

ProcessSummary contains summarized info about a process.

type ProtectedWriter

type ProtectedWriter struct {
	// contains filtered or unexported fields
}

ProtectedWriter filters PTY output to protect the status bar area. It intercepts ANSI sequences that could affect the protected region.

func NewProtectedWriter

func NewProtectedWriter(out io.Writer, width, height int, config FilterConfig) *ProtectedWriter

NewProtectedWriter creates a new PTY output filter.

func (*ProtectedWriter) EnforceScrollRegion

func (pw *ProtectedWriter) EnforceScrollRegion()

EnforceScrollRegion can be called externally to re-apply scroll region protection.

func (*ProtectedWriter) InAltScreen added in v0.12.0

func (pw *ProtectedWriter) InAltScreen() bool

InAltScreen returns whether the child process is currently in the alternate screen buffer.

func (*ProtectedWriter) RequestRedraw

func (pw *ProtectedWriter) RequestRedraw()

RequestRedraw marks that a redraw is needed.

func (*ProtectedWriter) SetSize

func (pw *ProtectedWriter) SetSize(width, height int)

SetSize updates the terminal dimensions.

func (*ProtectedWriter) Stop

func (pw *ProtectedWriter) Stop()

Stop stops the periodic redraw goroutine.

func (*ProtectedWriter) Write

func (pw *ProtectedWriter) Write(p []byte) (n int, err error)

Write filters the PTY output and writes to the underlying writer.

type ProxyInfo

type ProxyInfo struct {
	ID              string
	TargetURL       string
	ListenAddr      string
	HasErrors       bool
	ErrorCount      int
	TunnelURL       string
	TunnelRunning   bool
	LinkedProcessID string // ID of process this proxy targets (if any)
	TailscaleURL    string // Tailscale DNS URL if available (e.g., http://machine.tailnet.ts.net:port)
}

ProxyInfo holds information about a running proxy.

type ProxySummary

type ProxySummary struct {
	ID         string
	TargetURL  string
	ListenAddr string
	ErrorCount int
	PageCount  int
	RecentLogs string // Recent log entries (errors, panel messages, etc.)
}

ProxySummary contains summarized info about a proxy.

type PtyReadWriter added in v0.6.3

type PtyReadWriter interface {
	io.Reader
	io.Writer
}

PtyReadWriter is an interface for interacting with a PTY. This allows both Unix PTY (*os.File) and Windows ConPTY to be used.

type Renderer

type Renderer struct {
	// contains filtered or unexported fields
}

Renderer handles drawing to the terminal.

func NewRenderer

func NewRenderer(out io.Writer, width, height int) *Renderer

NewRenderer creates a new Renderer.

func (*Renderer) ClearCurrentMenu added in v0.7.8

func (r *Renderer) ClearCurrentMenu()

ClearCurrentMenu clears the current menu from screen and resets the region. Use this before transitioning to a different menu type (e.g., Dashboard to submenu).

func (*Renderer) ClearIndicator

func (r *Renderer) ClearIndicator()

ClearIndicator clears the indicator bar.

func (*Renderer) ClearMenu

func (r *Renderer) ClearMenu()

ClearMenu clears all overlay regions (menu and input dialogs). This restores the screen by clearing the tracked regions.

func (*Renderer) ClearScreen

func (r *Renderer) ClearScreen()

ClearScreen clears the entire screen and resets cursor to home.

func (*Renderer) ClearStatusBarMessage added in v0.7.8

func (r *Renderer) ClearStatusBarMessage()

ClearStatusBarMessage clears any message on the status bar. After clearing, the regular indicator should be redrawn.

func (*Renderer) ClearVisible added in v0.12.0

func (r *Renderer) ClearVisible()

ClearVisible clears the visible screen and moves cursor home. Unlike ClearScreen, this preserves the scroll region.

func (*Renderer) DrawDashboard

func (r *Renderer) DrawDashboard(menu Menu, selectedIndex int, status Status)

DrawDashboard draws a niri-style dashboard with centered panels. Panels are stacked vertically in the center with rounded corners, gradient borders, and gaps between them (inspired by niri window manager).

func (*Renderer) DrawIndicator

func (r *Renderer) DrawIndicator(status Status)

DrawIndicator draws the status indicator bar at the bottom of the screen.

func (*Renderer) DrawInput

func (r *Renderer) DrawInput(prompt, value string)

DrawInput draws a text input dialog.

func (*Renderer) DrawMenu

func (r *Renderer) DrawMenu(menu Menu, selectedIndex int)

DrawMenu draws a popup menu in the center of the screen.

func (*Renderer) DrawMenuWithProcesses

func (r *Renderer) DrawMenuWithProcesses(menu Menu, selectedIndex int, processes []ProcessInfo)

DrawMenuWithProcesses draws a popup menu with a process list below it. Deprecated: Use DrawDashboard for a more comprehensive view.

func (*Renderer) DrawPanelView added in v0.12.7

func (r *Renderer) DrawPanelView(panels []PanelItem, activeIndex int, status Status)

DrawPanelView draws a full-screen panel view with a niri-style tab bar at top. Panels are arranged horizontally like niri columns: Ctrl+Left/Right to navigate.

func (*Renderer) DrawProcessOutput

func (r *Renderer) DrawProcessOutput(processID, command, state, output string)

DrawProcessOutput draws the process output viewer on the alt screen using niri-style panel with rounded corners and gradient border.

func (*Renderer) DrawStatusBarMessage added in v0.7.8

func (r *Renderer) DrawStatusBarMessage(message string)

DrawStatusBarMessage draws a message on the status bar at the bottom of the screen. Use this for transient status updates like spinners.

func (*Renderer) EnterAltScreen

func (r *Renderer) EnterAltScreen()

EnterAltScreen switches to the alternate screen buffer. The main screen content is preserved and restored when ExitAltScreen is called.

func (*Renderer) ExitAltScreen

func (r *Renderer) ExitAltScreen()

ExitAltScreen switches back to the main screen buffer. The main screen content that was preserved when EnterAltScreen was called is restored.

func (*Renderer) ResetMenuRegions

func (r *Renderer) ResetMenuRegions()

ResetMenuRegions resets the tracked menu regions without clearing screen content. Use this when relying on SIGWINCH to trigger a full redraw by the child process.

func (*Renderer) SetOutput added in v0.12.11

func (r *Renderer) SetOutput(out io.Writer)

SetOutput changes the writer used for rendering. This is used to route output through a synchronized writer (e.g. OutputGate.WriteDirect) to prevent interleaving with PTY output on the same stdout.

func (*Renderer) SetSize

func (r *Renderer) SetSize(width, height int)

SetSize updates the terminal dimensions.

func (*Renderer) SetVersion added in v0.11.3

func (r *Renderer) SetVersion(version string)

SetVersion sets the version displayed in the dashboard title.

type ScreenBuffer

type ScreenBuffer struct {
	Region  ScreenRegion
	Content [][]rune   // [row][col] - stored content
	Styles  [][]string // [row][col] - ANSI style codes (if we track them)
}

ScreenBuffer stores saved screen content for restoration.

type ScreenManager

type ScreenManager struct {
	// contains filtered or unexported fields
}

ScreenManager handles saving and restoring screen regions. It uses ANSI escape sequences to query and restore terminal content.

func NewScreenManager

func NewScreenManager(out io.Writer, width, height int) *ScreenManager

NewScreenManager creates a new ScreenManager.

func (*ScreenManager) ClearRegion

func (sm *ScreenManager) ClearRegion(region ScreenRegion)

ClearRegion clears a rectangular region without saving.

func (*ScreenManager) DrawOverlay

func (sm *ScreenManager) DrawOverlay(name string, row, col, width, height int, drawFunc func(row, col, width, height int)) ScreenRegion

DrawOverlay draws content at a specific region and tracks it for later clearing. Returns the region for use with RestoreRegion.

func (*ScreenManager) ForceRedraw

func (sm *ScreenManager) ForceRedraw()

ForceRedraw sends a signal to force the underlying application to redraw. This works by simulating a resize event (SIGWINCH).

func (*ScreenManager) RestoreRegion

func (sm *ScreenManager) RestoreRegion(name string)

RestoreRegion restores a previously saved region by overwriting with spaces. This visually clears the region. The underlying application will redraw when it receives SIGWINCH.

func (*ScreenManager) SaveRegion

func (sm *ScreenManager) SaveRegion(name string, region ScreenRegion)

SaveRegion saves the screen content in a region. Since we can't actually read terminal content, we use the alternate screen buffer approach - save cursor, draw overlay, restore when done.

For terminals that don't support reading content, we'll use a different strategy: We'll track what we've drawn and clear it properly.

func (*ScreenManager) SetOutput added in v0.12.11

func (sm *ScreenManager) SetOutput(out io.Writer)

SetOutput changes the writer used for screen output.

func (*ScreenManager) SetSize

func (sm *ScreenManager) SetSize(width, height int)

SetSize updates the terminal dimensions.

type ScreenRegion

type ScreenRegion struct {
	Row    int // 1-indexed top row
	Col    int // 1-indexed left column
	Width  int
	Height int
}

ScreenRegion represents a rectangular region of the terminal screen.

type ScriptInfo added in v0.12.16

type ScriptInfo struct {
	Name       string // Script name (e.g., "dev")
	ProcessID  string // Current process ID (empty if idle)
	State      string // "idle", "starting", "running", "failed", "stopped", "restarting"
	Command    string
	StartCount int64
	FailCount  int64
	LastError  string
}

ScriptInfo holds information about a managed script from the ScriptRegistry. Scripts persist across process lifetimes, so their state is always available.

type StartupLogEntry added in v0.12.15

type StartupLogEntry struct {
	ScriptName string
	Level      string // "info", "warning", "error"
	EventType  string
	Message    string
	Timestamp  time.Time
}

StartupLogEntry holds a startup log entry for display.

type State

type State int

State represents the overlay display state.

const (
	StateHidden        State = iota // No overlay visible, full PTY passthrough
	StateIndicator                  // Status bar visible at bottom
	StateMenu                       // Popup menu active
	StateInput                      // Text input mode
	StateProcessViewer              // Process output viewer (temporary, while key held)
)

type Status

type Status struct {
	DaemonConnected ConnectionStatus
	DaemonPingMs    int64
	Processes       []ProcessInfo
	Scripts         []ScriptInfo
	Proxies         []ProxyInfo
	BrowserSessions []BrowserSession
	RecentErrors    []ErrorInfo
	StartupLog      []StartupLogEntry
	LastUpdate      time.Time
}

Status holds the current system status for display.

type StatusFetcher

type StatusFetcher struct {
	// contains filtered or unexported fields
}

StatusFetcher fetches status from the daemon periodically. It uses a shared daemon.Conn for all requests. By default, it only fetches processes/proxies from the current project directory.

func NewStatusFetcher

func NewStatusFetcher(conn *daemon.Conn, overlay *Overlay, interval time.Duration) *StatusFetcher

NewStatusFetcher creates a new StatusFetcher using a shared connection. It automatically detects the current working directory for scoping.

func (*StatusFetcher) Refresh

func (f *StatusFetcher) Refresh()

Refresh triggers an immediate status refresh.

func (*StatusFetcher) Start

func (f *StatusFetcher) Start(ctx context.Context)

Start starts the status fetcher.

func (*StatusFetcher) Stop

func (f *StatusFetcher) Stop()

Stop stops the status fetcher.

type StatusSummarizer

type StatusSummarizer interface {
	// Summarize aggregates all system data and generates a summary.
	Summarize(ctx context.Context) (*SummaryResult, error)
	// IsAvailable returns true if the AI channel is available.
	IsAvailable() bool
}

StatusSummarizer is an interface for summarizing system status.

type Summarizer

type Summarizer struct {
	// contains filtered or unexported fields
}

Summarizer aggregates system status and uses an AI channel to generate summaries. It uses a shared daemon.Conn for all requests.

func NewSummarizer

func NewSummarizer(conn *daemon.Conn, config SummarizerConfig) *Summarizer

NewSummarizer creates a new Summarizer using a shared connection. For Claude agent, uses CLI mode (required for Claude Code Max plan). For all other agents, automatically uses Anthropic API mode as a fallback since those CLIs may not be available or may require their own subscriptions.

func (*Summarizer) AgentType

func (s *Summarizer) AgentType() aichannel.AgentType

AgentType returns the configured agent type.

func (*Summarizer) IsAvailable

func (s *Summarizer) IsAvailable() bool

IsAvailable returns true if the AI channel is available.

func (*Summarizer) Summarize

func (s *Summarizer) Summarize(ctx context.Context) (*SummaryResult, error)

Summarize aggregates all system data and generates a summary.

type SummarizerConfig

type SummarizerConfig struct {
	// Agent type for AI summarization
	Agent aichannel.AgentType
	// Optional custom command (overrides agent default)
	Command string
	// Optional additional args
	Args []string
	// Timeout for AI response (default 2 minutes)
	Timeout time.Duration
	// DebugOutput is where debug messages are written (defaults to os.Stderr)
	DebugOutput io.Writer
	// ProjectPath is the current project directory for filtering processes/proxies
	ProjectPath string

	// --- API Mode Configuration ---
	// UseAPI forces API mode. For non-Claude agents, API mode is enabled automatically
	// since Claude Code Max plan only supports CLI, while other providers need API keys.
	// Set to true to force API mode even for Claude agent.
	UseAPI bool
	// LLMProvider specifies which provider to use (auto-detected if empty)
	LLMProvider aichannel.LLMProvider
	// APIKey overrides environment variable lookup
	APIKey string
	// Model overrides the provider's default model
	Model string
}

SummarizerConfig configures the Summarizer.

type SummaryResult

type SummaryResult struct {
	Summary     string
	ProcessData []ProcessSummary
	ProxyData   []ProxySummary
	ErrorCount  int
	Duration    time.Duration
}

SummaryResult contains the result of a summarization.

Jump to

Keyboard shortcuts

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