session

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2026 License: AGPL-3.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
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")
)
View Source
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

func ParseActivity(content string, program string) *Activity

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) Attach

func (i *Instance) Attach() (chan struct{}, error)

func (*Instance) GetDiffStats

func (i *Instance) GetDiffStats() *git.DiffStats

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

func (i *Instance) GetPaneContent() (string, error)

GetPaneContent returns the current tmux pane content for activity parsing.

func (*Instance) GetRepoPath

func (i *Instance) GetRepoPath() string

GetRepoPath returns the repo path for this instance, or empty string if not started.

func (*Instance) HasUpdated

func (i *Instance) HasUpdated() (updated bool, hasPrompt bool)

func (*Instance) IsTmuxDead added in v0.2.1

func (i *Instance) IsTmuxDead() bool

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) Kill

func (i *Instance) Kill() error

Kill terminates the instance and cleans up all resources

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

func (i *Instance) Pause() error

Pause stops the tmux session and removes the worktree, preserving the branch

func (*Instance) Paused

func (i *Instance) Paused() bool

func (*Instance) Preview

func (i *Instance) Preview() (string, error)

func (*Instance) PreviewFullHistory

func (i *Instance) PreviewFullHistory() (string, error)

PreviewFullHistory captures the entire tmux pane output including full scrollback history

func (*Instance) RepoName

func (i *Instance) RepoName() (string, error)

func (*Instance) Restart added in v0.2.1

func (i *Instance) Restart() error

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) Resume

func (i *Instance) Resume() error

Resume recreates the worktree and restarts the tmux session

func (*Instance) SendKeys

func (i *Instance) SendKeys(keys string) error

SendKeys sends keys to the tmux session

func (*Instance) SendPrompt

func (i *Instance) SendPrompt(prompt string) error

SendPrompt sends a prompt to the tmux session

func (*Instance) SetPreviewSize

func (i *Instance) SetPreviewSize(width, height int) error

func (*Instance) SetStatus

func (i *Instance) SetStatus(status Status)

func (*Instance) SetTitle

func (i *Instance) SetTitle(title string) error

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

func (i *Instance) Start(firstTimeSetup bool) error

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) Started

func (i *Instance) Started() bool

func (*Instance) TapEnter

func (i *Instance) TapEnter()

TapEnter sends an enter key press to the tmux session if AutoYes is enabled.

func (*Instance) TmuxAlive

func (i *Instance) TmuxAlive() bool

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

func (i *Instance) UpdateDiffStats() error

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

func (s *Storage) DeleteAllInstances() error

DeleteAllInstances removes all stored instances

func (*Storage) DeleteInstance

func (s *Storage) DeleteInstance(title string) error

DeleteInstance removes an instance from storage

func (*Storage) LoadInstances

func (s *Storage) LoadInstances() ([]*Instance, error)

LoadInstances loads the list of instances from disk

func (*Storage) LoadTopics

func (s *Storage) LoadTopics() ([]*Topic, error)

LoadTopics loads the list of topics from disk

func (*Storage) SaveInstances

func (s *Storage) SaveInstances(instances []*Instance) error

SaveInstances saves the list of instances to disk

func (*Storage) SaveTopics

func (s *Storage) SaveTopics(topics []*Topic) error

SaveTopics saves the list of topics to disk

func (*Storage) UpdateInstance

func (s *Storage) UpdateInstance(instance *Instance) error

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
	SharedWorktree bool
	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

func FromTopicData(data TopicData) *Topic

FromTopicData creates a Topic from serialized data.

func NewTopic

func NewTopic(opts TopicOptions) *Topic

func (*Topic) Cleanup

func (t *Topic) Cleanup() error

func (*Topic) GetGitWorktree

func (t *Topic) GetGitWorktree() *git.GitWorktree

func (*Topic) GetWorktreePath

func (t *Topic) GetWorktreePath() string

func (*Topic) Setup

func (t *Topic) Setup() error

func (*Topic) Started

func (t *Topic) Started() bool

func (*Topic) ToTopicData

func (t *Topic) ToTopicData() TopicData

ToTopicData converts a Topic to its serializable form.

type TopicData

type TopicData struct {
	Name           string          `json:"name"`
	SharedWorktree bool            `json:"shared_worktree"`
	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.

type TopicOptions

type TopicOptions struct {
	Name           string
	SharedWorktree bool
	Path           string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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