session

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2026 License: AGPL-3.0 Imports: 22 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 CloseAllRepoManagers added in v0.2.2

func CloseAllRepoManagers()

CloseAllRepoManagers closes and removes all per-repo memory managers. Should be called on TUI shutdown.

func GetMemoryManager added in v0.2.2

func GetMemoryManager() *memory.Manager

GetMemoryManager returns the application-wide memory manager, or nil if memory is disabled. It is safe for concurrent use.

func GetOrCreateRepoManager added in v0.2.2

func GetOrCreateRepoManager(slug string) (*memory.Manager, error)

GetOrCreateRepoManager returns (creating if necessary) a Manager for the given repo slug. The repo memory dir is ~/.hivemind/memory/repos/{slug}/. Returns nil if memory is globally disabled (no global manager set).

func GetRepoManagersForPaths added in v0.2.2

func GetRepoManagersForPaths(repoPath, worktreePath string) (repoMgr *memory.Manager, legacyRepoMgr *memory.Manager, repoSlug string, err error)

GetRepoManagersForPaths returns the canonical repo manager and, when in transition mode, a legacy repo manager for read-merge. Canonical slug is derived from repoPath; legacy slug is derived from worktreePath (historic behavior).

func InjectMemoryContext added in v0.2.2

func InjectMemoryContext(worktreePath string, globalMgr *memory.Manager, repoMgr *memory.Manager, count int) error

InjectMemoryContext is the compatibility wrapper used by older call sites.

func InjectMemoryContextForRepo added in v0.2.2

func InjectMemoryContextForRepo(worktreePath, repoName string, globalMgr *memory.Manager, repoMgr *memory.Manager, legacyRepoMgr *memory.Manager, count int) error

InjectMemoryContextForRepo is the primary injection function called on agent start/resume. globalMgr must be non-nil; repo managers may be nil.

func KillInstanceAsync added in v0.2.2

func KillInstanceAsync(inst *Instance)

KillInstanceAsync runs Kill() in a background goroutine. The operation is tracked via closeWg so shutdown can wait for completion.

func SendMemoryAutoWritePrompt added in v0.2.2

func SendMemoryAutoWritePrompt(inst *Instance) (sent bool, err error)

SendMemoryAutoWritePrompt sends a final prompt to the agent asking it to persist session learnings to memory. It is fire-and-forget: we do not wait for the agent to respond. Only called when memory is configured.

Callers are responsible for ensuring the instance is in a valid state before calling this function. Kill() uses CompareAndSwap to guarantee single-caller semantics before invoking this.

Returns sent=true only when the prompt was successfully delivered.

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.

func SetMemoryFactory added in v0.2.2

func SetMemoryFactory(fn func(dir string) (*memory.Manager, error))

SetMemoryFactory stores a function used to create new Managers for per-repo dirs. If not set, GetOrCreateRepoManager falls back to creating a keyword-only (FTS) manager.

func SetMemoryManager added in v0.2.2

func SetMemoryManager(mgr *memory.Manager, count, systemBudget int)

SetMemoryManager configures the memory manager used for startup injection. Called once from app.go when the TUI starts.

func WaitForAllClosing added in v0.2.2

func WaitForAllClosing(timeout time.Duration)

WaitForAllClosing blocks until all in-flight Kill() calls finish or the timeout elapses. Called from the TUI quit handler to avoid exiting while instances are still shutting down.

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
	// SetupScript is an optional shell command to run once after the worktree is ready.
	SetupScript string
	// InitialPrompt is passed to Claude Code via `-p` flag at startup (ephemeral, not persisted).
	InitialPrompt string

	// AutomationID is set when this instance was spawned by an automation.
	// Empty for manually-created instances.
	AutomationID 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) GetWorkingPath added in v0.2.2

func (i *Instance) GetWorkingPath() string

GetWorkingPath returns the working directory for this instance. For instances with a git worktree, this is the worktree path. For main-repo instances, this is the repo path (i.Path).

func (*Instance) HasUpdated

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

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) 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 using `tmux send-keys`, which delivers text reliably through tmux's server rather than raw PTY writes.

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) StartInMainRepo added in v0.2.2

func (i *Instance) StartInMainRepo() error

StartInMainRepo starts the instance directly in the repository directory. Unlike Start(), this does NOT create a git worktree or a new branch.

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.

func (*Instance) WaitForReady added in v0.2.2

func (i *Instance) WaitForReady(timeout time.Duration)

WaitForReady polls the tmux output until it stabilizes, indicating the program has finished initializing and is ready for input. Returns after the output hasn't changed for 2 consecutive checks (~1s of stability), or after the timeout elapses (best-effort, never errors on timeout).

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"`
	AutomationID    string          `json:"automation_id,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
	// AutomationID links this instance to the automation that spawned it.
	AutomationID string
	// SetupScript is an optional shell command to run before the agent starts.
	// It runs in the instance's worktree directory.
	SetupScript string
	// InitialPrompt is passed to Claude Code via `-p` flag at startup.
	// This is more reliable than injecting text after the agent starts.
	InitialPrompt 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
	WorktreeMode TopicWorktreeMode
	AutoYes      bool
	Branch       string
	Path         string
	CreatedAt    time.Time
	Notes        string
	Tasks        []TopicTask
	// 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) IsMainRepo added in v0.2.2

func (t *Topic) IsMainRepo() bool

IsMainRepo reports whether instances in this topic run directly in the repo directory.

func (*Topic) IsSharedWorktree added in v0.2.2

func (t *Topic) IsSharedWorktree() bool

IsSharedWorktree reports whether all instances in this topic share one worktree.

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"`
	WorktreeMode TopicWorktreeMode `json:"worktree_mode,omitempty"`
	// SharedWorktree is kept for backwards-compatible JSON deserialization.
	// New writes use WorktreeMode instead.
	SharedWorktree bool            `json:"shared_worktree,omitempty"`
	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"`
	Notes          string          `json:"notes,omitempty"`
	Tasks          []TopicTask     `json:"tasks,omitempty"`
}

TopicData represents the serializable data of a Topic.

type TopicOptions

type TopicOptions struct {
	Name         string
	WorktreeMode TopicWorktreeMode
	Path         string
}

type TopicTask added in v0.2.2

type TopicTask struct {
	ID   string `json:"id"`
	Text string `json:"text"`
	Done bool   `json:"done"`
}

TopicTask is a single item in the topic's todo list.

func NewTopicTask added in v0.2.2

func NewTopicTask(text string) TopicTask

NewTopicTask creates a TopicTask with a unique ID generated from the current time.

type TopicWorktreeMode added in v0.2.2

type TopicWorktreeMode string

TopicWorktreeMode controls how instances in a topic interact with git.

const (
	// TopicWorktreeModePerInstance gives each instance its own branch + worktree directory.
	TopicWorktreeModePerInstance TopicWorktreeMode = "per_instance"
	// TopicWorktreeModeShared makes all instances share one branch + worktree directory.
	TopicWorktreeModeShared TopicWorktreeMode = "shared"
	// TopicWorktreeModeMainRepo runs instances directly in the repo directory with no worktree.
	TopicWorktreeModeMainRepo TopicWorktreeMode = "main_repo"
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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