Documentation
¶
Index ¶
- Variables
- func SendNotification(title, body string)
- type Activity
- type DiffStatsData
- type EmbeddedTerminal
- type GitWorktreeData
- type Instance
- func (i *Instance) Attach() (chan struct{}, error)
- func (i *Instance) GetDiffStats() *git.DiffStats
- func (i *Instance) GetGitWorktree() (*git.GitWorktree, error)
- func (i *Instance) GetPaneContent() (string, error)
- func (i *Instance) GetRepoPath() string
- func (i *Instance) HasUpdated() (updated bool, hasPrompt bool)
- func (i *Instance) IsTmuxDead() bool
- func (i *Instance) Kill() error
- func (i *Instance) NewEmbeddedTerminalForInstance(cols, rows int) (*EmbeddedTerminal, error)
- func (i *Instance) Pause() error
- func (i *Instance) Paused() bool
- func (i *Instance) Preview() (string, error)
- func (i *Instance) PreviewFullHistory() (string, error)
- func (i *Instance) RepoName() (string, error)
- func (i *Instance) Restart() error
- func (i *Instance) Resume() error
- func (i *Instance) SendKeys(keys string) error
- func (i *Instance) SendPrompt(prompt string) error
- func (i *Instance) SetPreviewSize(width, height int) error
- func (i *Instance) SetStatus(status Status)
- func (i *Instance) SetTitle(title string) error
- func (i *Instance) SetTmuxSession(session *tmux.TmuxSession)
- func (i *Instance) Start(firstTimeSetup bool) error
- func (i *Instance) StartInSharedWorktree(worktree *git.GitWorktree, branch string) error
- func (i *Instance) Started() bool
- func (i *Instance) TapEnter()
- func (i *Instance) TmuxAlive() bool
- func (i *Instance) ToInstanceData() InstanceData
- func (i *Instance) UpdateDiffStats() error
- func (i *Instance) UpdateResourceUsage()
- type InstanceData
- type InstanceOptions
- type Status
- type Storage
- func (s *Storage) DeleteAllInstances() error
- func (s *Storage) DeleteInstance(title string) error
- func (s *Storage) LoadInstances() ([]*Instance, error)
- func (s *Storage) LoadTopics() ([]*Topic, error)
- func (s *Storage) SaveInstances(instances []*Instance) error
- func (s *Storage) SaveTopics(topics []*Topic) error
- func (s *Storage) UpdateInstance(instance *Instance) error
- type SubAgentInfo
- type Topic
- type TopicData
- type TopicOptions
Constants ¶
This section is empty.
Variables ¶
var ( ErrInstanceNotStarted = errors.New("instance not started") ErrInstanceAlreadyPaused = errors.New("instance is already paused") ErrBranchCheckedOut = errors.New("branch is currently checked out") ErrTitleEmpty = errors.New("instance title cannot be empty") ErrTitleImmutable = errors.New("cannot change title of a started instance") )
var NotificationsEnabled = true
NotificationsEnabled controls whether desktop notifications are sent. Set from config at startup.
Functions ¶
func SendNotification ¶
func SendNotification(title, body string)
SendNotification sends a desktop notification. It is fire-and-forget: the command is started but we do not wait for it to finish.
Types ¶
type Activity ¶
type Activity struct {
// Action is the type of activity (e.g. "editing", "running", "reading", "searching", "working").
Action string
// Detail provides additional context (e.g. filename or command).
Detail string
// Timestamp is when this activity was detected.
Timestamp time.Time
}
Activity represents what an agent is currently doing.
func ParseActivity ¶
ParseActivity parses the pane content to extract the current activity. It scans the last ~30 lines for known patterns. program is the agent name (e.g. "claude", "aider"). Returns nil if no activity is detected.
type DiffStatsData ¶
type DiffStatsData struct {
Added int `json:"added"`
Removed int `json:"removed"`
Content string `json:"content"`
}
DiffStatsData represents the serializable data of a DiffStats
type EmbeddedTerminal ¶
type EmbeddedTerminal struct {
// contains filtered or unexported fields
}
EmbeddedTerminal provides a zero-latency embedded terminal view.
Architecture: creates a dedicated `tmux attach-session` PTY, reads its output stream directly through a VT emulator (charmbracelet/x/vt), and renders from the emulator's in-memory screen buffer. No subprocess calls per frame.
Data flow:
PTY stdout → readLoop → emu.Write() (updates screen state) PTY stdin ← responseLoop ← emu.Read() (terminal query responses) User keys → SendKey → PTY stdin (zero latency, bypasses emulator) Display ← Render() ← renderLoop cache (decoupled from emulator lock)
Signal-driven rendering: readLoop signals dataReady after each Write(), renderLoop wakes immediately and snapshots the screen into the cache, then signals renderReady so the display tick fires without fixed sleeps.
func NewEmbeddedTerminal ¶
func NewEmbeddedTerminal(sessionName string, cols, rows int) (*EmbeddedTerminal, error)
NewEmbeddedTerminal creates an embedded terminal connected to a tmux session. It spawns a dedicated `tmux attach-session` process with its own PTY, reads the output stream through a VT emulator, and renders from memory.
func (*EmbeddedTerminal) Close ¶
func (t *EmbeddedTerminal) Close()
Close shuts down the terminal: stops all goroutines, closes the PTY, and kills the tmux attach process.
func (*EmbeddedTerminal) Render ¶
func (t *EmbeddedTerminal) Render() (string, bool)
Render returns the latest cached screen content. This never blocks on the emulator lock — it only touches the lightweight cacheMu for microseconds. Returns ("", false) if nothing changed since the last call.
func (*EmbeddedTerminal) Resize ¶
func (t *EmbeddedTerminal) Resize(cols, rows int)
Resize updates the terminal dimensions.
func (*EmbeddedTerminal) SendKey ¶
func (t *EmbeddedTerminal) SendKey(data []byte) error
SendKey writes raw bytes directly to the PTY.
func (*EmbeddedTerminal) WaitForRender ¶
func (t *EmbeddedTerminal) WaitForRender(timeout time.Duration)
WaitForRender blocks until new rendered content is available in the cache, or until the timeout expires. Used by the Bubble Tea display tick to wake immediately when content changes instead of polling on a fixed interval.
type GitWorktreeData ¶
type GitWorktreeData struct {
RepoPath string `json:"repo_path"`
WorktreePath string `json:"worktree_path"`
SessionName string `json:"session_name"`
BranchName string `json:"branch_name"`
BaseCommitSHA string `json:"base_commit_sha"`
}
GitWorktreeData represents the serializable data of a GitWorktree
type Instance ¶
type Instance struct {
// Title is the title of the instance.
Title string
// Path is the path to the workspace.
Path string
// Branch is the branch of the instance.
Branch string
// Status is the status of the instance.
Status Status
// Program is the program to run in the instance.
Program string
// Height is the height of the instance.
Height int
// Width is the width of the instance.
Width int
// CreatedAt is the time the instance was created.
CreatedAt time.Time
// UpdatedAt is the time the instance was last updated.
UpdatedAt time.Time
// AutoYes is true if the instance should automatically press enter when prompted.
AutoYes bool
// SkipPermissions is true if the instance should run Claude with --dangerously-skip-permissions.
SkipPermissions bool
// TopicName is the name of the topic this instance belongs to (empty = ungrouped).
TopicName string
// Role is the agent's role (coder, reviewer, architect, tester, etc.).
// Set when created via brain action. Empty for manually created instances.
Role string
// ParentTitle is the title of the agent that spawned this instance via brain create_instance.
// Empty for manually created (top-level) instances.
ParentTitle string
// BrainChildCount is the number of brain-spawned child instances (set by TUI, not persisted).
BrainChildCount int
// LoadingStage tracks the current startup progress. Exported so the UI can read it.
LoadingStage int
// LoadingTotal is the total number of startup stages.
LoadingTotal int
// LoadingMessage describes the current loading step.
LoadingMessage string
// Notified is true when the instance finished (Running→Ready) and the user
// hasn't selected it yet. Cleared when the user selects this instance.
Notified bool
// LastActiveAt is set whenever the instance is marked as Running.
LastActiveAt time.Time
// PromptDetected is true when the instance's program is waiting for user input.
// Reset to false when the instance resumes running. Used by the sidebar to
// persistently show a running indicator without flickering.
PromptDetected bool
// CPUPercent is the current CPU usage of the instance's process tree.
CPUPercent float64
// MemMB is the current memory usage in megabytes (aggregated across process tree).
MemMB float64
// SubAgentCount is the number of detected sub-agent processes (e.g. spawned Claude Code tasks).
SubAgentCount int
// SubAgents holds details of each detected sub-agent process.
SubAgents []SubAgentInfo
// LastActivity is the most recently detected agent activity (ephemeral, not persisted).
LastActivity *Activity
// contains filtered or unexported fields
}
Instance is a running instance of claude code.
func FromInstanceData ¶
func FromInstanceData(data InstanceData) (*Instance, error)
FromInstanceData creates a new Instance from serialized data
func NewInstance ¶
func NewInstance(opts InstanceOptions) (*Instance, error)
func (*Instance) GetDiffStats ¶
GetDiffStats returns the current git diff statistics
func (*Instance) GetGitWorktree ¶
func (i *Instance) GetGitWorktree() (*git.GitWorktree, error)
GetGitWorktree returns the git worktree for the instance
func (*Instance) GetPaneContent ¶
GetPaneContent returns the current tmux pane content for activity parsing.
func (*Instance) GetRepoPath ¶
GetRepoPath returns the repo path for this instance, or empty string if not started.
func (*Instance) HasUpdated ¶
func (*Instance) IsTmuxDead ¶ added in v0.2.1
IsTmuxDead returns true if the tmux session has been detected as dead. The UI uses this to show a "session ended" message instead of the preview.
func (*Instance) NewEmbeddedTerminalForInstance ¶
func (i *Instance) NewEmbeddedTerminalForInstance(cols, rows int) (*EmbeddedTerminal, error)
NewEmbeddedTerminalForInstance creates an embedded terminal emulator connected to this instance's tmux PTY for zero-latency interactive focus mode.
func (*Instance) Pause ¶
Pause stops the tmux session and removes the worktree, preserving the branch
func (*Instance) PreviewFullHistory ¶
PreviewFullHistory captures the entire tmux pane output including full scrollback history
func (*Instance) Restart ¶ added in v0.2.1
Restart recreates the tmux session for an instance whose agent process has exited (tmuxDead). If the worktree directory still exists it is reused; otherwise the worktree is recreated from the branch (like Resume).
func (*Instance) SendPrompt ¶
SendPrompt sends a prompt to the tmux session
func (*Instance) SetPreviewSize ¶
func (*Instance) SetTitle ¶
SetTitle sets the title of the instance. Returns an error if the instance has started. We cant change the title once it's been used for a tmux session etc.
func (*Instance) SetTmuxSession ¶
func (i *Instance) SetTmuxSession(session *tmux.TmuxSession)
SetTmuxSession sets the tmux session for testing purposes
func (*Instance) Start ¶
firstTimeSetup is true if this is a new instance. Otherwise, it's one loaded from storage.
func (*Instance) StartInSharedWorktree ¶
func (i *Instance) StartInSharedWorktree(worktree *git.GitWorktree, branch string) error
StartInSharedWorktree starts the instance using a topic's shared worktree. Unlike Start(), this does NOT create a new git worktree — it uses the one provided.
func (*Instance) TapEnter ¶
func (i *Instance) TapEnter()
TapEnter sends an enter key press to the tmux session if AutoYes is enabled.
func (*Instance) TmuxAlive ¶
TmuxAlive returns true if the tmux session is alive. This is a sanity check before attaching.
func (*Instance) ToInstanceData ¶
func (i *Instance) ToInstanceData() InstanceData
ToInstanceData converts an Instance to its serializable form
func (*Instance) UpdateDiffStats ¶
UpdateDiffStats updates the git diff statistics for this instance
func (*Instance) UpdateResourceUsage ¶
func (i *Instance) UpdateResourceUsage()
UpdateResourceUsage queries the process tree for CPU and memory usage, and detects sub-agent processes via tmux windows.
Claude Code's tmux spawn backend creates sub-agents as additional windows (index > 0) in the same tmux session. We use tmux list-windows for detection and the process tree for resource metrics per window.
Values are kept from the previous tick if the query fails, so the UI doesn't flicker.
type InstanceData ¶
type InstanceData struct {
Title string `json:"title"`
Path string `json:"path"`
Branch string `json:"branch"`
Status Status `json:"status"`
Height int `json:"height"`
Width int `json:"width"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
AutoYes bool `json:"auto_yes"`
SkipPermissions bool `json:"skip_permissions"`
TopicName string `json:"topic_name,omitempty"`
Role string `json:"role,omitempty"`
ParentTitle string `json:"parent_title,omitempty"`
Program string `json:"program"`
Worktree GitWorktreeData `json:"worktree"`
DiffStats DiffStatsData `json:"diff_stats"`
}
InstanceData represents the serializable data of an Instance
type InstanceOptions ¶
type InstanceOptions struct {
// Title is the title of the instance.
Title string
// Path is the path to the workspace.
Path string
// Program is the program to run in the instance (e.g. "claude", "aider --model ollama_chat/gemma3:1b")
Program string
// If AutoYes is true, then
AutoYes bool
// SkipPermissions enables --dangerously-skip-permissions for Claude instances.
SkipPermissions bool
// TopicName assigns this instance to a topic.
TopicName string
// Role is the agent's role (coder, reviewer, architect, tester, etc.).
Role string
// ParentTitle is the title of the parent agent that spawned this instance.
ParentTitle string
}
Options for creating a new instance
type Status ¶
type Status int
const ( // Running is the status when the instance is running and claude is working. Running Status = iota // Ready is if the claude instance is ready to be interacted with (waiting for user input). Ready // Loading is if the instance is loading (if we are starting it up or something). Loading // Paused is if the instance is paused (worktree removed but branch preserved). Paused )
type Storage ¶
type Storage struct {
// contains filtered or unexported fields
}
Storage handles saving and loading instances using the state interface
func NewStorage ¶
func NewStorage(state config.StateManager) (*Storage, error)
NewStorage creates a new storage instance
func (*Storage) DeleteAllInstances ¶
DeleteAllInstances removes all stored instances
func (*Storage) DeleteInstance ¶
DeleteInstance removes an instance from storage
func (*Storage) LoadInstances ¶
LoadInstances loads the list of instances from disk
func (*Storage) LoadTopics ¶
LoadTopics loads the list of topics from disk
func (*Storage) SaveInstances ¶
SaveInstances saves the list of instances to disk
func (*Storage) SaveTopics ¶
SaveTopics saves the list of topics to disk
func (*Storage) UpdateInstance ¶
UpdateInstance updates an existing instance in storage
type SubAgentInfo ¶ added in v0.2.1
type SubAgentInfo struct {
PID int
Name string // process name (e.g. "node")
Activity string // what the sub-agent is doing (e.g. "running git diff", "thinking")
CPU float64 // CPU% for this sub-agent's process tree
MemMB float64 // memory in MB for this sub-agent's process tree
}
SubAgentInfo holds metadata about a detected sub-agent process.
type Topic ¶
type Topic struct {
Name string
AutoYes bool
Branch string
Path string
CreatedAt time.Time
// contains filtered or unexported fields
}
Topic groups related instances, optionally sharing a single git worktree.
func FromTopicData ¶
FromTopicData creates a Topic from serialized data.
func NewTopic ¶
func NewTopic(opts TopicOptions) *Topic
func (*Topic) GetGitWorktree ¶
func (t *Topic) GetGitWorktree() *git.GitWorktree
func (*Topic) GetWorktreePath ¶
func (*Topic) ToTopicData ¶
ToTopicData converts a Topic to its serializable form.
type TopicData ¶
type TopicData struct {
Name string `json:"name"`
AutoYes bool `json:"auto_yes"`
Branch string `json:"branch,omitempty"`
Path string `json:"path"`
CreatedAt time.Time `json:"created_at"`
Worktree GitWorktreeData `json:"worktree,omitempty"`
}
TopicData represents the serializable data of a Topic.