Documentation
¶
Index ¶
- Constants
- Variables
- func BucketTimestamps(timestamps []time.Time, window time.Duration, width int) []int
- func Clamp(lo, hi, v int) int
- func ConfigDir() string
- func ConfigPath() string
- func EffectiveCost(model string, costUSD float64, ...) float64
- func EstimateCost(model string, inputTokens, outputTokens, cacheCreation, cacheRead int) float64
- func FormatCost(usd float64) string
- func FormatDuration(d time.Duration) string
- func FormatTokens(n int) string
- func IsActiveActivity(a ActivityKind) bool
- func PadRight(s string, n int) string
- func RenderSparkline(timestamps []time.Time, window time.Duration, width int) string
- func SaveConfig(cfg Config) error
- func ShortName(path string, maxLen int) string
- func SortSessions(sessions []*model.Session)
- type ActivityEntry
- type ActivityKind
- type ActivityTracker
- type Config
- type CursorProvider
- type LiveProvider
- type MultiProvider
- type OpenCodeProvider
- type PiProvider
- type ProjectWatcher
- type SessionDetailView
- type SessionManager
- func (m *SessionManager) ActivityFilter() ActivityKind
- func (m *SessionManager) ActivityFor(sessionID string) ActivityKind
- func (m *SessionManager) QuerySessions(search string, filter ActivityKind) []*model.Session
- func (m *SessionManager) Reload() error
- func (m *SessionManager) SessionDetail(id string) *SessionDetailView
- func (m *SessionManager) SessionName(sessionID string) string
- func (m *SessionManager) Sessions() []*model.Session
- func (m *SessionManager) SetActivityFilter(filter ActivityKind)
- func (m *SessionManager) SetSearchQuery(query string)
- func (m *SessionManager) SetSessionName(sessionID, name string) error
- func (m *SessionManager) SetWindowMinutes(minutes int)
- func (m *SessionManager) StartWatcher() error
- func (m *SessionManager) StopWatcher()
- func (m *SessionManager) UpdateActivities() bool
- func (m *SessionManager) VisibleSessions() []*model.Session
- func (m *SessionManager) WatcherEvents() <-chan struct{}
- func (m *SessionManager) WindowMinutes() int
- type SessionNames
- type SessionProvider
Constants ¶
const ( MinWindowMinutes = 10 MaxWindowMinutes = 480 )
Window minutes bounds.
const ActivityTimeout = 30 * time.Second
ActivityTimeout is the duration a tool-based activity stays visible after the tool finishes, unless replaced by a newer activity.
const SpawningTimeout = 20 * time.Minute
SpawningTimeout is how long a spawning activity (Agent, subagent, task) stays visible without new JSONL entries before falling back to idle. Spawned agents can run for minutes, so this is much longer than ActivityTimeout.
const WaitingGrace = 10 * time.Second
WaitingGrace is the minimum time StatusWaitingForUser must be stable before displaying ActivityWaiting. Claude sometimes writes a text-only assistant message before immediately continuing with a tool_use message (~2s later), which would otherwise cause a brief false "waiting" flash.
const WaitingTimeout = 2 * time.Minute
WaitingTimeout is how long "waiting" stays visible before falling back to idle.
Variables ¶
var AllActivities = []ActivityKind{ "", ActivityIdle, ActivityWaiting, ActivityThinking, ActivityCompacting, ActivityReading, ActivityWriting, ActivityRunning, ActivitySearching, ActivityBrowsing, ActivitySpawning, }
AllActivities returns all ActivityKind values in display order (empty = all).
var SpinnerFrames = []rune{'⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'}
SpinnerFrames contains the Braille spinner animation frames.
Functions ¶
func BucketTimestamps ¶
BucketTimestamps groups timestamps into fixed-width buckets for sparkline display. Returns a slice of counts per bucket.
func ConfigDir ¶
func ConfigDir() string
ConfigDir returns the config directory path (~/.config/lazyagent).
func EffectiveCost ¶
func EffectiveCost(model string, costUSD float64, inputTokens, outputTokens, cacheCreation, cacheRead int) float64
EffectiveCost returns CostUSD if non-zero, otherwise estimates from tokens.
func EstimateCost ¶
EstimateCost estimates API cost based on model and token counts. Supports Anthropic (Claude), Google (Gemini), and OpenAI (GPT) model families.
func FormatDuration ¶
FormatDuration converts a duration to a human-readable "Xs ago" string.
func FormatTokens ¶
FormatTokens formats a token count for display (e.g., 1200 → "1.2k").
func IsActiveActivity ¶
func IsActiveActivity(a ActivityKind) bool
IsActiveActivity returns true for any activity that represents ongoing work (i.e. everything except idle and waiting).
func PadRight ¶
PadRight pads a string with spaces to reach visual width n (rune count), or truncates if longer.
func RenderSparkline ¶
RenderSparkline renders bucketed data as a Unicode sparkline string.
func ShortName ¶
ShortName truncates a file path intelligently, showing "…/parent/child" when needed. maxLen is measured in runes (visual width for monospace display).
func SortSessions ¶
SortSessions sorts sessions by last activity (most recent first).
Types ¶
type ActivityEntry ¶
type ActivityEntry struct {
Kind ActivityKind
LastSeen time.Time
}
ActivityEntry holds a session's current sticky activity state.
type ActivityKind ¶
type ActivityKind string
ActivityKind is the human-readable label shown in the session list.
const ( ActivityIdle ActivityKind = "idle" ActivityWaiting ActivityKind = "waiting" ActivityThinking ActivityKind = "thinking" ActivityCompacting ActivityKind = "compacting" ActivityReading ActivityKind = "reading" ActivityWriting ActivityKind = "writing" ActivityRunning ActivityKind = "running" ActivitySearching ActivityKind = "searching" ActivityBrowsing ActivityKind = "browsing" ActivitySpawning ActivityKind = "spawning" )
func NextActivityFilter ¶
func NextActivityFilter(current ActivityKind) ActivityKind
NextActivityFilter cycles to the next activity filter in AllActivities.
func ResolveActivity ¶
func ResolveActivity(s *model.Session, now time.Time) ActivityKind
ResolveActivity determines the display activity for a session.
Priority:
- Compacting (summary entry written recently).
- Most recent tool in RecentTools within ActivityTimeout.
- StatusWaitingForUser within WaitingTimeout (with grace period).
- LastActivity older than ActivityTimeout → idle.
- Current JSONL status → thinking if Claude is processing, idle otherwise.
func ToolActivity ¶
func ToolActivity(tool string) ActivityKind
ToolActivity maps a tool name to an activity kind. Supports both Claude Code (PascalCase) and pi (snake_case) tool names.
type ActivityTracker ¶
type ActivityTracker struct {
// contains filtered or unexported fields
}
ActivityTracker manages sticky activity states with grace period logic.
func NewActivityTracker ¶
func NewActivityTracker() *ActivityTracker
NewActivityTracker creates a new ActivityTracker.
func (*ActivityTracker) Get ¶
func (t *ActivityTracker) Get(sessionID string) ActivityKind
Get returns the current sticky activity for a session.
type Config ¶
type Config struct {
WindowMinutes int `json:"window_minutes"`
DefaultFilter string `json:"default_filter"`
Editor string `json:"editor"`
LaunchAtLogin bool `json:"launch_at_login"`
Notifications bool `json:"notifications"`
NotifyAfterSec int `json:"notify_after_sec"`
Agents map[string]bool `json:"agents"`
ClaudeDirs []string `json:"claude_dirs,omitempty"`
}
Config holds application settings shared by TUI and GUI.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config with sensible defaults.
func LoadConfig ¶
func LoadConfig() Config
LoadConfig reads the config file, creating it with defaults if missing.
func (Config) AgentEnabled ¶
AgentEnabled returns whether an agent is enabled in config. Defaults to true if the agent key is missing from the map.
type CursorProvider ¶
type CursorProvider struct {
// contains filtered or unexported fields
}
CursorProvider discovers Cursor sessions from store.db files.
func NewCursorProvider ¶
func NewCursorProvider() *CursorProvider
NewCursorProvider creates a CursorProvider.
func (*CursorProvider) DiscoverSessions ¶
func (p *CursorProvider) DiscoverSessions() ([]*model.Session, error)
func (*CursorProvider) RefreshInterval ¶
func (p *CursorProvider) RefreshInterval() time.Duration
func (*CursorProvider) UseWatcher ¶
func (p *CursorProvider) UseWatcher() bool
func (*CursorProvider) WatchDirs ¶
func (p *CursorProvider) WatchDirs() []string
type LiveProvider ¶
type LiveProvider struct {
// contains filtered or unexported fields
}
LiveProvider discovers real Claude Code sessions from disk.
func NewLiveProvider ¶
func NewLiveProvider(claudeDirs []string) *LiveProvider
NewLiveProvider creates a LiveProvider with mtime-based caches. claudeDirs configures which Claude base directories to scan (e.g. ~/.claude). When empty, auto-detection via CLAUDE_CONFIG_DIR / ~/.claude is used.
func (*LiveProvider) DiscoverSessions ¶
func (p *LiveProvider) DiscoverSessions() ([]*model.Session, error)
func (*LiveProvider) RefreshInterval ¶
func (p *LiveProvider) RefreshInterval() time.Duration
func (*LiveProvider) UseWatcher ¶
func (p *LiveProvider) UseWatcher() bool
func (*LiveProvider) WatchDirs ¶
func (p *LiveProvider) WatchDirs() []string
type MultiProvider ¶
type MultiProvider struct {
Providers []SessionProvider
}
MultiProvider merges sessions from multiple providers.
func (MultiProvider) DiscoverSessions ¶
func (m MultiProvider) DiscoverSessions() ([]*model.Session, error)
func (MultiProvider) RefreshInterval ¶
func (m MultiProvider) RefreshInterval() time.Duration
func (MultiProvider) UseWatcher ¶
func (m MultiProvider) UseWatcher() bool
func (MultiProvider) WatchDirs ¶
func (m MultiProvider) WatchDirs() []string
type OpenCodeProvider ¶
type OpenCodeProvider struct {
// contains filtered or unexported fields
}
OpenCodeProvider discovers OpenCode sessions from SQLite.
func NewOpenCodeProvider ¶
func NewOpenCodeProvider() *OpenCodeProvider
NewOpenCodeProvider creates an OpenCodeProvider.
func (*OpenCodeProvider) DiscoverSessions ¶
func (p *OpenCodeProvider) DiscoverSessions() ([]*model.Session, error)
func (*OpenCodeProvider) RefreshInterval ¶
func (p *OpenCodeProvider) RefreshInterval() time.Duration
func (*OpenCodeProvider) UseWatcher ¶
func (p *OpenCodeProvider) UseWatcher() bool
func (*OpenCodeProvider) WatchDirs ¶
func (p *OpenCodeProvider) WatchDirs() []string
type PiProvider ¶
type PiProvider struct {
// contains filtered or unexported fields
}
PiProvider discovers pi coding agent sessions from disk.
func NewPiProvider ¶
func NewPiProvider() *PiProvider
NewPiProvider creates a PiProvider with an mtime-based cache.
func (*PiProvider) DiscoverSessions ¶
func (p *PiProvider) DiscoverSessions() ([]*model.Session, error)
func (*PiProvider) RefreshInterval ¶
func (p *PiProvider) RefreshInterval() time.Duration
func (*PiProvider) UseWatcher ¶
func (p *PiProvider) UseWatcher() bool
func (*PiProvider) WatchDirs ¶
func (p *PiProvider) WatchDirs() []string
type ProjectWatcher ¶
type ProjectWatcher struct {
Events <-chan struct{}
// contains filtered or unexported fields
}
ProjectWatcher watches ~/.claude/projects for JSONL changes using FSEvents. It debounces rapid writes so that a burst of JSONL lines triggers one reload.
func NewProjectWatcher ¶
func NewProjectWatcher(dirs ...string) (*ProjectWatcher, error)
NewProjectWatcher starts an FSEvents watcher on the given directories. Returns nil (no error) if none of the directories exist.
func (*ProjectWatcher) Close ¶
func (w *ProjectWatcher) Close()
Close signals the watcher goroutine to stop and releases resources.
type SessionDetailView ¶
type SessionDetailView struct {
model.Session
Activity ActivityKind
}
SessionDetailView is the full struct for a detail panel.
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager manages session discovery, file watching, and activity tracking.
func NewSessionManager ¶
func NewSessionManager(windowMinutes int, provider SessionProvider) *SessionManager
NewSessionManager creates a new SessionManager with the given provider.
func (*SessionManager) ActivityFilter ¶
func (m *SessionManager) ActivityFilter() ActivityKind
ActivityFilter returns the current activity filter.
func (*SessionManager) ActivityFor ¶
func (m *SessionManager) ActivityFor(sessionID string) ActivityKind
ActivityFor returns the current activity for a session.
func (*SessionManager) QuerySessions ¶
func (m *SessionManager) QuerySessions(search string, filter ActivityKind) []*model.Session
QuerySessions returns sessions filtered by explicit parameters without using the manager's internal filter/search state. Safe for concurrent API use. Empty search/filter means no filtering.
func (*SessionManager) Reload ¶
func (m *SessionManager) Reload() error
Reload discovers sessions via the provider and updates activity states.
func (*SessionManager) SessionDetail ¶
func (m *SessionManager) SessionDetail(id string) *SessionDetailView
SessionDetail returns the full detail view for a session.
func (*SessionManager) SessionName ¶
func (m *SessionManager) SessionName(sessionID string) string
SessionName returns the custom name for a session, or empty string.
func (*SessionManager) Sessions ¶
func (m *SessionManager) Sessions() []*model.Session
Sessions returns all raw sessions (unfiltered).
func (*SessionManager) SetActivityFilter ¶
func (m *SessionManager) SetActivityFilter(filter ActivityKind)
SetActivityFilter sets the activity filter.
func (*SessionManager) SetSearchQuery ¶
func (m *SessionManager) SetSearchQuery(query string)
SetSearchQuery sets the search query.
func (*SessionManager) SetSessionName ¶
func (m *SessionManager) SetSessionName(sessionID, name string) error
SetSessionName stores a custom name for a session.
func (*SessionManager) SetWindowMinutes ¶
func (m *SessionManager) SetWindowMinutes(minutes int)
SetWindowMinutes sets the time window filter, clamped to [MinWindowMinutes, MaxWindowMinutes].
func (*SessionManager) StartWatcher ¶
func (m *SessionManager) StartWatcher() error
StartWatcher starts the file system watcher if the provider supports it.
func (*SessionManager) StopWatcher ¶
func (m *SessionManager) StopWatcher()
StopWatcher stops the file system watcher.
func (*SessionManager) UpdateActivities ¶
func (m *SessionManager) UpdateActivities() bool
UpdateActivities refreshes activity states without reloading from disk. Returns true if any activity state changed. If the provider specifies a RefreshInterval, sessions are re-discovered periodically. Also refreshes session names from disk if modified externally.
func (*SessionManager) VisibleSessions ¶
func (m *SessionManager) VisibleSessions() []*model.Session
VisibleSessions returns sessions filtered by the manager's internal state (time window, activity filter, search query). Used by TUI and tray.
func (*SessionManager) WatcherEvents ¶
func (m *SessionManager) WatcherEvents() <-chan struct{}
WatcherEvents returns the channel for file change notifications, or nil.
func (*SessionManager) WindowMinutes ¶
func (m *SessionManager) WindowMinutes() int
WindowMinutes returns the current time window.
type SessionNames ¶
type SessionNames struct {
// contains filtered or unexported fields
}
SessionNames manages user-defined aliases for sessions. Stored in ~/.config/lazyagent/session-names.json.
func NewSessionNames ¶
func NewSessionNames() *SessionNames
NewSessionNames creates a new SessionNames and loads from disk.
func (*SessionNames) Get ¶
func (sn *SessionNames) Get(sessionID string) string
Get returns the custom name for a session, or empty string.
func (*SessionNames) Refresh ¶
func (sn *SessionNames) Refresh() bool
Refresh re-reads the file from disk if it was modified externally. Returns true if the file was actually reloaded.
func (*SessionNames) Set ¶
func (sn *SessionNames) Set(sessionID, name string) error
Set stores a custom name for a session and persists to disk. Empty name removes the alias.
type SessionProvider ¶
type SessionProvider interface {
// DiscoverSessions returns all available sessions.
DiscoverSessions() ([]*model.Session, error)
// UseWatcher returns whether a file system watcher should be started.
UseWatcher() bool
// RefreshInterval returns how often UpdateActivities should re-discover sessions,
// or 0 to never re-discover (only on explicit Reload or watcher events).
RefreshInterval() time.Duration
// WatchDirs returns directories to watch for file system changes.
WatchDirs() []string
}
SessionProvider abstracts how sessions are discovered.
func BuildProvider ¶
func BuildProvider(agentMode string, cfg Config) SessionProvider
BuildProvider creates a SessionProvider based on agent mode and config. When agentMode is "all", it reads the agents config to decide which providers to include. A specific agentMode (e.g. "claude") overrides the config.