session

package
v0.0.0-...-06885da Latest Latest
Warning

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

Go to latest
Published: Apr 4, 2026 License: AGPL-3.0 Imports: 42 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ReasonApprovalPending    = queue.ReasonApprovalPending
	ReasonInputRequired      = queue.ReasonInputRequired
	ReasonErrorState         = queue.ReasonErrorState
	ReasonTestsFailing       = queue.ReasonTestsFailing
	ReasonIdleTimeout        = queue.ReasonIdleTimeout
	ReasonTaskComplete       = queue.ReasonTaskComplete
	ReasonUncommittedChanges = queue.ReasonUncommittedChanges
	ReasonIdle               = queue.ReasonIdle
	ReasonStale              = queue.ReasonStale
	ReasonWaitingForUser     = queue.ReasonWaitingForUser
)
View Source
const (
	PriorityUrgent = queue.PriorityUrgent
	PriorityHigh   = queue.PriorityHigh
	PriorityMedium = queue.PriorityMedium
	PriorityLow    = queue.PriorityLow
)
View Source
const (
	MinTitleLength = 1
	MaxTitleLength = 32
)

Title validation constants

View Source
const (
	// DefaultBufferSize is 10MB of in-memory buffer
	DefaultBufferSize = 10 * 1024 * 1024
)
View Source
const MaxTagLength = 50

MaxTagLength is the maximum allowed length for a single tag.

Variables

View Source
var (
	ErrInvalidTitleLength = errors.New("title must be 1-32 characters")
	ErrInvalidTitleChars  = errors.New("title contains invalid characters")
	ErrDuplicateTitle     = errors.New("a session with this title already exists")
	ErrCannotRestart      = errors.New("session cannot be restarted in current state")
)

Title validation errors

View Source
var ContextCloudSession = ContextOptions{
	LoadCloud:    true,
	LoadActivity: true,
	LoadUI:       true,
	LoadTags:     true,
}

ContextCloudSession loads contexts for cloud/API sessions. Optimized for remote sessions that don't have local git/filesystem context. Memory usage: ~1-2 KB per session

View Source
var ContextDetailView = ContextOptions{
	LoadGit:           true,
	LoadFilesystem:    true,
	LoadTerminal:      true,
	LoadUI:            true,
	LoadActivity:      true,
	LoadWorktree:      true,
	LoadDiffStats:     true,
	LoadTags:          true,
	LoadClaudeSession: true,
}

ContextDetailView loads most contexts for detail panel. Comprehensive data for session detail views, excluding heavy diff content. Memory usage: ~10-20 KB per session

View Source
var ContextForReviewQueue = ContextOptions{
	LoadGit:       true,
	LoadActivity:  true,
	LoadWorktree:  true,
	LoadDiffStats: true,
	LoadTags:      true,
}

ContextForReviewQueue loads data needed for review queue operations. Focused on git context and change indicators. Memory usage: ~3-5 KB per session

View Source
var ContextForSearch = ContextOptions{
	LoadGit:      true,
	LoadTags:     true,
	LoadActivity: true,
}

ContextForSearch loads contexts needed for search operations. Includes tags and basic metadata for efficient filtering. Memory usage: ~1-2 KB per session

View Source
var ContextFull = ContextOptions{
	LoadGit:           true,
	LoadFilesystem:    true,
	LoadTerminal:      true,
	LoadUI:            true,
	LoadActivity:      true,
	LoadCloud:         true,
	LoadWorktree:      true,
	LoadDiffStats:     true,
	LoadDiffContent:   true,
	LoadTags:          true,
	LoadClaudeSession: true,
}

ContextFull loads all contexts and child data (expensive). Complete data including full diff content. Use sparingly. Memory usage: Can be 1-25 MB per session depending on diff size

View Source
var ContextMinimal = ContextOptions{}

ContextMinimal loads only core session data with no contexts. Use this for basic operations that only need session metadata. Memory usage: ~500 bytes per session

View Source
var ContextTerminalView = ContextOptions{
	LoadTerminal:  true,
	LoadGit:       true,
	LoadUI:        true,
	LoadActivity:  true,
	LoadDiffStats: true,
}

ContextTerminalView loads contexts needed for terminal preview. Includes terminal output and git diffs for preview panes. Memory usage: ~5-10 KB per session (varies with terminal output size)

View Source
var ContextUIView = ContextOptions{
	LoadUI:       true,
	LoadActivity: true,
	LoadGit:      true,
	LoadTags:     true,
}

ContextUIView loads contexts needed for list/card display. Optimized for responsive UI rendering with essential context only. Memory usage: ~2-3 KB per session

View Source
var DefaultRepoPathManager = NewRepoPathManager()

DefaultRepoPathManager is the default instance used for GitHub URL resolution.

View Source
var DeterminePriority = queue.DeterminePriority

DeterminePriority re-export

View Source
var LoadDiffOnly = LoadOptions{
	LoadWorktree:    true,
	LoadDiffStats:   true,
	LoadDiffContent: true,
}

LoadDiffOnly loads only diff-related data, useful for preview panes.

Deprecated: For new code, use ContextTerminalView.WithDiffContent() with GetSession/ListSessions.

View Source
var LoadForReviewQueue = LoadOptions{
	LoadWorktree:      true,
	LoadDiffStats:     true,
	LoadDiffContent:   false,
	LoadTags:          true,
	LoadClaudeSession: false,
}

LoadForReviewQueue loads data needed for review queue operations.

Deprecated: For new code, use ContextForReviewQueue with GetSession/ListSessions.

View Source
var LoadFull = LoadOptions{
	LoadWorktree:      true,
	LoadDiffStats:     true,
	LoadDiffContent:   true,
	LoadTags:          true,
	LoadClaudeSession: true,
}

LoadFull loads all available data including full diff content. Use this for detail views where you need complete information. Memory usage: Can be 1-25 MB per session depending on diff size

Deprecated: For new code, use ContextFull with GetSession/ListSessions.

View Source
var LoadMinimal = LoadOptions{}

LoadMinimal loads only the core session fields without any child data. Use this when you only need session metadata (title, path, status, etc.)

Deprecated: For new code, use ContextMinimal with GetSession/ListSessions.

View Source
var LoadSummary = LoadOptions{
	LoadWorktree:      true,
	LoadDiffStats:     true,
	LoadDiffContent:   false,
	LoadTags:          true,
	LoadClaudeSession: true,
}

LoadSummary loads lightweight child data suitable for list views. This includes everything except the heavy diff content. Memory usage: ~1-2 KB per session

Deprecated: For new code, use ContextUIView with GetSession/ListSessions.

Functions

func CanTransition

func CanTransition(from, to Status) bool

CanTransition returns true if transitioning from -> to is a valid state transition.

func CreateFullSyncDeltaFromRawContent

func CreateFullSyncDeltaFromRawContent(rawContent string, cursorRow, cursorCol, rows, cols int) *sessionv1.TerminalData

CreateFullSyncDeltaFromRawContent creates a full-sync delta from raw tmux content. This is used when sending initial pane content to clients over WebSocket. The raw content is processed into a proper delta to avoid xterm.js parsing errors.

func GetMainRepoPath

func GetMainRepoPath(path string) (string, error)

GetMainRepoPath uses git rev-parse --git-common-dir to get the main repo path. This is more reliable than parsing the .git file.

func IsGitHubURL

func IsGitHubURL(input string) bool

IsGitHubURL returns true if the input looks like a GitHub URL or shorthand.

func RollbackMigration

func RollbackMigration(backupPath, sqlitePath string) error

RollbackMigration restores the JSON backup and removes the SQLite database

func ValidateEntMigration

func ValidateEntMigration(jsonPath, entDBPath string) error

ValidateEntMigration verifies that all sessions from JSON were successfully migrated to Ent

Types

type ActivityTracking

type ActivityTracking struct {
	// LastTerminalUpdate is when the terminal output was last updated
	LastTerminalUpdate time.Time `json:"last_terminal_update,omitempty"`

	// LastMeaningfulOutput is when meaningful (non-noise) output was detected
	LastMeaningfulOutput time.Time `json:"last_meaningful_output,omitempty"`

	// LastViewed is when the session was last viewed by the user
	LastViewed time.Time `json:"last_viewed,omitempty"`

	// LastAcknowledged is when the user last acknowledged session output
	LastAcknowledged time.Time `json:"last_acknowledged,omitempty"`

	// LastOutputSignature is a hash/signature of the last output for deduplication
	LastOutputSignature string `json:"last_output_signature,omitempty"`

	// LastAddedToQueue is when the session was last added to the review queue
	LastAddedToQueue time.Time `json:"last_added_to_queue,omitempty"`
}

ActivityTracking represents the activity tracking data for a session. This includes timestamps for various events and output tracking.

func (*ActivityTracking) HasRecentActivity

func (a *ActivityTracking) HasRecentActivity(within time.Duration) bool

HasRecentActivity returns true if there has been activity within the specified duration

func (*ActivityTracking) IsEmpty

func (a *ActivityTracking) IsEmpty() bool

IsEmpty returns true if the ActivityTracking has no meaningful data

type ApprovalAutomation

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

ApprovalAutomation orchestrates automatic approval handling.

func NewApprovalAutomation

func NewApprovalAutomation(sessionName string, controller *ClaudeController) *ApprovalAutomation

NewApprovalAutomation creates a new approval automation system.

func (*ApprovalAutomation) GetDetector

func (aa *ApprovalAutomation) GetDetector() *detection.ApprovalDetector

GetDetector returns the approval detector for configuration.

func (*ApprovalAutomation) GetPendingApprovals

func (aa *ApprovalAutomation) GetPendingApprovals() []*PendingApproval

GetPendingApprovals returns all approvals awaiting user response.

func (*ApprovalAutomation) GetPolicyEngine

func (aa *ApprovalAutomation) GetPolicyEngine() *PolicyEngine

GetPolicyEngine returns the policy engine for configuration.

func (*ApprovalAutomation) GetSessionName

func (aa *ApprovalAutomation) GetSessionName() string

GetSessionName returns the session name.

func (*ApprovalAutomation) IsRunning

func (aa *ApprovalAutomation) IsRunning() bool

IsRunning returns whether the automation is currently running.

func (*ApprovalAutomation) RespondToApproval

func (aa *ApprovalAutomation) RespondToApproval(requestID string, approved bool, userInput string, options ApprovalAutomationOptions) error

RespondToApproval processes a user response to a pending approval.

func (*ApprovalAutomation) Start

Start begins the approval automation processing loop.

func (*ApprovalAutomation) Stop

func (aa *ApprovalAutomation) Stop() error

Stop halts the approval automation system.

func (*ApprovalAutomation) Subscribe

func (aa *ApprovalAutomation) Subscribe(subscriberID string) <-chan ApprovalEvent

Subscribe creates a subscription for approval events.

func (*ApprovalAutomation) Unsubscribe

func (aa *ApprovalAutomation) Unsubscribe(subscriberID string)

Unsubscribe removes a subscription.

type ApprovalAutomationOptions

type ApprovalAutomationOptions struct {
	AutoExecute     bool          // Automatically execute approved commands
	UserTimeout     time.Duration // Time to wait for user response
	ProcessingDelay time.Duration // Delay between processing approvals
	MaxQueueSize    int           // Maximum pending approvals
	EnableAuditLog  bool          // Log all approval actions
}

ApprovalAutomationOptions configures approval automation behavior.

func DefaultApprovalAutomationOptions

func DefaultApprovalAutomationOptions() ApprovalAutomationOptions

DefaultApprovalAutomationOptions returns sensible defaults.

type ApprovalEvent

type ApprovalEvent struct {
	Type      ApprovalEventType
	Request   *detection.ApprovalRequest
	Decision  *PolicyDecision
	Timestamp time.Time
	Details   string
}

ApprovalEvent represents an event in the approval automation system.

type ApprovalEventType

type ApprovalEventType string

ApprovalEventType categorizes approval events.

const (
	EventDetected      ApprovalEventType = "detected"
	EventAutoApproved  ApprovalEventType = "auto_approved"
	EventAutoRejected  ApprovalEventType = "auto_rejected"
	EventAwaitingUser  ApprovalEventType = "awaiting_user"
	EventUserApproved  ApprovalEventType = "user_approved"
	EventUserRejected  ApprovalEventType = "user_rejected"
	EventExpired       ApprovalEventType = "expired"
	EventExecuted      ApprovalEventType = "executed"
	EventExecutionFail ApprovalEventType = "execution_failed"
)

type ApprovalMetadata

type ApprovalMetadata struct {
	ApprovalID string
	ToolName   string
	ToolInput  map[string]interface{}
	Cwd        string
	Orphaned   bool
}

ApprovalMetadata holds metadata about a pending approval for enriching review queue items.

type ApprovalMetadataProvider

type ApprovalMetadataProvider interface {
	// GetApprovalMetadataBySession returns approval metadata for the given session ID.
	// Returns nil if no approvals exist for the session.
	GetApprovalMetadataBySession(sessionID string) []ApprovalMetadata
}

ApprovalMetadataProvider provides approval metadata for enriching review queue items. This interface decouples the poller (session package) from the ApprovalStore (services package).

type ApprovalPolicy

type ApprovalPolicy struct {
	ID              string                   `json:"id"`
	Name            string                   `json:"name"`
	Description     string                   `json:"description"`
	ApprovalTypes   []detection.ApprovalType `json:"approval_types"` // Types this policy applies to
	Enabled         bool                     `json:"enabled"`
	Priority        int                      `json:"priority"`   // Higher priority policies checked first
	Conditions      []PolicyCondition        `json:"conditions"` // All must match
	Action          PolicyAction             `json:"action"`     // What to do when matched
	TimeRestriction *TimeRestriction         `json:"time_restriction,omitempty"`
	UsageLimit      *UsageLimit              `json:"usage_limit,omitempty"`
	CreatedAt       time.Time                `json:"created_at"`
	UpdatedAt       time.Time                `json:"updated_at"`
	// contains filtered or unexported fields
}

ApprovalPolicy defines a rule for automatic approval.

func CreateBusinessHoursPolicy

func CreateBusinessHoursPolicy() *ApprovalPolicy

CreateBusinessHoursPolicy creates a policy that only applies during business hours.

func CreateNoDestructivePolicy

func CreateNoDestructivePolicy() *ApprovalPolicy

CreateNoDestructivePolicy creates a policy for rejecting destructive commands.

func CreateSafeCommandPolicy

func CreateSafeCommandPolicy() *ApprovalPolicy

CreateSafeCommandPolicy creates a policy for automatically approving safe commands.

type AttentionReason

type AttentionReason = queue.AttentionReason

AttentionReason re-export

func AttentionReasonFromDetected

func AttentionReasonFromDetected(detected detection.DetectedStatus) AttentionReason

AttentionReasonFromDetected maps a DetectedStatus to the AttentionReason that should be used when adding the session to the review queue. Returns the zero AttentionReason (empty string) when no attention is needed for that status.

type AvailableTargets

type AvailableTargets struct {
	VCSType         string
	Bookmarks       []BookmarkTarget
	RecentRevisions []RevisionTarget
	Worktrees       []WorktreeTarget
}

AvailableTargets contains the available workspace switch targets

type BookmarkTarget

type BookmarkTarget struct {
	Name       string
	RevisionID string
	IsRemote   bool
}

BookmarkTarget represents a bookmark/branch as a switch target

type Cell

type Cell struct {
	Char  rune
	Style CellStyle
}

Cell represents a single terminal cell with character and attributes

type CellStyle

type CellStyle struct {
	FgColor   string
	BgColor   string
	Bold      bool
	Italic    bool
	Underline bool
	Reverse   bool
}

CellStyle represents text styling attributes

func DefaultStyle

func DefaultStyle() CellStyle

DefaultStyle returns a default cell style

type CircularBuffer

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

CircularBuffer is a thread-safe circular buffer with automatic disk fallback when the in-memory buffer fills up. This prevents memory overflow while maintaining a history of PTY output for status detection and debugging.

func NewCircularBuffer

func NewCircularBuffer(size int) *CircularBuffer

NewCircularBuffer creates a new circular buffer with the specified size in bytes. When the buffer fills up, old data is automatically overwritten (circular behavior).

func (*CircularBuffer) Cap

func (cb *CircularBuffer) Cap() int

Cap returns the total capacity of the buffer.

func (*CircularBuffer) Clear

func (cb *CircularBuffer) Clear()

Clear resets the buffer to empty state.

func (*CircularBuffer) Close

func (cb *CircularBuffer) Close() error

Close releases resources used by the circular buffer. If disk fallback is enabled, it removes the disk file.

func (*CircularBuffer) DisableDiskFallback

func (cb *CircularBuffer) DisableDiskFallback() error

DisableDiskFallback disables disk fallback and removes the disk file.

func (*CircularBuffer) EnableDiskFallback

func (cb *CircularBuffer) EnableDiskFallback(diskPath string) error

EnableDiskFallback enables automatic disk fallback when buffer is full. The diskPath parameter specifies where to store overflow data. This feature is currently a placeholder for future implementation.

func (*CircularBuffer) GetAll

func (cb *CircularBuffer) GetAll() []byte

GetAll returns all data currently in the buffer. Returns a copy to prevent concurrent modification issues.

func (*CircularBuffer) GetRecent

func (cb *CircularBuffer) GetRecent(n int) []byte

GetRecent returns the last n bytes from the buffer. If n is larger than the buffer size or the available data, returns all available data.

func (*CircularBuffer) Len

func (cb *CircularBuffer) Len() int

Len returns the number of bytes currently in the buffer.

func (*CircularBuffer) Write

func (cb *CircularBuffer) Write(data []byte) (int, error)

Write appends data to the circular buffer. If the buffer is full, the oldest data is overwritten. This is an O(1) operation.

func (*CircularBuffer) WriteTo

func (cb *CircularBuffer) WriteTo(w io.Writer) (int64, error)

WriteTo implements io.WriterTo interface for efficient streaming.

type ClaudeCommandBuilder

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

ClaudeCommandBuilder constructs Claude CLI commands with session resumption support. This builder intelligently adds the --resume flag when appropriate to maintain conversation continuity across session restarts.

func NewClaudeCommandBuilder

func NewClaudeCommandBuilder(baseProgram string, claudeSession *ClaudeSessionData) *ClaudeCommandBuilder

NewClaudeCommandBuilder creates a new command builder for constructing Claude CLI commands. Parameters:

  • baseProgram: The base command string (e.g., "claude", "claude --model sonnet", "aider")
  • claudeSession: Optional session data for resumption support (can be nil)

func (*ClaudeCommandBuilder) Build

func (b *ClaudeCommandBuilder) Build() string

Build constructs the final command string with session resumption if applicable. The method follows these rules:

  1. If not a Claude command, returns baseProgram unchanged
  2. If no session data exists, returns baseProgram unchanged
  3. If session ID is invalid UUID, returns baseProgram unchanged with warning
  4. If all conditions met, returns "baseProgram --resume <sessionId>"

type ClaudeController

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

ClaudeController provides a high-level API for controlling Claude instances. It orchestrates all the underlying components (queue, executor, history, streams).

func NewClaudeController

func NewClaudeController(instance *Instance) (*ClaudeController, error)

NewClaudeController creates a new controller for the given instance.

func (*ClaudeController) CancelCommand

func (cc *ClaudeController) CancelCommand(commandID string) error

CancelCommand cancels a pending command in the queue.

func (*ClaudeController) ClearHistory

func (cc *ClaudeController) ClearHistory() error

ClearHistory removes all command history entries.

func (*ClaudeController) ClearQueue

func (cc *ClaudeController) ClearQueue() error

ClearQueue removes all pending commands from the queue.

func (*ClaudeController) GetCommandHistory

func (cc *ClaudeController) GetCommandHistory(limit int) []*HistoryEntry

GetCommandHistory returns recent command history.

func (*ClaudeController) GetCommandStatus

func (cc *ClaudeController) GetCommandStatus(commandID string) (*Command, error)

GetCommandStatus retrieves the current status of a command.

func (*ClaudeController) GetCurrentCommand

func (cc *ClaudeController) GetCurrentCommand() *Command

GetCurrentCommand returns the currently executing command, if any.

func (*ClaudeController) GetCurrentStatus

func (cc *ClaudeController) GetCurrentStatus() (detection.DetectedStatus, string)

GetCurrentStatus detects the current status of the Claude instance.

func (*ClaudeController) GetExecutionOptions

func (cc *ClaudeController) GetExecutionOptions() ExecutionOptions

GetExecutionOptions returns current execution options.

func (*ClaudeController) GetHistoryStatistics

func (cc *ClaudeController) GetHistoryStatistics() HistoryStatistics

GetHistoryStatistics returns statistics about command execution.

func (*ClaudeController) GetIdleDuration

func (cc *ClaudeController) GetIdleDuration() time.Duration

GetIdleDuration returns how long the session has been idle.

func (*ClaudeController) GetIdleState

func (cc *ClaudeController) GetIdleState() (detection.IdleState, time.Time)

GetIdleState returns the current idle state with timing information. Returns the state and the timestamp of last activity.

func (*ClaudeController) GetIdleStateInfo

func (cc *ClaudeController) GetIdleStateInfo() detection.IdleStateInfo

GetIdleStateInfo returns comprehensive idle state information.

func (*ClaudeController) GetInstance

func (cc *ClaudeController) GetInstance() *Instance

GetInstance returns the underlying Instance.

func (*ClaudeController) GetQueuedCommands

func (cc *ClaudeController) GetQueuedCommands() []*Command

GetQueuedCommands returns all commands currently in the queue.

func (*ClaudeController) GetRecentOutput

func (cc *ClaudeController) GetRecentOutput(bytes int) []byte

GetRecentOutput returns recent output from the PTY buffer.

func (*ClaudeController) GetSessionName

func (cc *ClaudeController) GetSessionName() string

GetSessionName returns the session name for this controller.

func (*ClaudeController) IsActive

func (cc *ClaudeController) IsActive() bool

IsActive returns whether the Claude instance is actively processing commands.

func (*ClaudeController) IsIdle

func (cc *ClaudeController) IsIdle() bool

IsIdle returns whether the Claude instance is currently idle (waiting for input). This uses pattern-based detection on terminal content.

func (*ClaudeController) IsStarted

func (cc *ClaudeController) IsStarted() bool

IsStarted returns whether the controller is currently started.

func (*ClaudeController) SearchHistory

func (cc *ClaudeController) SearchHistory(query string) []*HistoryEntry

SearchHistory searches command history by text.

func (*ClaudeController) SendCommand

func (cc *ClaudeController) SendCommand(text string, priority int) (string, error)

SendCommand sends a command to the Claude instance (queued execution).

func (*ClaudeController) SendCommandImmediate

func (cc *ClaudeController) SendCommandImmediate(text string) (*ExecutionResult, error)

SendCommandImmediate sends a command for immediate execution (bypasses queue).

func (*ClaudeController) SetExecutionOptions

func (cc *ClaudeController) SetExecutionOptions(options ExecutionOptions)

SetExecutionOptions updates command execution options.

func (*ClaudeController) Start

func (cc *ClaudeController) Start(ctx context.Context) error

Start initializes all components and begins background operations (streaming, command execution). This is the single entry point for starting the controller - no separate Initialize() call needed.

func (*ClaudeController) Stop

func (cc *ClaudeController) Stop() error

Stop stops all background operations and cleans up resources.

func (*ClaudeController) Subscribe

func (cc *ClaudeController) Subscribe(subscriberID string) (<-chan ResponseChunk, error)

Subscribe creates a new subscription to the response stream.

func (*ClaudeController) Unsubscribe

func (cc *ClaudeController) Unsubscribe(subscriberID string) error

Unsubscribe removes a subscription from the response stream.

type ClaudeConversationMessage

type ClaudeConversationMessage struct {
	Role      string
	Content   string
	Timestamp time.Time
	Model     string
}

ClaudeConversationMessage represents a message in a conversation

type ClaudeHistoryEntry

type ClaudeHistoryEntry struct {
	// ID is the unique identifier for this conversation
	ID string `json:"id"`
	// Name is the conversation title
	Name string `json:"name"`
	// Project is the project/directory path
	Project string `json:"project"`
	// CreatedAt is when the conversation started
	CreatedAt time.Time `json:"created_at"`
	// UpdatedAt is when the conversation was last updated
	UpdatedAt time.Time `json:"updated_at"`
	// Model is the Claude model used (e.g., "claude-sonnet-4")
	Model string `json:"model"`
	// MessageCount is the number of messages in the conversation
	MessageCount int `json:"message_count"`
}

ClaudeHistoryEntry represents a single entry from Claude's history.jsonl file

type ClaudeSession

type ClaudeSession struct {
	ID             string    `json:"id"`
	ConversationID string    `json:"conversation_id"`
	ProjectName    string    `json:"project_name"`
	LastActive     time.Time `json:"last_active"`
	WorkingDir     string    `json:"working_dir"`
	IsActive       bool      `json:"is_active"`
}

ClaudeSession represents a Claude Code session

type ClaudeSessionData

type ClaudeSessionData struct {
	SessionID      string            `json:"session_id,omitempty"`      // Claude Code session identifier
	ConversationID string            `json:"conversation_id,omitempty"` // Conversation thread ID
	ProjectName    string            `json:"project_name,omitempty"`    // Project name in Claude Code
	LastAttached   time.Time         `json:"last_attached,omitempty"`   // When this session was last used
	Settings       ClaudeSettings    `json:"settings,omitempty"`        // User preferences for Claude Code
	Metadata       map[string]string `json:"metadata,omitempty"`        // Additional session metadata
}

ClaudeSessionData represents Claude Code session information

type ClaudeSessionHistory

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

ClaudeSessionHistory manages access to Claude session history

func NewClaudeSessionHistory

func NewClaudeSessionHistory(historyPath string) (*ClaudeSessionHistory, error)

NewClaudeSessionHistory creates a new ClaudeSessionHistory instance

func NewClaudeSessionHistoryFromClaudeDir

func NewClaudeSessionHistoryFromClaudeDir() (*ClaudeSessionHistory, error)

NewClaudeSessionHistoryFromClaudeDir creates a ClaudeSessionHistory from ~/.claude directory

func (*ClaudeSessionHistory) Count

func (sh *ClaudeSessionHistory) Count() int

Count returns the total number of history entries

func (*ClaudeSessionHistory) GetAll

GetAll returns all history entries, sorted by UpdatedAt descending

func (*ClaudeSessionHistory) GetByID

GetByID returns a specific history entry by ID

func (*ClaudeSessionHistory) GetByProject

func (sh *ClaudeSessionHistory) GetByProject(projectPath string) []ClaudeHistoryEntry

GetByProject returns all history entries for a specific project path

func (*ClaudeSessionHistory) GetMessagesFromConversationFile

func (sh *ClaudeSessionHistory) GetMessagesFromConversationFile(sessionID string) ([]ClaudeConversationMessage, error)

GetMessagesFromConversationFile reads all messages from a conversation file

func (*ClaudeSessionHistory) GetProjects

func (sh *ClaudeSessionHistory) GetProjects() []string

GetProjects returns a list of unique project paths from history

func (*ClaudeSessionHistory) LastLoadTime

func (sh *ClaudeSessionHistory) LastLoadTime() time.Time

LastLoadTime returns when the history was last loaded from disk

func (*ClaudeSessionHistory) Reload

func (sh *ClaudeSessionHistory) Reload() error

Reload reloads the history by scanning all conversation files in ~/.claude/projects/

func (*ClaudeSessionHistory) Search

func (sh *ClaudeSessionHistory) Search(query string) []ClaudeHistoryEntry

Search searches history entries by name or project path

type ClaudeSessionManager

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

ClaudeSessionManager handles Claude Code session detection and management

func NewClaudeSessionManager

func NewClaudeSessionManager() *ClaudeSessionManager

NewClaudeSessionManager creates a new Claude session manager

func (*ClaudeSessionManager) AttachToSession

func (csm *ClaudeSessionManager) AttachToSession(sessionID string) error

AttachToSession attempts to attach to a Claude Code session

func (*ClaudeSessionManager) CreateSessionData

func (csm *ClaudeSessionManager) CreateSessionData(session ClaudeSession, settings ClaudeSettings) ClaudeSessionData

CreateSessionData creates ClaudeSessionData from a detected session

func (*ClaudeSessionManager) DetectAvailableSessions

func (csm *ClaudeSessionManager) DetectAvailableSessions() ([]ClaudeSession, error)

DetectAvailableSessions scans for available Claude Code sessions

func (*ClaudeSessionManager) FindSessionByProject

func (csm *ClaudeSessionManager) FindSessionByProject(projectPath string) ([]ClaudeSession, error)

FindSessionByProject finds Claude sessions that match a given project/working directory

func (*ClaudeSessionManager) GetSessionByID

func (csm *ClaudeSessionManager) GetSessionByID(sessionID string) (*ClaudeSession, error)

GetSessionByID retrieves a specific Claude session by ID

type ClaudeSettings

type ClaudeSettings struct {
	AutoReattach          bool   `json:"auto_reattach"`           // Automatically reattach to last session on resume
	PreferredSessionName  string `json:"preferred_session_name"`  // Preferred session naming pattern
	CreateNewOnMissing    bool   `json:"create_new_on_missing"`   // Create new session if previous one is missing
	ShowSessionSelector   bool   `json:"show_session_selector"`   // Show session selection menu on resume
	SessionTimeoutMinutes int    `json:"session_timeout_minutes"` // Consider sessions stale after this time
}

ClaudeSettings contains user preferences for Claude Code integration

type CloudContext

type CloudContext struct {
	// Provider is the cloud provider name (aws/gcp/azure/custom)
	Provider string `json:"provider,omitempty"`

	// Region is the cloud region/zone
	Region string `json:"region,omitempty"`

	// InstanceID is the cloud instance identifier
	InstanceID string `json:"instance_id,omitempty"`

	// APIEndpoint is the API endpoint URL for the cloud service
	APIEndpoint string `json:"api_endpoint,omitempty"`

	// APIKeyRef is a reference to secure key storage (not the actual key)
	APIKeyRef string `json:"api_key_ref,omitempty"`

	// CloudSessionID is the cloud provider's session identifier
	CloudSessionID string `json:"cloud_session_id,omitempty"`

	// ConversationID is the conversation/thread identifier for AI services
	ConversationID string `json:"conversation_id,omitempty"`
}

CloudContext represents the cloud-related context for a session. This includes cloud provider details, region, and API configuration.

func (*CloudContext) IsConfigured

func (c *CloudContext) IsConfigured() bool

IsConfigured returns true if the CloudContext has minimum required configuration

func (*CloudContext) IsEmpty

func (c *CloudContext) IsEmpty() bool

IsEmpty returns true if the CloudContext has no meaningful data

type Command

type Command struct {
	ID        string        `json:"id"`
	Text      string        `json:"text"`
	Priority  int           `json:"priority"`  // Higher priority = executed first
	Timestamp time.Time     `json:"timestamp"` // When the command was queued
	Status    CommandStatus `json:"status"`
	Result    string        `json:"result,omitempty"`     // Command result/output
	Error     string        `json:"error,omitempty"`      // Error message if failed
	StartTime time.Time     `json:"start_time,omitempty"` // When execution started
	EndTime   time.Time     `json:"end_time,omitempty"`   // When execution finished
}

Command represents a command to be executed in a Claude instance.

type CommandExecutor

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

CommandExecutor executes commands by writing to PTY and monitoring responses.

func NewCommandExecutor

func NewCommandExecutor(
	sessionName string,
	ptyAccess *PTYAccess,
	responseStream *ResponseStream,
	statusDetector *detection.StatusDetector,
	queue *CommandQueue,
) *CommandExecutor

NewCommandExecutor creates a new command executor for the given session.

func NewCommandExecutorWithOptions

func NewCommandExecutorWithOptions(
	sessionName string,
	ptyAccess *PTYAccess,
	responseStream *ResponseStream,
	statusDetector *detection.StatusDetector,
	queue *CommandQueue,
	options ExecutionOptions,
) *CommandExecutor

NewCommandExecutorWithOptions creates a command executor with custom options.

func (*CommandExecutor) ExecuteImmediate

func (ce *CommandExecutor) ExecuteImmediate(cmd *Command) (*ExecutionResult, error)

ExecuteImmediate executes a command immediately without using the queue. This is useful for interactive commands that need immediate execution.

func (*CommandExecutor) GetCurrentCommand

func (ce *CommandExecutor) GetCurrentCommand() *Command

GetCurrentCommand returns the currently executing command, or nil if none.

func (*CommandExecutor) GetOptions

func (ce *CommandExecutor) GetOptions() ExecutionOptions

GetOptions returns the current execution options.

func (*CommandExecutor) GetSessionName

func (ce *CommandExecutor) GetSessionName() string

GetSessionName returns the session name for this executor.

func (*CommandExecutor) IsExecuting

func (ce *CommandExecutor) IsExecuting() bool

IsExecuting returns whether the executor is currently running.

func (*CommandExecutor) SetOptions

func (ce *CommandExecutor) SetOptions(options ExecutionOptions)

SetOptions updates execution options (only applies to future commands).

func (*CommandExecutor) SetResultCallback

func (ce *CommandExecutor) SetResultCallback(callback func(*ExecutionResult))

SetResultCallback sets a callback function to be invoked after each command execution.

func (*CommandExecutor) Start

func (ce *CommandExecutor) Start(ctx context.Context) error

Start begins processing commands from the queue.

func (*CommandExecutor) Stop

func (ce *CommandExecutor) Stop() error

Stop stops the command executor and waits for completion.

type CommandHistory

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

CommandHistory tracks all executed commands with persistence.

func NewCommandHistory

func NewCommandHistory(sessionName string) *CommandHistory

NewCommandHistory creates a new command history tracker.

func NewCommandHistoryWithPersistence

func NewCommandHistoryWithPersistence(sessionName string, persistDir string) (*CommandHistory, error)

NewCommandHistoryWithPersistence creates a command history with persistence enabled.

func (*CommandHistory) Add

func (ch *CommandHistory) Add(entry *HistoryEntry) error

Add adds a command execution to the history.

func (*CommandHistory) AddFromResult

func (ch *CommandHistory) AddFromResult(result *ExecutionResult) error

AddFromResult creates and adds a history entry from an execution result.

func (*CommandHistory) Clear

func (ch *CommandHistory) Clear() error

Clear removes all history entries.

func (*CommandHistory) Count

func (ch *CommandHistory) Count() int

Count returns the total number of entries in history.

func (*CommandHistory) GetAll

func (ch *CommandHistory) GetAll() []*HistoryEntry

GetAll returns all history entries (most recent first).

func (*CommandHistory) GetByCommandID

func (ch *CommandHistory) GetByCommandID(commandID string) []*HistoryEntry

GetByCommandID returns all history entries for a specific command ID.

func (*CommandHistory) GetByStatus

func (ch *CommandHistory) GetByStatus(status CommandStatus) []*HistoryEntry

GetByStatus returns entries with a specific command status.

func (*CommandHistory) GetByTimeRange

func (ch *CommandHistory) GetByTimeRange(start, end time.Time) []*HistoryEntry

GetByTimeRange returns entries within the specified time range.

func (*CommandHistory) GetFailed

func (ch *CommandHistory) GetFailed() []*HistoryEntry

GetFailed returns all failed command executions.

func (*CommandHistory) GetMaxEntries

func (ch *CommandHistory) GetMaxEntries() int

GetMaxEntries returns the current maximum entries limit.

func (*CommandHistory) GetPersistPath

func (ch *CommandHistory) GetPersistPath() string

GetPersistPath returns the path where history is persisted.

func (*CommandHistory) GetRecent

func (ch *CommandHistory) GetRecent(n int) []*HistoryEntry

GetRecent returns the N most recent history entries.

func (*CommandHistory) GetSessionName

func (ch *CommandHistory) GetSessionName() string

GetSessionName returns the session name for this history.

func (*CommandHistory) GetStatistics

func (ch *CommandHistory) GetStatistics() HistoryStatistics

GetStatistics returns statistics about command execution history.

func (*CommandHistory) GetSuccessful

func (ch *CommandHistory) GetSuccessful() []*HistoryEntry

GetSuccessful returns all successful command executions.

func (*CommandHistory) Load

func (ch *CommandHistory) Load() error

Load restores the history from disk.

func (*CommandHistory) Save

func (ch *CommandHistory) Save() error

Save persists the history to disk.

func (*CommandHistory) Search

func (ch *CommandHistory) Search(query string) []*HistoryEntry

Search searches history entries by command text (case-insensitive substring match).

func (*CommandHistory) SetMaxEntries

func (ch *CommandHistory) SetMaxEntries(max int)

SetMaxEntries sets the maximum number of entries to keep in history. Setting to 0 means unlimited. If current entries exceed the new limit, oldest entries are removed.

func (*CommandHistory) SetPersistPath

func (ch *CommandHistory) SetPersistPath(path string)

SetPersistPath sets the path for history persistence.

type CommandQueue

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

CommandQueue manages a priority queue of commands with persistence.

func NewCommandQueue

func NewCommandQueue(sessionName string) *CommandQueue

NewCommandQueue creates a new command queue for the given session.

func NewCommandQueueWithPersistence

func NewCommandQueueWithPersistence(sessionName string, persistDir string) (*CommandQueue, error)

NewCommandQueueWithPersistence creates a command queue with persistence enabled. The queue state will be saved to the specified directory.

func (*CommandQueue) Cancel

func (cq *CommandQueue) Cancel(id string) error

Cancel marks a command as cancelled and removes it from the queue. Returns an error if the command is not found or is already executing.

func (*CommandQueue) Clear

func (cq *CommandQueue) Clear() error

Clear removes all commands from the queue.

func (*CommandQueue) Dequeue

func (cq *CommandQueue) Dequeue() *Command

Dequeue removes and returns the highest priority command from the queue. Returns nil if the queue is empty.

func (*CommandQueue) Enqueue

func (cq *CommandQueue) Enqueue(cmd *Command) error

Enqueue adds a command to the queue with the specified priority. Higher priority commands are executed first.

func (*CommandQueue) Get

func (cq *CommandQueue) Get(id string) (*Command, error)

Get retrieves a command by ID without removing it from the queue.

func (*CommandQueue) GetPersistPath

func (cq *CommandQueue) GetPersistPath() string

GetPersistPath returns the path where the queue state is persisted.

func (*CommandQueue) IsEmpty

func (cq *CommandQueue) IsEmpty() bool

IsEmpty returns true if the queue is empty.

func (*CommandQueue) Len

func (cq *CommandQueue) Len() int

Len returns the number of commands in the queue.

func (*CommandQueue) List

func (cq *CommandQueue) List() []*Command

List returns all commands currently in the queue. The returned slice is a copy to prevent external modification.

func (*CommandQueue) ListByStatus

func (cq *CommandQueue) ListByStatus(status CommandStatus) []*Command

ListByStatus returns all commands with the specified status.

func (*CommandQueue) Load

func (cq *CommandQueue) Load() error

Load restores the queue state from disk.

func (*CommandQueue) NotifyChannel

func (cq *CommandQueue) NotifyChannel() <-chan struct{}

NotifyChannel returns a channel that receives a notification when commands are added. This can be used to wait for new commands without polling.

func (*CommandQueue) Peek

func (cq *CommandQueue) Peek() *Command

Peek returns the highest priority command without removing it. Returns nil if the queue is empty.

func (*CommandQueue) Save

func (cq *CommandQueue) Save() error

Save persists the queue state to disk.

func (*CommandQueue) SetPersistPath

func (cq *CommandQueue) SetPersistPath(path string)

SetPersistPath sets the path for queue persistence.

func (*CommandQueue) Update

func (cq *CommandQueue) Update(cmd *Command) error

Update updates the status and metadata of a command.

type CommandStatus

type CommandStatus int

CommandStatus represents the current status of a command in the queue.

const (
	CommandPending CommandStatus = iota
	CommandExecuting
	CommandCompleted
	CommandFailed
	CommandCancelled
)

func (CommandStatus) String

func (cs CommandStatus) String() string

String returns a human-readable string for the command status.

type ContextOptions

type ContextOptions struct {
	// Context loading flags
	LoadGit        bool // Git repository context (branch, commit, remotes)
	LoadFilesystem bool // Filesystem context (directory state, file counts)
	LoadTerminal   bool // Terminal context (output, command history)
	LoadUI         bool // UI context (position, focus state, expanded/collapsed)
	LoadActivity   bool // Activity context (last active, duration, events)
	LoadCloud      bool // Cloud context (API sessions, remote state)

	// Child data loading flags (from existing LoadOptions)
	LoadWorktree      bool // Git worktree data
	LoadDiffStats     bool // Diff statistics (added/removed counts)
	LoadDiffContent   bool // Full diff content (heavy - only load when needed)
	LoadTags          bool // Session tags
	LoadClaudeSession bool // Claude Code session data
}

ContextOptions specifies which optional contexts to load when querying sessions. This enables optimized queries that only load the data needed for each use case.

func FromLoadOptions

func FromLoadOptions(lo LoadOptions) ContextOptions

FromLoadOptions creates ContextOptions from the legacy LoadOptions type. This provides backward compatibility when migrating existing code.

func (ContextOptions) AnyChildDataLoaded

func (o ContextOptions) AnyChildDataLoaded() bool

AnyChildDataLoaded returns true if any child data is configured to load.

func (ContextOptions) AnyContextLoaded

func (o ContextOptions) AnyContextLoaded() bool

AnyContextLoaded returns true if any context is configured to load.

func (ContextOptions) Merge

Merge combines two ContextOptions, returning options that load the union of both. This is useful for combining requirements from multiple components.

func (ContextOptions) String

func (o ContextOptions) String() string

String returns a human-readable description of what will be loaded.

func (ContextOptions) ToLoadOptions

func (o ContextOptions) ToLoadOptions() LoadOptions

ToLoadOptions converts ContextOptions to the legacy LoadOptions type. This provides backward compatibility with existing code.

func (ContextOptions) WithActivity

func (o ContextOptions) WithActivity() ContextOptions

WithActivity returns a copy of options with activity context loading enabled.

func (ContextOptions) WithCloud

func (o ContextOptions) WithCloud() ContextOptions

WithCloud returns a copy of options with cloud context loading enabled.

func (ContextOptions) WithDiffContent

func (o ContextOptions) WithDiffContent() ContextOptions

WithDiffContent returns a copy of options with diff content loading enabled.

func (ContextOptions) WithFilesystem

func (o ContextOptions) WithFilesystem() ContextOptions

WithFilesystem returns a copy of options with filesystem context loading enabled.

func (ContextOptions) WithGit

func (o ContextOptions) WithGit() ContextOptions

WithGit returns a copy of options with git context loading enabled.

func (ContextOptions) WithTags

func (o ContextOptions) WithTags() ContextOptions

WithTags returns a copy of options with tag loading enabled.

func (ContextOptions) WithTerminal

func (o ContextOptions) WithTerminal() ContextOptions

WithTerminal returns a copy of options with terminal context loading enabled.

func (ContextOptions) WithUI

func (o ContextOptions) WithUI() ContextOptions

WithUI returns a copy of options with UI context loading enabled.

func (ContextOptions) WithoutDiffContent

func (o ContextOptions) WithoutDiffContent() ContextOptions

WithoutDiffContent returns a copy of options with diff content loading disabled.

func (ContextOptions) WithoutTags

func (o ContextOptions) WithoutTags() ContextOptions

WithoutTags returns a copy of options with tag loading disabled.

type ControllerManager

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

ControllerManager owns the ClaudeController and InstanceStatusManager references that were previously bare fields on Instance.

Instance keeps thin wrapper methods (with lifecycle guards) that delegate here. ControllerManager itself has no knowledge of Instance lifecycle; it only manages the controller and status-manager references.

Note: claudeSession is intentionally NOT included here because it is a rich data object with complex lifecycle management (persistence, re-attachment, session selection) that is tightly coupled to Instance business logic. It remains a direct field on Instance for now.

func (*ControllerManager) GetController

func (cm *ControllerManager) GetController() *ClaudeController

GetController returns the current ClaudeController (may be nil).

func (*ControllerManager) GetStatusManager

func (cm *ControllerManager) GetStatusManager() *InstanceStatusManager

GetStatusManager returns the current InstanceStatusManager (may be nil).

func (*ControllerManager) HasController

func (cm *ControllerManager) HasController() bool

HasController reports whether a ClaudeController has been registered.

func (*ControllerManager) RegisterController

func (cm *ControllerManager) RegisterController(title string, controller *ClaudeController)

RegisterController wires a new controller into the status manager and stores it. Any existing controller is stopped first.

func (*ControllerManager) SetController

func (cm *ControllerManager) SetController(c *ClaudeController)

SetController replaces the controller. Callers are responsible for stopping the old controller before calling this.

func (*ControllerManager) SetStatusManager

func (cm *ControllerManager) SetStatusManager(m *InstanceStatusManager)

SetStatusManager replaces the status manager.

func (*ControllerManager) StopAndClearController

func (cm *ControllerManager) StopAndClearController()

StopAndClearController stops the controller (if running) and clears the reference.

func (*ControllerManager) UnregisterController

func (cm *ControllerManager) UnregisterController(title string)

UnregisterController stops and clears the controller, and removes it from the status manager.

type DiffStatsData

type DiffStatsData struct {
	Added   int    `json:"added"`
	Removed int    `json:"removed"`
	Content string `json:"-"` // Excluded from serialization - generated on-demand
}

DiffStatsData represents the serializable data of a DiffStats Note: Content is excluded from JSON serialization to reduce state file size. Diffs are generated on-demand via GetSessionDiff RPC when needed.

type DiscoveryMode

type DiscoveryMode int

DiscoveryMode controls what instances are discovered and how they can be interacted with

const (
	// DiscoveryModeManaged discovers only squad-managed sessions (default, safest)
	DiscoveryModeManaged DiscoveryMode = iota

	// DiscoveryModeExtended discovers managed + external instances in read-only mode
	DiscoveryModeExtended

	// DiscoveryModeFull discovers all instances with attach capability (power user mode)
	DiscoveryModeFull
)

func ParseDiscoveryMode

func ParseDiscoveryMode(s string) DiscoveryMode

ParseDiscoveryMode parses a string into a DiscoveryMode

func (DiscoveryMode) String

func (dm DiscoveryMode) String() string

type EntRepository

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

EntRepository implements the Repository interface using Ent ORM as the storage backend. It provides type-safe database operations with automatic schema migrations.

func NewEntRepository

func NewEntRepository(opts ...RepositoryOption) (*EntRepository, error)

NewEntRepository creates a new Ent repository with the given options. The database will be initialized with the schema if it doesn't exist.

func (*EntRepository) Close

func (r *EntRepository) Close() error

Close performs cleanup and releases resources

func (*EntRepository) Create

func (r *EntRepository) Create(ctx context.Context, data InstanceData) error

Create inserts a new session into the database

func (*EntRepository) CreateSession

func (r *EntRepository) CreateSession(ctx context.Context, session *Session) error

CreateSession creates a new session from the Session domain model. Stub: not yet implemented; use InstanceData-based methods instead.

func (*EntRepository) Delete

func (r *EntRepository) Delete(ctx context.Context, title string) error

Delete removes a session from the database by title

func (*EntRepository) Get

func (r *EntRepository) Get(ctx context.Context, title string) (*InstanceData, error)

Get retrieves a single session by title

func (*EntRepository) GetSession

func (r *EntRepository) GetSession(ctx context.Context, title string, opts ContextOptions) (*Session, error)

GetSession retrieves a session using the new Session domain model. Stub: not yet implemented; use InstanceData-based methods instead.

func (*EntRepository) GetWithOptions

func (r *EntRepository) GetWithOptions(ctx context.Context, title string, options LoadOptions) (*InstanceData, error)

GetWithOptions retrieves a single session with selective child data loading. EntRepository: Delegates to Get with full loading.

func (*EntRepository) List

func (r *EntRepository) List(ctx context.Context) ([]InstanceData, error)

List retrieves all sessions from the database

func (*EntRepository) ListByStatus

func (r *EntRepository) ListByStatus(ctx context.Context, status Status) ([]InstanceData, error)

ListByStatus retrieves sessions filtered by status

func (*EntRepository) ListByStatusWithOptions

func (r *EntRepository) ListByStatusWithOptions(ctx context.Context, status Status, options LoadOptions) ([]InstanceData, error)

ListByStatusWithOptions retrieves sessions filtered by status with selective loading. EntRepository: Delegates to ListByStatus with full loading.

func (*EntRepository) ListByTag

func (r *EntRepository) ListByTag(ctx context.Context, tagName string) ([]InstanceData, error)

ListByTag retrieves sessions that have a specific tag

func (*EntRepository) ListByTagWithOptions

func (r *EntRepository) ListByTagWithOptions(ctx context.Context, tag string, options LoadOptions) ([]InstanceData, error)

ListByTagWithOptions retrieves sessions with a specific tag with selective loading. EntRepository: Delegates to ListByTag with full loading.

func (*EntRepository) ListSessions

func (r *EntRepository) ListSessions(ctx context.Context, opts ContextOptions) ([]*Session, error)

ListSessions retrieves all sessions using the new Session domain model. Stub: not yet implemented; use InstanceData-based methods instead.

func (*EntRepository) ListWithOptions

func (r *EntRepository) ListWithOptions(ctx context.Context, options LoadOptions) ([]InstanceData, error)

ListWithOptions retrieves all sessions with selective child data loading. EntRepository: Delegates to List with full loading.

func (*EntRepository) Update

func (r *EntRepository) Update(ctx context.Context, data InstanceData) error

Update modifies an existing session in the database

func (*EntRepository) UpdateSession

func (r *EntRepository) UpdateSession(ctx context.Context, session *Session) error

UpdateSession updates an existing session using the Session domain model. Stub: not yet implemented; use InstanceData-based methods instead.

func (*EntRepository) UpdateTimestamps

func (r *EntRepository) UpdateTimestamps(ctx context.Context, title string, lastTerminalUpdate, lastMeaningfulOutput time.Time, lastOutputSignature string) error

UpdateTimestamps efficiently updates only timestamp fields for a session

type ErrDuplicateTag

type ErrDuplicateTag struct {
	Tag string
}

ErrDuplicateTag is returned when adding a tag that already exists.

func (ErrDuplicateTag) Error

func (e ErrDuplicateTag) Error() string

type ErrInvalidTransition

type ErrInvalidTransition struct {
	From Status
	To   Status
}

ErrInvalidTransition is returned when a status transition is not allowed by the state machine defined in state_machine.go.

func (ErrInvalidTransition) Error

func (e ErrInvalidTransition) Error() string

type ErrTagTooLong

type ErrTagTooLong struct {
	Tag    string
	MaxLen int
}

ErrTagTooLong is returned when a tag exceeds the maximum length.

func (ErrTagTooLong) Error

func (e ErrTagTooLong) Error() string

type ExecutionOptions

type ExecutionOptions struct {
	// Timeout for command execution (0 = no timeout)
	Timeout time.Duration
	// MaxOutputSize limits captured output (0 = unlimited)
	MaxOutputSize int
	// StatusCheckInterval for polling status detector
	StatusCheckInterval time.Duration
	// TerminalStatuses are statuses that indicate command completion
	TerminalStatuses []detection.DetectedStatus
}

ExecutionOptions configures command execution behavior.

func DefaultExecutionOptions

func DefaultExecutionOptions() ExecutionOptions

DefaultExecutionOptions returns sensible defaults for command execution.

type ExecutionResult

type ExecutionResult struct {
	Command       *Command
	Success       bool
	Output        string
	Error         error
	StartTime     time.Time
	EndTime       time.Time
	FinalStatus   detection.DetectedStatus
	StatusChanges []StatusChange
}

ExecutionResult represents the result of a command execution.

type ExternalApprovalCallback

type ExternalApprovalCallback func(*ExternalApprovalEvent)

ExternalApprovalCallback is called when an approval is detected.

type ExternalApprovalEvent

type ExternalApprovalEvent struct {
	Request      *detection.ApprovalRequest
	SessionID    string // Socket path or unique identifier
	SessionTitle string
	Source       ExternalApprovalSource
	Cwd          string
	Command      string
}

ExternalApprovalEvent represents an approval detected in an external session.

type ExternalApprovalMonitor

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

ExternalApprovalMonitor monitors external sessions for approval requests.

func NewExternalApprovalMonitor

func NewExternalApprovalMonitor() *ExternalApprovalMonitor

NewExternalApprovalMonitor creates a new external approval monitor.

func (*ExternalApprovalMonitor) GetAllPendingApprovals

func (m *ExternalApprovalMonitor) GetAllPendingApprovals() map[string][]*detection.ApprovalRequest

GetAllPendingApprovals returns pending approvals across all monitored sessions.

func (*ExternalApprovalMonitor) GetDetector

GetDetector returns the underlying approval detector for configuration.

func (*ExternalApprovalMonitor) GetMonitoredSessions

func (m *ExternalApprovalMonitor) GetMonitoredSessions() []string

GetMonitoredSessions returns the socket paths of all monitored sessions.

func (*ExternalApprovalMonitor) GetPendingApprovals

func (m *ExternalApprovalMonitor) GetPendingApprovals(socketPath string) []*detection.ApprovalRequest

GetPendingApprovals returns all pending approval requests for a session.

func (*ExternalApprovalMonitor) IntegrateWithDiscovery

func (m *ExternalApprovalMonitor) IntegrateWithDiscovery(
	discovery *ExternalSessionDiscovery,
	streamerManager *ExternalStreamerManager,
)

IntegrateWithDiscovery connects the approval monitor to external session discovery. This auto-monitors new external sessions as they're discovered.

func (*ExternalApprovalMonitor) IntegrateWithDiscoveryTmux

func (m *ExternalApprovalMonitor) IntegrateWithDiscoveryTmux(
	discovery *ExternalSessionDiscovery,
	tmuxStreamerManager *ExternalTmuxStreamerManager,
)

IntegrateWithDiscoveryTmux connects the approval monitor to external session discovery using tmux-based streaming instead of socket-based streaming.

func (*ExternalApprovalMonitor) MarkApprovalHandled

func (m *ExternalApprovalMonitor) MarkApprovalHandled(socketPath, requestID string, approved bool) error

MarkApprovalHandled marks an approval request as handled.

func (*ExternalApprovalMonitor) MonitorSession

func (m *ExternalApprovalMonitor) MonitorSession(
	streamer *ExternalStreamer,
	title string,
	source ExternalApprovalSource,
) error

MonitorSession starts monitoring an external session for approval requests.

func (*ExternalApprovalMonitor) MonitorSessionTmux

func (m *ExternalApprovalMonitor) MonitorSessionTmux(
	streamer *ExternalTmuxStreamer,
	tmuxSessionName string,
	title string,
	source ExternalApprovalSource,
) error

MonitorSessionTmux starts monitoring an external session using tmux-based streaming.

func (*ExternalApprovalMonitor) OnApproval

func (m *ExternalApprovalMonitor) OnApproval(callback ExternalApprovalCallback)

OnApproval registers a callback for approval events.

func (*ExternalApprovalMonitor) Start

func (m *ExternalApprovalMonitor) Start()

Start begins monitoring for approvals.

func (*ExternalApprovalMonitor) Stop

func (m *ExternalApprovalMonitor) Stop()

Stop stops all monitoring.

func (*ExternalApprovalMonitor) StopMonitoringSession

func (m *ExternalApprovalMonitor) StopMonitoringSession(socketPath string)

StopMonitoringSession stops monitoring a specific session.

type ExternalApprovalSource

type ExternalApprovalSource string

ExternalApprovalSource identifies the source of an external approval.

const (
	SourceIntelliJ ExternalApprovalSource = "IntelliJ"
	SourceTerminal ExternalApprovalSource = "Terminal"
	SourceVSCode   ExternalApprovalSource = "VS Code"
	SourceMux      ExternalApprovalSource = "mux"
	SourceUnknown  ExternalApprovalSource = "Unknown"
)

type ExternalInstanceMetadata

type ExternalInstanceMetadata struct {
	// TmuxSocket is the tmux server socket this instance belongs to
	// Empty string means the default tmux server
	TmuxSocket string

	// TmuxSessionName is the full tmux session name
	TmuxSessionName string

	// DiscoveredAt is when this external instance was first discovered
	DiscoveredAt time.Time

	// LastSeen is when this instance was last seen during discovery
	LastSeen time.Time

	// OriginalPID is the process ID when first discovered
	OriginalPID int

	// MuxSocketPath is the path to a claude-mux Unix domain socket
	// If set, this instance was discovered via claude-mux and supports
	// full bidirectional terminal access
	MuxSocketPath string

	// MuxEnabled indicates whether this instance supports mux protocol
	MuxEnabled bool

	// SourceTerminal identifies the source (e.g., "IntelliJ", "Terminal", "tmux")
	SourceTerminal string
}

ExternalInstanceMetadata contains metadata for externally discovered Claude instances

type ExternalSessionDiscovery

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

ExternalSessionDiscovery discovers and manages external Claude sessions from claude-mux multiplexed terminals.

func NewExternalSessionDiscovery

func NewExternalSessionDiscovery() *ExternalSessionDiscovery

NewExternalSessionDiscovery creates a new external session discovery service.

func (*ExternalSessionDiscovery) GetSession

func (e *ExternalSessionDiscovery) GetSession(socketPath string) *Instance

GetSession returns a specific external session by socket path (deprecated - use GetSessionByTmux).

func (*ExternalSessionDiscovery) GetSessionByTmux

func (e *ExternalSessionDiscovery) GetSessionByTmux(tmuxSessionName string) *Instance

GetSessionByTmux returns a specific external session by tmux session name.

func (*ExternalSessionDiscovery) GetSessions

func (e *ExternalSessionDiscovery) GetSessions() []*Instance

GetSessions returns all currently discovered external sessions.

func (*ExternalSessionDiscovery) OnSessionAdded

func (e *ExternalSessionDiscovery) OnSessionAdded(callback func(*Instance))

OnSessionAdded registers a callback for when a new external session is discovered. Multiple callbacks can be registered and will all be invoked.

func (*ExternalSessionDiscovery) OnSessionRemoved

func (e *ExternalSessionDiscovery) OnSessionRemoved(callback func(*Instance))

OnSessionRemoved registers a callback for when an external session is removed. Multiple callbacks can be registered and will all be invoked.

func (*ExternalSessionDiscovery) Start

func (e *ExternalSessionDiscovery) Start(interval time.Duration)

Start begins periodic discovery of external sessions.

func (*ExternalSessionDiscovery) Stop

func (e *ExternalSessionDiscovery) Stop()

Stop stops the discovery service.

type ExternalStreamer

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

ExternalStreamer connects to a mux socket and streams terminal output. It handles reconnection and broadcasts output to registered consumers.

func NewExternalStreamer

func NewExternalStreamer(socketPath string, bufferSize int) *ExternalStreamer

NewExternalStreamer creates a new streamer for the given mux socket.

func (*ExternalStreamer) AddConsumer

func (s *ExternalStreamer) AddConsumer(consumer OutputConsumer, catchUp bool)

AddConsumer registers a callback to receive output data. If catchUp is true, the consumer receives buffered recent output first.

func (*ExternalStreamer) ConsumerCount

func (s *ExternalStreamer) ConsumerCount() int

ConsumerCount returns the number of registered consumers.

func (*ExternalStreamer) GetMetadata

func (s *ExternalStreamer) GetMetadata() *mux.SessionMetadata

GetMetadata returns the session metadata from the mux.

func (*ExternalStreamer) GetRecentOutput

func (s *ExternalStreamer) GetRecentOutput() []byte

GetRecentOutput returns the buffered recent output.

func (*ExternalStreamer) GetSnapshot

func (s *ExternalStreamer) GetSnapshot() ([]byte, error)

GetSnapshot requests a clean screen snapshot from the mux session. This uses tmux capture-pane on the server side to get clean terminal content without ANSI escape sequences, suitable for pattern matching and initial state. The snapshot request is coordinated with the readLoop to avoid race conditions.

func (*ExternalStreamer) IsConnected

func (s *ExternalStreamer) IsConnected() bool

IsConnected returns whether the streamer is currently connected.

func (*ExternalStreamer) RemoveConsumer

func (s *ExternalStreamer) RemoveConsumer(consumer OutputConsumer)

RemoveConsumer unregisters a consumer callback. Note: This uses function pointer comparison which may not work for closures. Consider using a consumer ID pattern for production use.

func (*ExternalStreamer) SendInput

func (s *ExternalStreamer) SendInput(data []byte) error

SendInput sends input data to the mux session.

func (*ExternalStreamer) SendResize

func (s *ExternalStreamer) SendResize(cols, rows uint16) error

SendResize sends a terminal resize command to the mux session.

func (*ExternalStreamer) SocketPath

func (s *ExternalStreamer) SocketPath() string

SocketPath returns the path to the mux socket.

func (*ExternalStreamer) Start

func (s *ExternalStreamer) Start() error

Start connects to the mux socket and begins streaming.

func (*ExternalStreamer) Stop

func (s *ExternalStreamer) Stop()

Stop disconnects and stops the streamer.

type ExternalStreamerManager

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

ExternalStreamerManager manages multiple external streamers.

func NewExternalStreamerManager

func NewExternalStreamerManager(bufferSize int) *ExternalStreamerManager

NewExternalStreamerManager creates a new streamer manager.

func (*ExternalStreamerManager) Count

func (m *ExternalStreamerManager) Count() int

Count returns the number of active streamers.

func (*ExternalStreamerManager) Get

func (m *ExternalStreamerManager) Get(socketPath string) *ExternalStreamer

Get returns a streamer if it exists.

func (*ExternalStreamerManager) GetOrCreate

func (m *ExternalStreamerManager) GetOrCreate(socketPath string) (*ExternalStreamer, error)

GetOrCreate returns an existing streamer or creates a new one.

func (*ExternalStreamerManager) Remove

func (m *ExternalStreamerManager) Remove(socketPath string)

Remove stops and removes a streamer.

func (*ExternalStreamerManager) StopAll

func (m *ExternalStreamerManager) StopAll()

StopAll stops all streamers.

type ExternalTmuxStreamer

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

ExternalTmuxStreamer provides terminal content streaming for external sessions.

It uses two strategies in priority order:

  1. Control mode (preferred): Starts "tmux -C attach-session -t <name> -r" which provides real-time %output notifications via the tmux control protocol. When an %output event arrives it signals that the pane content has changed, triggering a single capture-pane call to obtain the full terminal snapshot. This eliminates blind polling while preserving the full-snapshot semantic that consumers expect.

  2. Capture-pane polling (fallback): If control mode fails to start (e.g. older tmux, session not found) the streamer falls back to polling capture-pane every 500ms. This is less responsive but universally compatible.

func NewExternalTmuxStreamer

func NewExternalTmuxStreamer(tmuxSessionName string) *ExternalTmuxStreamer

NewExternalTmuxStreamer creates a new tmux-based streamer for an external session.

func (*ExternalTmuxStreamer) AddConsumer

func (s *ExternalTmuxStreamer) AddConsumer(consumer func(content string))

AddConsumer registers a callback to receive content updates. The consumer will be called with the full terminal content whenever it changes.

func (*ExternalTmuxStreamer) ConsumerCount

func (s *ExternalTmuxStreamer) ConsumerCount() int

ConsumerCount returns the number of registered consumers.

func (*ExternalTmuxStreamer) GetContent

func (s *ExternalTmuxStreamer) GetContent() string

GetContent returns the current terminal content.

func (*ExternalTmuxStreamer) IsRunning

func (s *ExternalTmuxStreamer) IsRunning() bool

IsRunning returns whether the streamer is currently running.

func (*ExternalTmuxStreamer) RemoveConsumer

func (s *ExternalTmuxStreamer) RemoveConsumer(consumer func(content string))

RemoveConsumer removes a consumer. Note: this uses pointer comparison which may not work for closures.

func (*ExternalTmuxStreamer) Start

func (s *ExternalTmuxStreamer) Start() error

Start begins streaming the tmux session for content changes. It first attempts to use tmux control mode for event-driven updates. If control mode is unavailable, it falls back to capture-pane polling.

func (*ExternalTmuxStreamer) Stop

func (s *ExternalTmuxStreamer) Stop()

Stop stops the streamer.

type ExternalTmuxStreamerManager

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

ExternalTmuxStreamerManager manages multiple external tmux streamers.

func NewExternalTmuxStreamerManager

func NewExternalTmuxStreamerManager() *ExternalTmuxStreamerManager

NewExternalTmuxStreamerManager creates a new streamer manager.

func (*ExternalTmuxStreamerManager) Count

func (m *ExternalTmuxStreamerManager) Count() int

Count returns the number of active streamers.

func (*ExternalTmuxStreamerManager) Get

func (m *ExternalTmuxStreamerManager) Get(tmuxSessionName string) *ExternalTmuxStreamer

Get returns a streamer if it exists.

func (*ExternalTmuxStreamerManager) GetOrCreate

func (m *ExternalTmuxStreamerManager) GetOrCreate(tmuxSessionName string) (*ExternalTmuxStreamer, error)

GetOrCreate returns an existing streamer or creates a new one.

func (*ExternalTmuxStreamerManager) Remove

func (m *ExternalTmuxStreamerManager) Remove(tmuxSessionName string)

Remove stops and removes a streamer.

func (*ExternalTmuxStreamerManager) StopAll

func (m *ExternalTmuxStreamerManager) StopAll()

StopAll stops all streamers.

type FilesystemContext

type FilesystemContext struct {
	// ProjectPath is the root project/repository directory
	ProjectPath string `json:"project_path,omitempty"`

	// WorkingDir is the current working directory within the project
	WorkingDir string `json:"working_dir,omitempty"`

	// IsWorktree indicates if this session is using a git worktree
	IsWorktree bool `json:"is_worktree,omitempty"`

	// MainRepoPath is the parent repository path if this is a worktree
	MainRepoPath string `json:"main_repo_path,omitempty"`

	// ClonedRepoPath is the path to the cloned repository for external PRs
	ClonedRepoPath string `json:"cloned_repo_path,omitempty"`

	// ExistingWorktree is the path to an existing worktree being used
	ExistingWorktree string `json:"existing_worktree,omitempty"`

	// SessionType indicates the type of session workflow
	SessionType SessionType `json:"session_type,omitempty"`
}

FilesystemContext represents the filesystem-related context for a session. This includes project paths, working directories, and worktree information.

func (*FilesystemContext) IsEmpty

func (f *FilesystemContext) IsEmpty() bool

IsEmpty returns true if the FilesystemContext has no meaningful data

type GitContext

type GitContext struct {
	// Branch is the current git branch name
	Branch string `json:"branch,omitempty"`

	// BaseCommitSHA is the commit SHA where this branch diverged from main/master
	BaseCommitSHA string `json:"base_commit_sha,omitempty"`

	// WorktreeID is a foreign key to the worktrees table (nil if no worktree)
	WorktreeID *int64 `json:"worktree_id,omitempty"`

	// PRNumber is the pull request number
	PRNumber int `json:"pr_number,omitempty"`

	// PRURL is the full URL to the pull request
	PRURL string `json:"pr_url,omitempty"`

	// Owner is the GitHub repository owner/organization
	Owner string `json:"owner,omitempty"`

	// Repo is the GitHub repository name
	Repo string `json:"repo,omitempty"`

	// SourceRef is the source branch reference for the PR
	SourceRef string `json:"source_ref,omitempty"`
}

GitContext represents the Git-related context for a session. This includes repository information, branch details, and GitHub PR integration.

func (*GitContext) IsEmpty

func (g *GitContext) IsEmpty() bool

IsEmpty returns true if the GitContext has no meaningful data

type GitHubMetadataView

type GitHubMetadataView struct {
	PRNumber       int
	PRURL          string
	Owner          string
	Repo           string
	SourceRef      string
	ClonedRepoPath string
}

GitHubMetadataView is a read-only value object for GitHub session metadata. Constructed by Instance.GitHub() from the underlying fields. This is intentionally a value type (not a pointer) for safe concurrent reads.

func (GitHubMetadataView) IsEmpty

func (gh GitHubMetadataView) IsEmpty() bool

IsEmpty returns true if no GitHub metadata is set.

func (GitHubMetadataView) IsGitHubSession

func (gh GitHubMetadataView) IsGitHubSession() bool

IsGitHubSession returns true if owner and repo are both set.

func (GitHubMetadataView) IsPRSession

func (gh GitHubMetadataView) IsPRSession() bool

IsPRSession returns true if this metadata represents a PR-based session.

func (GitHubMetadataView) PRDisplayInfo

func (gh GitHubMetadataView) PRDisplayInfo() string

PRDisplayInfo returns human-readable PR description for UI display. Returns empty string if not a PR session.

func (GitHubMetadataView) RepoFullName

func (gh GitHubMetadataView) RepoFullName() string

RepoFullName returns "owner/repo" format, or empty string if either is missing.

type GitHubRef

type GitHubRef struct {
	Owner    string
	Repo     string
	Branch   string
	PRNumber int
	Type     GitHubRefType
}

GitHubRef represents a parsed GitHub reference.

func ParseGitHubURL

func ParseGitHubURL(input string) (*GitHubRef, error)

ParseGitHubURL parses a GitHub URL and returns the components. Supported formats:

func ResolveGitHubInput

func ResolveGitHubInput(input string) (localPath string, ref *GitHubRef, err error)

ResolveGitHubInput is a convenience function using the default manager.

type GitHubRefType

type GitHubRefType int

GitHubRefType indicates what kind of GitHub reference this is.

const (
	GitHubRefTypeRepo GitHubRefType = iota
	GitHubRefTypeBranch
	GitHubRefTypePR
)

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 GitWorktreeManager

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

GitWorktreeManager owns the git worktree and diff-stats state that were previously bare fields on Instance.

Instance keeps thin wrapper methods that delegate here. GitWorktreeManager itself has no knowledge of Instance lifecycle; it only manages the worktree and diff operations.

func (*GitWorktreeManager) Cleanup

func (gm *GitWorktreeManager) Cleanup() error

Cleanup removes the worktree from the filesystem and git metadata. Returns nil if no worktree is set.

func (*GitWorktreeManager) ClearDiffStats

func (gm *GitWorktreeManager) ClearDiffStats()

ClearDiffStats sets diffStats to nil.

func (*GitWorktreeManager) CommitChanges

func (gm *GitWorktreeManager) CommitChanges(commitMsg string) error

CommitChanges stages all changes and creates a commit.

func (*GitWorktreeManager) ComputeDiff

func (gm *GitWorktreeManager) ComputeDiff() *git.DiffStats

ComputeDiff runs git diff and returns the result without storing it. Returns nil if no worktree is set.

func (*GitWorktreeManager) ComputeDiffIfReady

func (gm *GitWorktreeManager) ComputeDiffIfReady() (stats *git.DiffStats, needsPause bool)

ComputeDiffIfReady checks if the worktree path exists and computes a new diff. Returns (stats, needsPause) where needsPause is true if the worktree directory is missing. This method performs I/O and should be called WITHOUT holding Instance.stateMutex. Returns (nil, false) if no worktree is set.

func (*GitWorktreeManager) GetBaseCommitSHA

func (gm *GitWorktreeManager) GetBaseCommitSHA() string

GetBaseCommitSHA returns the base commit SHA or "" if no worktree.

func (*GitWorktreeManager) GetBranchName

func (gm *GitWorktreeManager) GetBranchName() string

GetBranchName returns the branch name or "" if no worktree.

func (*GitWorktreeManager) GetDiffStats

func (gm *GitWorktreeManager) GetDiffStats() *git.DiffStats

GetDiffStats returns the most recently computed diff stats (may be nil).

func (*GitWorktreeManager) GetRepoName

func (gm *GitWorktreeManager) GetRepoName() string

GetRepoName returns the repository name or "" if no worktree.

func (*GitWorktreeManager) GetRepoPath

func (gm *GitWorktreeManager) GetRepoPath() string

GetRepoPath returns the repo root path or "" if no worktree.

func (*GitWorktreeManager) GetWorktree

func (gm *GitWorktreeManager) GetWorktree() *git.GitWorktree

GetWorktree returns the underlying GitWorktree (may be nil before Setup).

func (*GitWorktreeManager) GetWorktreePath

func (gm *GitWorktreeManager) GetWorktreePath() string

GetWorktreePath returns the worktree path or "" if no worktree.

func (*GitWorktreeManager) HasWorktree

func (gm *GitWorktreeManager) HasWorktree() bool

HasWorktree reports whether a git worktree has been initialized.

func (*GitWorktreeManager) IsBranchCheckedOut

func (gm *GitWorktreeManager) IsBranchCheckedOut() (bool, error)

IsBranchCheckedOut reports whether the branch is currently checked out.

func (*GitWorktreeManager) IsDirty

func (gm *GitWorktreeManager) IsDirty() (bool, error)

IsDirty reports whether the worktree has uncommitted changes.

func (*GitWorktreeManager) OpenBranchURL

func (gm *GitWorktreeManager) OpenBranchURL() error

OpenBranchURL opens the branch URL in the browser.

func (*GitWorktreeManager) Prune

func (gm *GitWorktreeManager) Prune() error

Prune cleans up stale worktree references.

func (*GitWorktreeManager) PushChanges

func (gm *GitWorktreeManager) PushChanges(commitMsg string, open bool) error

PushChanges commits and pushes the worktree branch.

func (*GitWorktreeManager) Remove

func (gm *GitWorktreeManager) Remove() error

Remove removes the worktree from git without pruning.

func (*GitWorktreeManager) SetDiffStats

func (gm *GitWorktreeManager) SetDiffStats(stats *git.DiffStats)

SetDiffStats directly replaces the diff stats (used during deserialization).

func (*GitWorktreeManager) SetWorktree

func (gm *GitWorktreeManager) SetWorktree(wt *git.GitWorktree)

SetWorktree replaces the underlying GitWorktree. Used during session start and by tests.

func (*GitWorktreeManager) Setup

func (gm *GitWorktreeManager) Setup() error

Setup prepares the worktree (creates directories, checks out branch, etc.).

func (*GitWorktreeManager) UpdateDiffStats

func (gm *GitWorktreeManager) UpdateDiffStats()

UpdateDiffStats computes a new diff and stores it. Returns nil and clears stats if worktree is not ready.

type HealthCheckResult

type HealthCheckResult struct {
	InstanceTitle     string
	IsHealthy         bool
	Issues            []string
	Actions           []string
	RecoveryAttempted bool
	RecoverySuccess   bool
}

HealthCheckResult represents the result of a session health check

type HistoryEntry

type HistoryEntry struct {
	Command       Command          `json:"command"`
	Result        *ExecutionResult `json:"result,omitempty"`
	Timestamp     time.Time        `json:"timestamp"`
	SessionName   string           `json:"session_name"`
	ExecutionTime time.Duration    `json:"execution_time"`
}

HistoryEntry represents a single command execution in history.

type HistoryStatistics

type HistoryStatistics struct {
	TotalCommands        int
	SuccessfulCommands   int
	FailedCommands       int
	CancelledCommands    int
	AverageExecutionTime time.Duration
	FirstCommandTime     time.Time
	LastCommandTime      time.Time
}

HistoryStatistics provides summary statistics about command history.

type Instance

type Instance struct {
	// Title is the title of the instance.
	Title string
	// Path is the path to the workspace repository root.
	Path string
	// WorkingDir is the directory within the repository to start in.
	WorkingDir 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
	// Prompt is the initial prompt to pass to the instance on startup
	Prompt string
	// ExistingWorktree is an optional path to an existing worktree to reuse
	ExistingWorktree string
	// Category is used for organizing sessions into groups
	Category string
	// IsExpanded indicates whether this session's category is expanded in the UI
	IsExpanded bool
	// SessionType determines the session workflow (directory, new_worktree, existing_worktree)
	SessionType SessionType
	// TmuxPrefix is the prefix to use for tmux session names
	TmuxPrefix string
	// TmuxServerSocket is the server socket name for tmux isolation (used with -L flag)
	// If empty, uses the default tmux server. For complete isolation (e.g., testing),
	// set to a unique value like "test" or "teatest_123" to create separate tmux servers.
	TmuxServerSocket string
	// Tags are multi-valued labels for flexible session organization
	// Sessions can have multiple tags and appear in multiple groups simultaneously
	// Examples: ["frontend", "urgent", "client-work"]
	Tags []string

	// GitHub integration fields for PR/URL-based session creation
	// GitHubPRNumber is the PR number if this session was created from a PR URL
	GitHubPRNumber int `json:"github_pr_number,omitempty"`
	// GitHubPRURL is the full URL to the PR on GitHub
	GitHubPRURL string `json:"github_pr_url,omitempty"`
	// GitHubOwner is the repository owner (user or organization)
	GitHubOwner string `json:"github_owner,omitempty"`
	// GitHubRepo is the repository name
	GitHubRepo string `json:"github_repo,omitempty"`
	// GitHubSourceRef is the original URL or reference used to create this session
	GitHubSourceRef string `json:"github_source_ref,omitempty"`
	// ClonedRepoPath is the path where we cloned the repo (if cloned)
	ClonedRepoPath string `json:"cloned_repo_path,omitempty"`
	// MainRepoPath is the path to the main repository when Path is a worktree
	// Detected automatically via `git rev-parse --git-common-dir`
	MainRepoPath string `json:"main_repo_path,omitempty"`
	// IsWorktree indicates whether Path is a git worktree (not the main repo)
	IsWorktree bool `json:"is_worktree,omitempty"`

	// ReviewState holds all review queue and terminal activity timestamps.
	// Fields are embedded (promoted) so external code can still access inst.LastViewed etc.
	// Protected by stateMutex.
	ReviewState

	// Instance type and management metadata
	// InstanceType indicates whether this is a squad-managed or external instance
	InstanceType InstanceType
	// IsManaged is true if this is a squad-managed session (backward compatible helper)
	IsManaged bool
	// ExternalMetadata contains additional information for externally discovered instances
	ExternalMetadata *ExternalInstanceMetadata
	// Permissions defines what operations are allowed on this instance
	Permissions InstancePermissions
	// 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 NewInstanceWithCleanup

func NewInstanceWithCleanup(opts InstanceOptions) (*Instance, tmux.CleanupFunc, error)

NewInstanceWithCleanup creates a new Instance and returns it along with a cleanup function. Usage: instance, cleanup, err := NewInstanceWithCleanup(opts); if err == nil { defer cleanup() }

func SessionToInstance

func SessionToInstance(s *Session) *Instance

SessionToInstance converts a Session back to the legacy Instance type. This adapter enables interoperability during the migration period. Note: Some Session features (like CloudContext) don't have Instance equivalents.

func (*Instance) AddTag

func (i *Instance) AddTag(tag string) error

AddTag adds a tag to the instance. Delegates to TagManager.Add. Returns ErrTagTooLong if the tag exceeds MaxTagLength, or ErrDuplicateTag if it already exists.

func (*Instance) Approve

func (i *Instance) Approve() error

Approve transitions the instance from NeedsApproval to Running. Returns an error if the current state does not allow this transition.

func (*Instance) Attach

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

func (*Instance) CapturePaneContent

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

CapturePaneContent captures the current visible tmux pane content. This is a simple wrapper around TmuxSession.CapturePaneContent() for compatibility with the terminal WebSocket handlers.

func (*Instance) CapturePaneContentRaw

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

CapturePaneContentRaw captures pane content with ANSI codes preserved (no line joining). Essential for hybrid streaming where cursor positioning codes must be preserved.

func (*Instance) CleanupWorktree

func (i *Instance) CleanupWorktree() error

CleanupWorktree removes the git worktree, keeping session intact

func (*Instance) ClosePR

func (i *Instance) ClosePR() error

ClosePR closes the PR without merging Returns an error if this is not a PR session or if the GitHub API call fails

func (*Instance) Deny

func (i *Instance) Deny() error

Deny transitions the instance from NeedsApproval to Paused. Returns an error if the current state does not allow this transition.

func (*Instance) Destroy

func (i *Instance) Destroy() error

Destroy completely destroys the instance - both tmux session and worktree

func (*Instance) DetectAndPopulateWorktreeInfo

func (i *Instance) DetectAndPopulateWorktreeInfo() error

DetectAndPopulateWorktreeInfo detects if the instance path is a worktree and populates the IsWorktree, MainRepoPath, GitHubOwner, and GitHubRepo fields. NOTE: This method writes to GitHub fields (i.GitHubOwner, i.GitHubRepo) directly. A future pass could route writes through a setter method for encapsulation. This is useful for sessions created from existing worktrees where we want to display the actual repository information in the UI.

IMPORTANT: For sessions with git worktrees, we check BOTH paths: 1. The worktree path (gitWorktree.GetWorktreePath()) - to detect IsWorktree and MainRepoPath 2. The original path (i.Path) - as fallback for GitHub owner/repo if worktree detection fails

This is necessary because: - i.Path is the main repository path (e.g., ~/Documents/personal-wiki) - gitWorktree.GetWorktreePath() is the actual worktree (e.g., ~/.stapler-squad/worktrees/...) - The main repo has .git as a directory; the worktree has .git as a file pointing to the main repo

func (*Instance) GeneratePRContextPrompt

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

GeneratePRContextPrompt generates a context prompt for Claude based on PR information This can be used to initialize a Claude Code session with comprehensive PR context Returns an error if this is not a PR session or if the GitHub API call fails

func (*Instance) GetCategoryPath

func (i *Instance) GetCategoryPath() []string

GetCategoryPath returns the category path as a slice of strings for nested category support Supports "Work/Frontend" syntax by splitting on "/" delimiter

func (*Instance) GetClaudeSession

func (i *Instance) GetClaudeSession() *ClaudeSessionData

GetClaudeSession returns the Claude session data for this instance

func (*Instance) GetController

func (i *Instance) GetController() *ClaudeController

GetController returns the ClaudeController if one exists

func (*Instance) GetCurrentPaneContent

func (i *Instance) GetCurrentPaneContent(lines int) (string, error)

GetCurrentPaneContent captures the current visible tmux pane content. Delegates to tmuxManager.CaptureViewport.

func (*Instance) GetDiffStats

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

GetDiffStats returns the current git diff statistics

func (*Instance) GetEffectiveRootDir

func (i *Instance) GetEffectiveRootDir() string

GetEffectiveRootDir returns the root directory where this session operates. For worktree sessions, this is the worktree path. For directory sessions, this is Path. Used for injecting configuration files (e.g., .claude/settings.local.json).

func (*Instance) GetEffectiveStatus

func (i *Instance) GetEffectiveStatus() Status

GetEffectiveStatus returns the most accurate status for this instance, combining the lifecycle status with real-time terminal detection when available. Unlike Status (which only reflects lifecycle transitions), this consults the ClaudeController's detected terminal state to surface NeedsApproval, Idle, etc.

func (*Instance) GetGitHubRepoFullName

func (i *Instance) GetGitHubRepoFullName() string

GetGitHubRepoFullName returns "owner/repo" format, or empty string. Delegates to GitHubMetadataView.RepoFullName.

func (*Instance) GetGitWorktree

func (i *Instance) GetGitWorktree() (*git.GitWorktree, error)

GetGitWorktree returns the git worktree for the instance

func (*Instance) GetPRComments

func (i *Instance) GetPRComments() ([]github.PRComment, error)

GetPRComments fetches all comments on the PR Returns an error if this is not a PR session or if the GitHub API call fails

func (*Instance) GetPRDiff

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

GetPRDiff fetches the diff for the PR Returns an error if this is not a PR session or if the GitHub API call fails

func (*Instance) GetPRDisplayInfo

func (i *Instance) GetPRDisplayInfo() string

GetPRDisplayInfo returns a human-readable PR description for UI display. Delegates to GitHubMetadataView.PRDisplayInfo.

func (*Instance) GetPTYReader

func (i *Instance) GetPTYReader() (*os.File, error)

GetPTYReader returns an io.Reader for streaming terminal output. Delegates to tmuxManager.GetPTY.

func (*Instance) GetPaneCursorPosition

func (i *Instance) GetPaneCursorPosition() (x, y int, err error)

GetPaneCursorPosition gets the current cursor position in the tmux pane. Returns cursor X (column) and Y (row) coordinates, both 0-based.

func (*Instance) GetPaneDimensions

func (i *Instance) GetPaneDimensions() (width, height int, err error)

GetPaneDimensions gets the current dimensions of the tmux pane. Returns width (columns) and height (rows).

func (*Instance) GetPermissions

func (i *Instance) GetPermissions() InstancePermissions

GetPermissions returns the permissions for this instance based on its type

func (*Instance) GetReviewItem

func (i *Instance) GetReviewItem() (*ReviewItem, bool)

GetReviewItem returns the review item for this instance if it exists

func (*Instance) GetReviewQueue

func (i *Instance) GetReviewQueue() *ReviewQueue

GetReviewQueue returns the review queue for this instance

func (*Instance) GetScrollbackHistory

func (i *Instance) GetScrollbackHistory(startLine, endLine string) (string, error)

GetScrollbackHistory captures scrollback history from tmux using line ranges. Uses tmux's native scrollback capabilities instead of stored sequences. startLine and endLine follow tmux conventions: negative numbers go back from current position, use "-" for the start/end of history.

func (*Instance) GetStatusIconForType

func (i *Instance) GetStatusIconForType() string

GetStatusIconForType returns the appropriate status icon based on instance type

func (*Instance) GetStatusManager

func (i *Instance) GetStatusManager() *InstanceStatusManager

GetStatusManager returns the status manager

func (*Instance) GetTags

func (i *Instance) GetTags() []string

GetTags returns a copy of the instance's tags. Delegates to TagManager.All.

func (*Instance) GetTimeSinceLastMeaningfulOutput

func (i *Instance) GetTimeSinceLastMeaningfulOutput() time.Duration

GetTimeSinceLastMeaningfulOutput delegates to ReviewState.TimeSinceLastMeaningfulOutput. Falls back to time since creation if no meaningful output has been recorded.

func (*Instance) GetTimeSinceLastTerminalUpdate

func (i *Instance) GetTimeSinceLastTerminalUpdate() time.Duration

GetTimeSinceLastTerminalUpdate delegates to ReviewState.TimeSinceLastTerminalUpdate. Falls back to time since creation if no terminal output has been recorded.

func (*Instance) GetTmuxSession

func (i *Instance) GetTmuxSession() *tmux.TmuxSession

GetTmuxSession returns the underlying tmux session for direct access. Returns nil if the session hasn't been started yet.

func (*Instance) GetVCSInfo

func (i *Instance) GetVCSInfo() (*VCSInfo, error)

GetVCSInfo returns information about the VCS for this session

func (*Instance) GetWorkingDirectory

func (i *Instance) GetWorkingDirectory() string

GetWorkingDirectory returns the working directory for this instance

func (*Instance) GitHub

func (i *Instance) GitHub() GitHubMetadataView

GitHub returns a read-only view of the GitHub metadata for this instance.

func (*Instance) HasClaudeSession

func (i *Instance) HasClaudeSession() bool

HasClaudeSession returns true if this instance has Claude session data

func (*Instance) HasGitWorktree

func (i *Instance) HasGitWorktree() bool

HasGitWorktree returns true if the instance has a git worktree

func (*Instance) HasTag

func (i *Instance) HasTag(tag string) bool

HasTag returns true if the instance has the specified tag. Delegates to TagManager.Has.

func (*Instance) HasUpdated

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

func (*Instance) IsGitHubSession

func (i *Instance) IsGitHubSession() bool

IsGitHubSession returns true if this session has GitHub owner and repo set. Delegates to GitHubMetadataView.IsGitHubSession.

func (*Instance) IsPRSession

func (i *Instance) IsPRSession() bool

IsPRSession returns true if this session was created from a GitHub PR URL. Delegates to GitHubMetadataView.IsPRSession.

func (*Instance) Kill

func (i *Instance) Kill() error

Kill terminates the instance and cleans up all resources Kill destroys both tmux session and worktree (legacy method)

func (*Instance) KillExternalSession

func (i *Instance) KillExternalSession() error

KillExternalSession terminates an external mux session by killing its tmux session. This only works for external sessions that were started via claude-mux with tmux integration. Returns an error if this is not an external instance or lacks tmux session name.

func (*Instance) KillSession

func (i *Instance) KillSession() error

KillSession terminates only the tmux session, keeping worktree intact

func (*Instance) KillSessionKeepWorktree

func (i *Instance) KillSessionKeepWorktree() error

KillSessionKeepWorktree terminates tmux session but preserves worktree for recovery scenarios

func (*Instance) ListAvailableTargets

func (i *Instance) ListAvailableTargets() (*AvailableTargets, error)

ListAvailableTargets returns available switch targets (branches, bookmarks, worktrees)

func (*Instance) MergePR

func (i *Instance) MergePR(method string) error

MergePR merges the PR using the specified merge method method can be: "merge", "squash", or "rebase" Returns an error if this is not a PR session or if the GitHub API call fails

func (*Instance) NeedsReview

func (i *Instance) NeedsReview() bool

NeedsReview returns true if this session is in the review queue

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

func (i *Instance) PostComment(body string) error

PostComment posts a comment to the PR Returns an error if this is not a PR session or if the GitHub API call fails

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

func (i *Instance) RefreshPRInfo() (*github.PRInfo, error)

RefreshPRInfo fetches the latest PR information from GitHub Returns an error if this is not a PR session or if the GitHub API call fails

func (*Instance) RefreshTmuxClient

func (i *Instance) RefreshTmuxClient() error

RefreshTmuxClient forces the tmux client to refresh, triggering a redraw of the process running inside. This is critical after resizing to ensure cursor positions and line wrapping are recalculated for the new dimensions.

func (*Instance) RemoveTag

func (i *Instance) RemoveTag(tag string)

RemoveTag removes a tag from the instance. Delegates to TagManager.Remove.

func (*Instance) Rename

func (i *Instance) Rename(newTitle string) error

Rename changes the title of the instance. Per ADR-001, this only updates metadata - the tmux session name remains unchanged. Returns an error if the title is invalid (wrong length or contains invalid characters).

func (*Instance) RepoName

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

func (*Instance) ResizePTY

func (i *Instance) ResizePTY(cols, rows int) error

ResizePTY resizes the terminal dimensions. This is used when clients resize their terminal windows.

func (*Instance) Restart

func (i *Instance) Restart(preserveOutput bool) error

Restart restarts the session by killing and recreating the tmux session. The git worktree is preserved during restart. If preserveOutput is true, captures terminal output before killing the session. For Claude sessions, uses --resume flag with the stored session ID.

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. Delegates to tmuxManager.SendPromptWithEnter.

func (*Instance) SetClaudeSession

func (i *Instance) SetClaudeSession(sessionData *ClaudeSessionData)

SetClaudeSession sets the Claude session data for this instance

func (*Instance) SetGitWorktree

func (i *Instance) SetGitWorktree(worktree *git.GitWorktree)

SetGitWorktree sets the git worktree for testing purposes

func (*Instance) SetPreviewSize

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

func (*Instance) SetReviewQueue

func (i *Instance) SetReviewQueue(queue *ReviewQueue)

SetReviewQueue sets the review queue for this instance

func (*Instance) SetStatus

func (i *Instance) SetStatus(status Status)

SetStatus sets the instance status. Deprecated: Use transitionTo for validated state transitions within the session package. This exported method is retained temporarily for the detection/poller subsystem which sets NeedsApproval based on terminal output patterns. It will be removed once that subsystem is refactored to use domain methods.

func (*Instance) SetStatusManager

func (i *Instance) SetStatusManager(manager *InstanceStatusManager)

SetStatusManager sets the status manager for idle detection.

func (*Instance) SetTags

func (i *Instance) SetTags(tags []string) error

SetTags replaces all tags with a new deduplicated set. Delegates to TagManager.Set. Returns ErrTagTooLong on the first tag that exceeds MaxTagLength.

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

func (i *Instance) SetWindowSize(cols, rows int) error

SetWindowSize propagates window size changes to the tmux session This enables proper terminal resizing in environments like IntelliJ where SIGWINCH doesn't work

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

func (i *Instance) StartController() error

StartController creates and starts a ClaudeController for this instance. The controller enables automated idle detection and queue management.

func (*Instance) StartWithCleanup

func (i *Instance) StartWithCleanup(firstTimeSetup bool) (tmux.CleanupFunc, error)

StartWithCleanup starts the instance and returns a cleanup function. Usage: cleanup, err := instance.StartWithCleanup(firstTimeSetup); if err == nil { defer cleanup() }

func (*Instance) Started

func (i *Instance) Started() bool

func (*Instance) StopController

func (i *Instance) StopController()

StopController stops and cleans up the ClaudeController for this instance

func (*Instance) SwitchWorkspace

func (i *Instance) SwitchWorkspace(req WorkspaceSwitchRequest) (*WorkspaceSwitchResult, error)

SwitchWorkspace switches the session's workspace according to the request. For directory changes, this is a simple cd operation. For revision/worktree switches, this restarts Claude with --resume to preserve conversation.

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

func (i *Instance) ToSession() *Session

ToSession converts this Instance to the new Session type. This is a convenience method that wraps InstanceToSession.

func (*Instance) UpdateDiffStats

func (i *Instance) UpdateDiffStats() error

UpdateDiffStats updates the git diff statistics for this instance. Performs I/O (git diff) outside the lock, then updates state under the write lock.

func (*Instance) UpdateTerminalTimestamps

func (i *Instance) UpdateTerminalTimestamps(content string, forceUpdate bool)

UpdateTerminalTimestamps is a coordinator method that bridges TmuxProcessManager (I/O) with ReviewState (timestamp recording). It:

  1. Calls tmuxManager.FilterBanners/HasMeaningfulContent (no lock needed, read-only tmux ops)
  2. Acquires stateMutex
  3. Delegates to ReviewState.UpdateTimestamps

This method intentionally stays on Instance because it coordinates two sub-managers. The forceUpdate parameter bypasses meaningful content checking for user-initiated interactions.

func (*Instance) WriteToPTY

func (i *Instance) WriteToPTY(data []byte) (int, error)

WriteToPTY writes data to the PTY, sending input to the terminal session. This is used for forwarding client input to the tmux session.

type InstanceData

type InstanceData struct {
	Title      string    `json:"title"`
	Path       string    `json:"path"`
	WorkingDir string    `json:"working_dir"`
	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"`
	Prompt     string    `json:"prompt"`

	Program          string          `json:"program"`
	ExistingWorktree string          `json:"existing_worktree,omitempty"`
	Worktree         GitWorktreeData `json:"worktree"`
	DiffStats        DiffStatsData   `json:"diff_stats"`

	// New fields for session organization and grouping
	Category   string   `json:"category,omitempty"`
	IsExpanded bool     `json:"is_expanded,omitempty"`
	Tags       []string `json:"tags,omitempty"` // Multi-valued tags for flexible organization

	// Session type determines the workflow (directory, new_worktree, existing_worktree)
	SessionType SessionType `json:"session_type,omitempty"`

	// GitHub integration fields for PR/URL-based session creation
	GitHubPRNumber  int    `json:"github_pr_number,omitempty"`
	GitHubPRURL     string `json:"github_pr_url,omitempty"`
	GitHubOwner     string `json:"github_owner,omitempty"`
	GitHubRepo      string `json:"github_repo,omitempty"`
	GitHubSourceRef string `json:"github_source_ref,omitempty"`
	ClonedRepoPath  string `json:"cloned_repo_path,omitempty"`
	// Worktree detection fields
	MainRepoPath string `json:"main_repo_path,omitempty"` // Path to main repo when this is a worktree
	IsWorktree   bool   `json:"is_worktree,omitempty"`    // True if path is a git worktree

	// Claude Code session persistence
	ClaudeSession ClaudeSessionData `json:"claude_session,omitempty"`
	// Tmux session prefix for isolation
	TmuxPrefix string `json:"tmux_prefix,omitempty"`

	// Terminal update timestamps for activity tracking
	LastTerminalUpdate   time.Time `json:"last_terminal_update,omitempty"`
	LastMeaningfulOutput time.Time `json:"last_meaningful_output,omitempty"`

	// Content signature for detecting actual terminal changes vs restarts
	// This is a SHA256 hash of the terminal content used to prevent false "new activity"
	// notifications when app restarts but terminal content hasn't changed
	LastOutputSignature string `json:"last_output_signature,omitempty"`

	// Review queue spam prevention
	LastAddedToQueue time.Time `json:"last_added_to_queue,omitempty"`

	// User interaction tracking
	// LastViewed tracks when the user last viewed this session (terminal, session details, etc.)
	// Used for smarter review queue notifications (don't notify if just viewed)
	LastViewed time.Time `json:"last_viewed,omitempty"`

	// Review queue snooze tracking
	// LastAcknowledged tracks when the user last dismissed this session from review queue
	// Sessions acknowledged after their last update won't appear in the queue until they update again
	LastAcknowledged time.Time `json:"last_acknowledged,omitempty"`

	// Prompt detection and interaction tracking for smart review queue behavior
	LastPromptDetected   time.Time `json:"last_prompt_detected,omitempty"`
	LastPromptSignature  string    `json:"last_prompt_signature,omitempty"`
	LastUserResponse     time.Time `json:"last_user_response,omitempty"`
	ProcessingGraceUntil time.Time `json:"processing_grace_until,omitempty"`
}

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 repository root.
	Path string
	// WorkingDir is the directory within the repository to start in.
	// If empty, defaults to repository root.
	WorkingDir string
	// Branch is the git branch name to use when creating a new worktree.
	// If empty and SessionType is SessionTypeNewWorktree, a branch name is derived from the title.
	Branch 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, automatically accept prompts
	AutoYes bool
	// Prompt is the initial prompt to pass to the instance on startup
	Prompt string
	// ExistingWorktree is an optional path to an existing worktree to reuse
	ExistingWorktree string
	// Category is used for organizing sessions into groups
	Category string
	// Tags are multi-valued labels for flexible organization
	Tags []string
	// SessionType determines the session workflow (directory, new_worktree, existing_worktree)
	SessionType SessionType
	// TmuxPrefix is the prefix to use for tmux session names (e.g., "staplersquad_")
	TmuxPrefix string
	// TmuxServerSocket is the server socket name for tmux isolation (used with -L flag)
	// If empty, uses the default tmux server. For complete isolation (e.g., testing),
	// set to a unique value like "test" or "teatest_123" to create separate tmux servers.
	TmuxServerSocket string
	// GitHub integration fields for PR/URL-based session creation
	GitHubPRNumber  int    // PR number if created from PR URL
	GitHubPRURL     string // Full URL to the PR
	GitHubOwner     string // Repository owner
	GitHubRepo      string // Repository name
	GitHubSourceRef string // Original URL/reference used to create session
	ClonedRepoPath  string // Path where repo was cloned (if cloned)
	// ResumeId is the Claude conversation ID to resume (from history browser).
	// When set, the session will start with --resume <id> flag.
	ResumeId string
}

Options for creating a new instance

type InstancePermissions

type InstancePermissions struct {
	// View operations
	CanView bool

	// Attach to the terminal session
	CanAttach bool

	// Send commands to the terminal
	CanSendCommand bool

	// Pause the session (stop tmux, keep worktree)
	CanPause bool

	// Resume a paused session
	CanResume bool

	// Destroy the session completely
	CanDestroy bool

	// Perform git operations (commit, push, worktree management)
	CanModifyGit bool

	// Add to review queue
	CanAddToQueue bool

	// RequiresConfirmation maps operation names to whether they need confirmation
	// Used for high-risk operations on external instances
	RequiresConfirmation map[string]bool
}

InstancePermissions defines what operations are allowed on an instance

func GetExternalPermissions

func GetExternalPermissions(allowAttach bool) InstancePermissions

GetExternalPermissions returns limited permissions for external instances allowAttach controls whether attach operations are permitted (power user mode)

func GetManagedPermissions

func GetManagedPermissions() InstancePermissions

GetManagedPermissions returns full permissions for squad-managed instances

func GetMuxExternalPermissions

func GetMuxExternalPermissions() InstancePermissions

GetMuxExternalPermissions returns permissions for mux-enabled external instances. Mux instances support full bidirectional terminal access and can be destroyed since they're explicitly opted-in by launching through claude-mux with tmux session.

type InstanceStatusInfo

type InstanceStatusInfo struct {
	BasicStatus        Status                   // Running, Paused, Ready
	ClaudeStatus       detection.DetectedStatus // If ClaudeController is active
	StatusContext      string                   // Context/details about current status (e.g., error message)
	PendingApprovals   int                      // Number of pending approvals
	QueuedCommands     int                      // Number of queued commands
	LastCommandStatus  string                   // Status of last command
	IsControllerActive bool                     // Whether ClaudeController is running
	IdleState          detection.IdleStateInfo  // NEW: Idle state information
}

InstanceStatusInfo provides extended status information for an instance.

func (InstanceStatusInfo) GetColorCode

func (info InstanceStatusInfo) GetColorCode() string

GetColorCode returns a color code for the status (for lipgloss styling).

func (InstanceStatusInfo) GetStatusDescription

func (info InstanceStatusInfo) GetStatusDescription() string

GetStatusDescription returns a human-readable status description.

func (InstanceStatusInfo) GetStatusIcon

func (info InstanceStatusInfo) GetStatusIcon() string

GetStatusIcon returns an icon representing the instance status.

func (InstanceStatusInfo) HasPendingWork

func (info InstanceStatusInfo) HasPendingWork() bool

HasPendingWork returns true if the instance has pending commands or approvals.

func (InstanceStatusInfo) IsWaitingForUser

func (info InstanceStatusInfo) IsWaitingForUser() bool

IsWaitingForUser returns true if the instance is waiting for user input.

func (InstanceStatusInfo) NeedsAttention

func (info InstanceStatusInfo) NeedsAttention() bool

NeedsAttention returns true if the instance requires user attention.

type InstanceStatusManager

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

InstanceStatusManager manages status information for instances.

func NewInstanceStatusManager

func NewInstanceStatusManager() *InstanceStatusManager

NewInstanceStatusManager creates a new status manager.

func (*InstanceStatusManager) GetAllControllers

func (ism *InstanceStatusManager) GetAllControllers() map[string]*ClaudeController

GetAllControllers returns all registered controllers.

func (*InstanceStatusManager) GetController

func (ism *InstanceStatusManager) GetController(instanceTitle string) (*ClaudeController, bool)

GetController retrieves a controller for an instance.

func (*InstanceStatusManager) GetStatus

func (ism *InstanceStatusManager) GetStatus(instance *Instance) InstanceStatusInfo

GetStatus retrieves comprehensive status for an instance.

func (*InstanceStatusManager) RegisterController

func (ism *InstanceStatusManager) RegisterController(instanceTitle string, controller *ClaudeController)

RegisterController registers a controller for an instance.

func (*InstanceStatusManager) UnregisterController

func (ism *InstanceStatusManager) UnregisterController(instanceTitle string)

UnregisterController removes a controller for an instance.

type InstanceType

type InstanceType int

InstanceType represents the type of session instance

const (
	// InstanceTypeManaged represents a session fully managed by stapler-squad
	// with complete lifecycle control, git worktrees, and all features
	InstanceTypeManaged InstanceType = iota

	// InstanceTypeExternal represents a Claude instance discovered externally
	// (not created by stapler-squad) with limited interaction capabilities
	InstanceTypeExternal
)

func (InstanceType) String

func (it InstanceType) String() string

type LoadOptions

type LoadOptions struct {
	// LoadWorktree controls whether git worktree data is loaded
	LoadWorktree bool

	// LoadDiffStats controls whether diff statistics (added/removed counts) are loaded
	LoadDiffStats bool

	// LoadDiffContent controls whether full diff content is loaded
	// Note: This implies LoadDiffStats=true, as we need counts to interpret content
	LoadDiffContent bool

	// LoadTags controls whether session tags are loaded
	LoadTags bool

	// LoadClaudeSession controls whether Claude Code session data is loaded
	LoadClaudeSession bool
}

LoadOptions controls what child data is loaded for sessions. This allows selective loading to optimize performance by avoiding unnecessary data retrieval.

func (LoadOptions) WithDiffContent

func (o LoadOptions) WithDiffContent() LoadOptions

WithDiffContent returns a copy of options with diff content loading enabled.

func (LoadOptions) WithTags

func (o LoadOptions) WithTags() LoadOptions

WithTags returns a copy of options with tag loading enabled.

func (LoadOptions) WithoutDiffContent

func (o LoadOptions) WithoutDiffContent() LoadOptions

WithoutDiffContent returns a copy of options with diff content loading disabled.

func (LoadOptions) WithoutTags

func (o LoadOptions) WithoutTags() LoadOptions

WithoutTags returns a copy of options with tag loading disabled.

type MigrationOptions

type MigrationOptions struct {
	// JSONPath is the path to the existing JSON state file
	JSONPath string

	// SQLitePath is the path where the SQLite database will be created
	SQLitePath string

	// BackupPath is the path where the JSON backup will be saved
	BackupPath string

	// ForceOverwrite allows overwriting existing SQLite database
	ForceOverwrite bool

	// DryRun performs validation without actually migrating
	DryRun bool
}

MigrationOptions configures the migration from JSON to SQLite

type MigrationResult

type MigrationResult struct {
	TotalSessions      int
	MigratedSessions   int
	SkippedSessions    int
	Errors             []string
	Duration           time.Duration
	BackupCreated      bool
	BackupPath         string
	SQLiteDatabasePath string
}

MigrationResult contains the results of the migration process

func MigrateJSONToEnt

func MigrateJSONToEnt(opts MigrationOptions) (*MigrationResult, error)

MigrateJSONToEnt migrates session data from JSON to Ent ORM storage.

type OutputConsumer

type OutputConsumer func(data []byte)

OutputConsumer is a callback that receives terminal output from external sessions.

type PTYAccess

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

PTYAccess provides thread-safe access to a tmux session's PTY for reading and writing. It wraps the PTY file descriptor with synchronization primitives to enable concurrent access from multiple goroutines (e.g., command execution, response streaming, status monitoring).

func NewPTYAccess

func NewPTYAccess(sessionName string, pty *os.File, buffer *CircularBuffer) *PTYAccess

NewPTYAccess creates a new PTYAccess wrapper for a PTY file descriptor. The buffer parameter specifies the circular buffer for storing PTY output history.

func (*PTYAccess) Close

func (p *PTYAccess) Close() error

Close marks the PTY access as closed and prevents further operations. It does NOT close the underlying PTY file descriptor - that's handled by the tmux session.

func (*PTYAccess) GetBuffer

func (p *PTYAccess) GetBuffer() []byte

GetBuffer returns the most recent output from the circular buffer. This provides access to historical PTY output without blocking. Returns a copy of the buffer contents to prevent concurrent modification issues.

func (*PTYAccess) GetRecentOutput

func (p *PTYAccess) GetRecentOutput(n int) []byte

GetRecentOutput returns the last n bytes from the circular buffer. This is useful for status detection and response streaming.

func (*PTYAccess) GetSessionName

func (p *PTYAccess) GetSessionName() string

GetSessionName returns the name of the session this PTY access is for.

func (*PTYAccess) IsClosed

func (p *PTYAccess) IsClosed() bool

IsClosed returns whether the PTY access has been closed.

func (*PTYAccess) Read

func (p *PTYAccess) Read(buf []byte) (int, error)

Read reads data from the PTY in a thread-safe manner. This is a blocking call that will wait for data to be available. Returns the number of bytes read and any error encountered.

func (*PTYAccess) UpdatePTY

func (p *PTYAccess) UpdatePTY(pty *os.File) error

UpdatePTY updates the underlying PTY file descriptor. This is used when the PTY needs to be refreshed (e.g., after detach/reattach).

func (*PTYAccess) Write

func (p *PTYAccess) Write(data []byte) (int, error)

Write writes data to the PTY in a thread-safe manner. Returns the number of bytes written and any error encountered.

type PTYCategory

type PTYCategory int

PTYCategory represents grouping of PTYs

const (
	PTYCategorySquad    PTYCategory = iota // Squad-managed sessions
	PTYCategoryOrphaned                    // Unmanaged Claude instances
	PTYCategoryOther                       // Other tools (aider, etc.)
)

func (PTYCategory) String

func (c PTYCategory) String() string

type PTYConnection

type PTYConnection struct {
	Path         string            // /dev/pts/12
	PID          int               // Process ID
	Command      string            // "claude" or "aider"
	SessionName  string            // Associated squad session (if any)
	Status       PTYStatus         // Current status
	LastActivity time.Time         // Last activity timestamp
	Controller   *ClaudeController // Connected controller (if any)

	// Ownership and management metadata
	IsManaged       bool   // True if this is a squad-managed session
	TmuxSocket      string // Which tmux server socket (empty = default)
	TmuxSessionName string // Full tmux session name
	CanAttach       bool   // Whether attach operations are allowed
	CanDestroy      bool   // Whether destroy operations are allowed
	Owner           string // "squad" for managed, "external" for discovered
}

PTYConnection represents a discovered PTY

func (*PTYConnection) GetDisplayName

func (conn *PTYConnection) GetDisplayName() string

GetDisplayName returns a human-readable name for the PTY

func (*PTYConnection) GetPTYBasename

func (conn *PTYConnection) GetPTYBasename() string

GetPTYBasename returns just the PTY number (e.g., "12" from "/dev/pts/12")

func (*PTYConnection) GetStatusColor

func (conn *PTYConnection) GetStatusColor() string

GetStatusColor returns a color code for PTY status

func (*PTYConnection) GetStatusIcon

func (conn *PTYConnection) GetStatusIcon() string

GetStatusIcon returns a visual indicator for PTY status

type PTYDiscovery

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

PTYDiscovery manages PTY discovery and monitoring

func NewPTYDiscovery

func NewPTYDiscovery() *PTYDiscovery

NewPTYDiscovery creates a new PTY discovery service with default configuration

func NewPTYDiscoveryWithConfig

func NewPTYDiscoveryWithConfig(config PTYDiscoveryConfig) *PTYDiscovery

NewPTYDiscoveryWithConfig creates a new PTY discovery service with custom configuration

func (*PTYDiscovery) GetConnection

func (pd *PTYDiscovery) GetConnection(path string) *PTYConnection

GetConnection returns a specific PTY connection by path

func (*PTYDiscovery) GetConnections

func (pd *PTYDiscovery) GetConnections() []*PTYConnection

GetConnections returns all discovered PTY connections

func (*PTYDiscovery) GetConnectionsByCategory

func (pd *PTYDiscovery) GetConnectionsByCategory() map[PTYCategory][]*PTYConnection

GetConnectionsByCategory returns PTYs grouped by category

func (*PTYDiscovery) Refresh

func (pd *PTYDiscovery) Refresh() error

Refresh performs a full PTY discovery scan

func (*PTYDiscovery) SetSessions

func (pd *PTYDiscovery) SetSessions(sessions []*Instance)

SetSessions updates the session map for correlation

func (*PTYDiscovery) Start

func (pd *PTYDiscovery) Start()

Start begins PTY discovery monitoring

func (*PTYDiscovery) Stop

func (pd *PTYDiscovery) Stop()

Stop halts PTY discovery monitoring

type PTYDiscoveryConfig

type PTYDiscoveryConfig struct {
	// Primary tmux server socket for squad-managed sessions
	// Empty string means use the default tmux server
	PrimarySocket string

	// ExternalSockets are additional tmux servers to scan for external instances
	// Only used when Mode is Extended or Full
	ExternalSockets []string

	// Mode controls discovery scope and permissions
	Mode DiscoveryMode

	// ManagedPrefix is the tmux session prefix for squad-managed sessions
	// Default: "staplersquad_"
	ManagedPrefix string

	// DiscoverExternal enables discovery of non-prefixed Claude instances
	// Automatically enabled for Extended and Full modes
	DiscoverExternal bool

	// AllowExternalAttach permits attaching to external instances
	// Only effective in Full mode
	AllowExternalAttach bool

	// RequireConfirmation requires user confirmation for external operations
	// Recommended to keep true for safety
	RequireConfirmation bool

	// DiscoveryInterval controls how often to refresh discovery
	DiscoveryInterval time.Duration

	// ParallelDiscovery enables parallel scanning of multiple tmux servers
	ParallelDiscovery bool
}

PTYDiscoveryConfig controls PTY discovery scope and behavior

func DefaultPTYDiscoveryConfig

func DefaultPTYDiscoveryConfig() PTYDiscoveryConfig

DefaultPTYDiscoveryConfig returns the default discovery configuration

func (*PTYDiscoveryConfig) CanAttachExternal

func (c *PTYDiscoveryConfig) CanAttachExternal() bool

CanAttachExternal returns true if attaching to external instances is allowed

func (*PTYDiscoveryConfig) ShouldDiscoverExternal

func (c *PTYDiscoveryConfig) ShouldDiscoverExternal() bool

ShouldDiscoverExternal returns true if external instances should be discovered

type PTYStatus

type PTYStatus int

PTYStatus represents the current state of a PTY

const (
	PTYReady PTYStatus = iota // Waiting for input
	PTYBusy                   // Executing command
	PTYIdle                   // No activity
	PTYError                  // Error state
)

func (PTYStatus) String

func (s PTYStatus) String() string

type PendingApproval

type PendingApproval struct {
	Request      *detection.ApprovalRequest
	Decision     *PolicyDecision
	ReceivedAt   time.Time
	ExpiresAt    time.Time
	Status       PendingApprovalStatus
	UserResponse *detection.ApprovalResponse
}

PendingApproval represents an approval request awaiting action.

type PendingApprovalStatus

type PendingApprovalStatus string

PendingApprovalStatus tracks the state of a pending approval.

const (
	PendingStatusAwaiting  PendingApprovalStatus = "awaiting"
	PendingStatusProcessed PendingApprovalStatus = "processed"
	PendingStatusExpired   PendingApprovalStatus = "expired"
	PendingStatusCancelled PendingApprovalStatus = "cancelled"
)

type PolicyAction

type PolicyAction string

PolicyAction specifies what to do when a policy matches.

const (
	ActionAutoApprove PolicyAction = "auto_approve"
	ActionAutoReject  PolicyAction = "auto_reject"
	ActionPrompt      PolicyAction = "prompt"
	ActionLog         PolicyAction = "log_only"
)

type PolicyAuditEntry

type PolicyAuditEntry struct {
	Timestamp      time.Time                  `json:"timestamp"`
	RequestID      string                     `json:"request_id"`
	PolicyID       string                     `json:"policy_id"`
	PolicyName     string                     `json:"policy_name"`
	Action         PolicyAction               `json:"action"`
	MatchedRequest *detection.ApprovalRequest `json:"matched_request"`
	Reason         string                     `json:"reason"`
}

PolicyAuditEntry records policy evaluation results.

type PolicyCondition

type PolicyCondition struct {
	Field    string `json:"field"`    // Field to check (e.g., "command", "file_path")
	Operator string `json:"operator"` // "equals", "contains", "regex", "not_contains"
	Value    string `json:"value"`    // Value to compare against
	// contains filtered or unexported fields
}

PolicyCondition represents a single condition that must be met.

type PolicyDecision

type PolicyDecision struct {
	Request       *detection.ApprovalRequest `json:"request"`
	Timestamp     time.Time                  `json:"timestamp"`
	Decision      PolicyAction               `json:"decision"`
	Matched       bool                       `json:"matched"`
	MatchedPolicy *ApprovalPolicy            `json:"matched_policy,omitempty"`
	Reason        string                     `json:"reason"`
}

PolicyDecision represents the result of policy evaluation.

type PolicyEngine

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

PolicyEngine manages approval policies and evaluates approval requests.

func NewPolicyEngine

func NewPolicyEngine() *PolicyEngine

NewPolicyEngine creates a new approval policy engine.

func (*PolicyEngine) AddPolicy

func (pe *PolicyEngine) AddPolicy(policy *ApprovalPolicy) error

AddPolicy adds a new approval policy.

func (*PolicyEngine) ClearAuditLog

func (pe *PolicyEngine) ClearAuditLog()

ClearAuditLog removes all audit log entries.

func (*PolicyEngine) Evaluate

func (pe *PolicyEngine) Evaluate(request *detection.ApprovalRequest) (*PolicyDecision, error)

Evaluate evaluates an approval request against all policies.

func (*PolicyEngine) GetAuditLog

func (pe *PolicyEngine) GetAuditLog(limit int) []PolicyAuditEntry

GetAuditLog returns recent audit log entries.

func (*PolicyEngine) GetPolicy

func (pe *PolicyEngine) GetPolicy(id string) *ApprovalPolicy

GetPolicy retrieves a policy by ID.

func (*PolicyEngine) GetStatistics

func (pe *PolicyEngine) GetStatistics() PolicyStatistics

GetStatistics returns statistics about policy usage.

func (*PolicyEngine) ListPolicies

func (pe *PolicyEngine) ListPolicies() []*ApprovalPolicy

ListPolicies returns all policies, sorted by priority.

func (*PolicyEngine) RemovePolicy

func (pe *PolicyEngine) RemovePolicy(id string) bool

RemovePolicy removes a policy by ID.

func (*PolicyEngine) SetMaxAuditLog

func (pe *PolicyEngine) SetMaxAuditLog(max int)

SetMaxAuditLog sets the maximum number of audit log entries to keep.

func (*PolicyEngine) UpdatePolicy

func (pe *PolicyEngine) UpdatePolicy(updated *ApprovalPolicy) error

UpdatePolicy updates an existing policy.

type PolicyStatistics

type PolicyStatistics struct {
	TotalPolicies     int
	EnabledPolicies   int
	TotalEvaluations  int
	AutoApprovals     int
	AutoRejections    int
	PromptedApprovals int
	LoggedOnly        int
}

PolicyStatistics provides summary statistics.

type Priority

type Priority = queue.Priority

Priority re-export

type RepoPathManager

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

RepoPathManager handles GOPATH-style repository path management. Repositories are stored in a consistent location based on their URL:

  • ~/.stapler-squad/repos/github.com/owner/repo (main clone)
  • Worktrees are created relative to the main repo as needed

func NewRepoPathManager

func NewRepoPathManager() *RepoPathManager

NewRepoPathManager creates a new RepoPathManager with the default base directory.

func NewRepoPathManagerWithBase

func NewRepoPathManagerWithBase(baseDir string) *RepoPathManager

NewRepoPathManagerWithBase creates a RepoPathManager with a custom base directory.

func (*RepoPathManager) EnsureRepoCloned

func (m *RepoPathManager) EnsureRepoCloned(ref *GitHubRef) (string, error)

EnsureRepoCloned ensures the repository is cloned to the local path. If already cloned, it fetches the latest changes. Returns the path to the cloned repository.

func (*RepoPathManager) GetCloneURL

func (m *RepoPathManager) GetCloneURL(ref *GitHubRef) string

GetCloneURL returns the git clone URL for a GitHub ref.

func (*RepoPathManager) GetRepoPath

func (m *RepoPathManager) GetRepoPath(ref *GitHubRef) string

GetRepoPath returns the local path where a GitHub repo should be stored. Format: ~/.stapler-squad/repos/github.com/owner/repo

func (*RepoPathManager) ResolveGitHubInput

func (m *RepoPathManager) ResolveGitHubInput(input string) (localPath string, ref *GitHubRef, err error)

ResolveGitHubInput takes a GitHub URL/shorthand and returns a resolved path. It clones the repo if necessary and returns the local path. Also returns the parsed GitHubRef for storing metadata.

type Repository

type Repository interface {
	// Create inserts a new session into storage
	Create(ctx context.Context, data InstanceData) error

	// Update modifies an existing session in storage
	Update(ctx context.Context, data InstanceData) error

	// Delete removes a session from storage by title
	Delete(ctx context.Context, title string) error

	// Get retrieves a single session by title with full child data
	// For selective loading, use GetWithOptions instead
	Get(ctx context.Context, title string) (*InstanceData, error)

	// GetWithOptions retrieves a single session with selective child data loading
	// Use LoadOptions presets (LoadMinimal, LoadSummary, LoadFull) or custom options
	GetWithOptions(ctx context.Context, title string, options LoadOptions) (*InstanceData, error)

	// List retrieves all sessions with summary child data (no diff content)
	// For selective loading, use ListWithOptions instead
	List(ctx context.Context) ([]InstanceData, error)

	// ListWithOptions retrieves all sessions with selective child data loading
	// Use LoadOptions presets (LoadMinimal, LoadSummary, LoadFull) or custom options
	ListWithOptions(ctx context.Context, options LoadOptions) ([]InstanceData, error)

	// ListByStatus retrieves sessions filtered by status with summary child data
	// For selective loading, use ListByStatusWithOptions instead
	ListByStatus(ctx context.Context, status Status) ([]InstanceData, error)

	// ListByStatusWithOptions retrieves sessions filtered by status with selective loading
	ListByStatusWithOptions(ctx context.Context, status Status, options LoadOptions) ([]InstanceData, error)

	// ListByTag retrieves sessions with a specific tag with summary child data
	// For selective loading, use ListByTagWithOptions instead
	ListByTag(ctx context.Context, tag string) ([]InstanceData, error)

	// ListByTagWithOptions retrieves sessions with a specific tag with selective loading
	ListByTagWithOptions(ctx context.Context, tag string, options LoadOptions) ([]InstanceData, error)

	// UpdateTimestamps efficiently updates only timestamp fields for a session
	// This is optimized for frequent updates from WebSocket terminal streaming
	UpdateTimestamps(ctx context.Context, title string, lastTerminalUpdate, lastMeaningfulOutput time.Time, lastOutputSignature string) error

	// Close performs cleanup and releases resources
	Close() error

	// GetSession retrieves a session using the new Session domain model.
	// Use ContextOptions to control which optional contexts are loaded.
	// Returns nil if session not found.
	GetSession(ctx context.Context, title string, opts ContextOptions) (*Session, error)

	// ListSessions retrieves all sessions using the new Session domain model.
	// Use ContextOptions to control which optional contexts are loaded.
	ListSessions(ctx context.Context, opts ContextOptions) ([]*Session, error)

	// CreateSession creates a new session from the Session domain model.
	CreateSession(ctx context.Context, session *Session) error

	// UpdateSession updates an existing session using the Session domain model.
	UpdateSession(ctx context.Context, session *Session) error
}

Repository defines the interface for session persistence operations. This abstraction allows multiple storage backends (SQLite, JSON, etc.) while maintaining a consistent API for session management.

type RepositoryOption

type RepositoryOption func(interface{}) error

RepositoryOption is a function that configures a repository

func WithDatabasePath

func WithDatabasePath(path string) RepositoryOption

WithDatabasePath sets the database file path for the repository

type ResponseChunk

type ResponseChunk struct {
	Data      []byte
	Timestamp time.Time
	Error     error
}

ResponseChunk represents a chunk of output from the Claude instance.

type ResponseStream

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

ResponseStream manages real-time streaming of Claude instance responses to multiple subscribers. It reads from the PTY access layer and broadcasts output to all active subscribers.

func NewResponseStream

func NewResponseStream(sessionName string, ptyAccess *PTYAccess) *ResponseStream

NewResponseStream creates a new response stream for the given session. The bufferSize parameter determines how many chunks can be buffered per subscriber.

func NewResponseStreamWithBuffer

func NewResponseStreamWithBuffer(sessionName string, ptyAccess *PTYAccess, bufferSize int) *ResponseStream

NewResponseStreamWithBuffer creates a response stream with a custom buffer size.

func (*ResponseStream) GetBufferSize

func (rs *ResponseStream) GetBufferSize() int

GetBufferSize returns the current buffer size setting.

func (*ResponseStream) GetSubscriberCount

func (rs *ResponseStream) GetSubscriberCount() int

GetSubscriberCount returns the number of active subscribers.

func (*ResponseStream) GetSubscriberIDs

func (rs *ResponseStream) GetSubscriberIDs() []string

GetSubscriberIDs returns the IDs of all active subscribers.

func (*ResponseStream) GetSubscriberInfo

func (rs *ResponseStream) GetSubscriberInfo(subscriberID string) (created time.Time, exists bool)

GetSubscriberInfo returns information about a specific subscriber.

func (*ResponseStream) IsStarted

func (rs *ResponseStream) IsStarted() bool

IsStarted returns whether the stream is currently active.

func (*ResponseStream) SetBufferSize

func (rs *ResponseStream) SetBufferSize(size int)

SetBufferSize sets the buffer size for future subscribers. Does not affect existing subscribers.

func (*ResponseStream) Start

func (rs *ResponseStream) Start(ctx context.Context) error

Start begins streaming responses from the PTY to all subscribers. This is a non-blocking call that starts a background goroutine. Use the provided context to stop the stream.

func (*ResponseStream) Stop

func (rs *ResponseStream) Stop() error

Stop stops the response stream and closes all subscriber channels. This is a blocking call that waits for the streaming goroutine to finish.

func (*ResponseStream) Subscribe

func (rs *ResponseStream) Subscribe(subscriberID string) (<-chan ResponseChunk, error)

Subscribe registers a new subscriber and returns a channel for receiving response chunks. The subscriber ID should be unique. Returns an error if the ID is already in use.

func (*ResponseStream) Unsubscribe

func (rs *ResponseStream) Unsubscribe(subscriberID string) error

Unsubscribe removes a subscriber and closes their channel.

type RestartState

type RestartState struct {
	// Working directory to restore
	WorkingDir string
	// Claude session ID for --resume flag
	ClaudeSessionID string
	// Environment variables to restore
	Environment map[string]string
	// Original command/program
	Program string
	// AutoYes flag
	AutoYes bool
	// Original prompt
	Prompt string
}

RestartState holds the state needed to restart a session

type ReviewItem

type ReviewItem = queue.ReviewItem

ReviewItem re-export

type ReviewQueue

type ReviewQueue = queue.ReviewQueue

ReviewQueue re-export

func NewReviewQueue

func NewReviewQueue() *ReviewQueue

NewReviewQueue creates a new review queue.

type ReviewQueueObserver

type ReviewQueueObserver = queue.ReviewQueueObserver

ReviewQueueObserver re-export

type ReviewQueuePoller

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

ReviewQueuePoller automatically monitors sessions and adds them to the review queue when they become idle or need attention.

func NewReviewQueuePoller

func NewReviewQueuePoller(queue *ReviewQueue, statusManager *InstanceStatusManager, storage *Storage) *ReviewQueuePoller

NewReviewQueuePoller creates a new poller for automatically managing the review queue. The storage parameter is optional (can be nil) but required for persisting LastAddedToQueue timestamps.

func NewReviewQueuePollerWithConfig

func NewReviewQueuePollerWithConfig(queue *ReviewQueue, statusManager *InstanceStatusManager, storage *Storage, config ReviewQueuePollerConfig) *ReviewQueuePoller

NewReviewQueuePollerWithConfig creates a poller with custom configuration. The storage parameter is optional (can be nil) but required for persisting LastAddedToQueue timestamps.

func (*ReviewQueuePoller) AddInstance

func (rqp *ReviewQueuePoller) AddInstance(instance *Instance)

AddInstance adds a single instance to monitor.

func (*ReviewQueuePoller) CheckSession

func (rqp *ReviewQueuePoller) CheckSession(inst *Instance)

CheckSession checks a single session immediately (exported for ReactiveQueueManager). This allows external components to trigger immediate re-evaluation without waiting for the next poll cycle, providing <100ms feedback on user interactions.

func (*ReviewQueuePoller) FindInstance

func (rqp *ReviewQueuePoller) FindInstance(sessionID string) *Instance

FindInstance finds an instance by session ID (exported for ReactiveQueueManager). Returns nil if the instance is not found in the monitored list.

func (*ReviewQueuePoller) GetConfig

func (rqp *ReviewQueuePoller) GetConfig() ReviewQueuePollerConfig

GetConfig returns the current configuration.

func (*ReviewQueuePoller) GetInstances

func (rqp *ReviewQueuePoller) GetInstances() []*Instance

GetInstances returns a snapshot of all live in-memory instances held by the poller. Use this instead of LoadInstances() for read-only operations to avoid the side effect of FromInstanceData() calling Start() on every non-paused instance.

func (*ReviewQueuePoller) GetMonitoredCount

func (rqp *ReviewQueuePoller) GetMonitoredCount() int

GetMonitoredCount returns the number of instances being monitored.

func (*ReviewQueuePoller) IsRunning

func (rqp *ReviewQueuePoller) IsRunning() bool

IsRunning returns true if the poller is currently running.

func (*ReviewQueuePoller) RemoveInstance

func (rqp *ReviewQueuePoller) RemoveInstance(instanceTitle string)

RemoveInstance removes an instance from monitoring.

func (*ReviewQueuePoller) SetApprovalProvider

func (rqp *ReviewQueuePoller) SetApprovalProvider(provider ApprovalMetadataProvider)

SetApprovalProvider sets the approval metadata provider for enriching review queue items.

func (*ReviewQueuePoller) SetInstances

func (rqp *ReviewQueuePoller) SetInstances(instances []*Instance)

SetInstances sets the list of instances to monitor.

func (*ReviewQueuePoller) Start

func (rqp *ReviewQueuePoller) Start(ctx context.Context)

Start begins polling for idle sessions.

func (*ReviewQueuePoller) Stop

func (rqp *ReviewQueuePoller) Stop()

Stop stops the poller.

func (*ReviewQueuePoller) UpdateConfig

func (rqp *ReviewQueuePoller) UpdateConfig(config ReviewQueuePollerConfig)

UpdateConfig updates the poller configuration.

type ReviewQueuePollerConfig

type ReviewQueuePollerConfig struct {
	PollInterval       time.Duration // How often to check sessions
	IdleThreshold      time.Duration // Duration before considering session idle and adding to queue
	InputWaitDuration  time.Duration // Time waiting for input before flagging
	StalenessThreshold time.Duration // Duration since last meaningful output before considering stale
}

ReviewQueuePollerConfig contains configuration for the review queue poller.

func DefaultReviewQueuePollerConfig

func DefaultReviewQueuePollerConfig() ReviewQueuePollerConfig

DefaultReviewQueuePollerConfig returns sensible defaults for polling.

type ReviewQueueStatistics

type ReviewQueueStatistics = queue.ReviewQueueStatistics

ReviewQueueStatistics re-export

type ReviewState

type ReviewState struct {
	// LastAcknowledged tracks when the user last acknowledged this session in the review queue.
	// Sessions acknowledged after their last update won't appear in the queue until they update again.
	LastAcknowledged time.Time

	// LastAddedToQueue tracks when this session was last added to the review queue.
	// Used to prevent notification spam by enforcing a minimum re-add interval.
	LastAddedToQueue time.Time

	// LastTerminalUpdate is the timestamp of the last output received from the terminal (any output).
	LastTerminalUpdate time.Time

	// LastMeaningfulOutput is the timestamp of the last meaningful output (excludes tmux status banners).
	// Used by the review queue to determine session staleness.
	LastMeaningfulOutput time.Time

	// LastOutputSignature is a hash of the terminal content, used to detect actual changes
	// vs app restarts with unchanged content (prevents false "new activity" notifications).
	LastOutputSignature string

	// LastViewed tracks when the user last interacted with this session
	// (viewing the terminal, attaching via tmux, or viewing session details).
	// Used for smarter review queue notifications (don't notify if just viewed).
	LastViewed time.Time

	// LastPromptDetected is the timestamp when we last detected a prompt requiring user input.
	// Used to distinguish new prompts from the same prompt re-appearing.
	LastPromptDetected time.Time

	// LastPromptSignature is a hash of the prompt content (last 10 lines before cursor).
	// Used to determine if this is the same prompt or a new one.
	LastPromptSignature string

	// LastUserResponse is the timestamp when the user last provided input/interaction.
	// Used to determine if user responded AFTER a prompt was detected.
	LastUserResponse time.Time

	// ProcessingGraceUntil is the deadline for waiting for the session to respond after
	// user interaction. If the session shows no activity by this time, it may be re-added
	// to the review queue.
	ProcessingGraceUntil time.Time
}

ReviewState holds all timestamps and state related to the review queue and terminal activity tracking for a session. It is embedded in Instance so all field accesses remain unchanged.

Fields are protected by Instance.stateMutex; do not lock ReviewState independently. Methods on ReviewState are intentionally non-locking — callers must hold stateMutex if concurrent access is possible.

Direct field access via Go embedding promotion (inst.LastMeaningfulOutput etc.) is used by:

  • session/review_queue_poller.go: reads LastMeaningfulOutput, LastAcknowledged, LastAddedToQueue, ProcessingGraceUntil, LastPromptDetected, LastPromptSignature, LastUserResponse, LastViewed, LastTerminalUpdate, LastOutputSignature
  • server/dependencies.go: reads LastMeaningfulOutput, LastTerminalUpdate, LastAddedToQueue, LastAcknowledged
  • server/adapters/instance_adapter.go: reads LastTerminalUpdate, LastMeaningfulOutput
  • server/review_queue_manager.go: writes LastUserResponse directly

All access is either within the session package (under stateMutex) or through Instance methods that acquire stateMutex.

TODO: Migrate cross-package field accesses (server/) to accessor methods to enable future encapsulation of ReviewState as a composed (non-embedded) field.

func (*ReviewState) ComputePromptSignature

func (rs *ReviewState) ComputePromptSignature(content string) string

ComputePromptSignature computes a hash of the prompt content using the last 10 lines. Returns "" if content is empty. Caller may call this without holding any lock.

func (*ReviewState) DetectAndTrackPrompt

func (rs *ReviewState) DetectAndTrackPrompt(content string, statusInfo InstanceStatusInfo, sessionTitle string) bool

DetectAndTrackPrompt detects whether the current status represents a new user-facing prompt and records it. Returns true only when a NEW prompt is detected (signature changed or first). Caller must hold Instance.stateMutex when writing prompt fields.

func (*ReviewState) IsAcknowledgedAfterOutput

func (rs *ReviewState) IsAcknowledgedAfterOutput() bool

IsAcknowledgedAfterOutput returns true if the user acknowledged this session more recently than the last meaningful terminal output — meaning no new output has occurred since the user last dismissed the session from the review queue. Returns false when LastMeaningfulOutput is zero: if no output has ever been recorded, the acknowledgment cannot logically be "after" output, so the session is not snoozed. Caller must hold the relevant mutex if concurrent access is possible.

func (*ReviewState) IsInProcessingGracePeriod

func (rs *ReviewState) IsInProcessingGracePeriod() bool

IsInProcessingGracePeriod returns true if the session is within its processing grace window. Caller must hold the relevant mutex if concurrent access is possible.

func (*ReviewState) TimeSinceLastMeaningfulOutput

func (rs *ReviewState) TimeSinceLastMeaningfulOutput(createdAt time.Time) time.Duration

TimeSinceLastMeaningfulOutput returns how long ago meaningful terminal output was received. If LastMeaningfulOutput is zero, returns the duration since the given createdAt time. Caller must hold the relevant mutex if concurrent access is possible.

func (*ReviewState) TimeSinceLastTerminalUpdate

func (rs *ReviewState) TimeSinceLastTerminalUpdate(createdAt time.Time) time.Duration

TimeSinceLastTerminalUpdate returns how long ago any terminal output was received. If LastTerminalUpdate is zero, returns the duration since the given createdAt time. Caller must hold the relevant mutex if concurrent access is possible.

func (*ReviewState) UpdateTimestamps

func (rs *ReviewState) UpdateTimestamps(rawContent, filteredContent string, shouldUpdateMeaningful bool, sessionTitle string)

UpdateTimestamps updates terminal activity timestamps based on processed content.

  • rawContent: original captured output, used for the LastTerminalUpdate non-blank check.
  • filteredContent: rawContent with tmux banners stripped, used for signature computation.
  • shouldUpdateMeaningful: true when the content carries meaningful signal (not just banners).
  • sessionTitle: used only for structured debug logging.

Caller must hold Instance.stateMutex.

func (*ReviewState) UserRespondedAfterPrompt

func (rs *ReviewState) UserRespondedAfterPrompt() bool

UserRespondedAfterPrompt returns true if the user responded (LastUserResponse) after a prompt was detected (LastPromptDetected), indicating the session is no longer waiting. Caller must hold the relevant mutex if concurrent access is possible.

type RevisionTarget

type RevisionTarget struct {
	ID          string
	ShortID     string
	Description string
	Author      string
	Timestamp   time.Time
	IsCurrent   bool
}

RevisionTarget represents a revision as a switch target

type Session

type Session struct {
	// Identity
	ID        string    `json:"id"`
	Title     string    `json:"title"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`

	// Process
	Status  Status `json:"status"`
	Program string `json:"program"`

	// Configuration
	AutoYes bool   `json:"auto_yes,omitempty"`
	Prompt  string `json:"prompt,omitempty"`

	// Optional contexts (nil = not loaded or not applicable)
	Git        *GitContext        `json:"git,omitempty"`
	Filesystem *FilesystemContext `json:"filesystem,omitempty"`
	Terminal   *TerminalContext   `json:"terminal,omitempty"`
	UI         *UIPreferences     `json:"ui,omitempty"`
	Activity   *ActivityTracking  `json:"activity,omitempty"`
	Cloud      *CloudContext      `json:"cloud,omitempty"`
}

Session represents the core domain entity for an AI agent session. It contains only universally required fields, with optional contexts for deployment-specific functionality.

Context types are defined in contexts.go: - GitContext: Git repository, branch, PR integration - FilesystemContext: Paths, working directories, worktree detection - TerminalContext: Terminal dimensions, tmux configuration - UIPreferences: Categories, tags, display preferences - ActivityTracking: Timestamps, output signatures, queue tracking - CloudContext: Cloud provider, API configuration

func InstanceToSession

func InstanceToSession(i *Instance) *Session

InstanceToSession converts a legacy Instance to the new Session type. This adapter enables gradual migration while maintaining backward compatibility. It populates all relevant contexts from the Instance fields.

func NewSession

func NewSession(title, program string) *Session

NewSession creates a new Session with the required fields. Optional contexts can be added using the With* methods.

func (*Session) GetBranch

func (s *Session) GetBranch() string

GetBranch returns the Git branch name, or empty string if no Git context.

func (*Session) GetCategory

func (s *Session) GetCategory() string

GetCategory returns the UI category, or empty string if no UI preferences.

func (*Session) GetLastMeaningfulOutput

func (s *Session) GetLastMeaningfulOutput() time.Time

GetLastMeaningfulOutput returns when the session had meaningful output, or zero time if no activity tracking.

func (*Session) GetLastViewed

func (s *Session) GetLastViewed() time.Time

GetLastViewed returns when the session was last viewed, or zero time if no activity tracking.

func (*Session) GetPath

func (s *Session) GetPath() string

GetPath returns the filesystem project path, or empty string if no filesystem context.

func (*Session) GetTags

func (s *Session) GetTags() []string

GetTags returns the UI tags, or empty slice if no UI preferences.

func (*Session) GetTerminalDimensions

func (s *Session) GetTerminalDimensions() (width, height int)

GetTerminalDimensions returns the terminal width and height, or 0,0 if no terminal context.

func (*Session) GetTmuxSessionName

func (s *Session) GetTmuxSessionName() string

GetTmuxSessionName returns the tmux session name, or empty string if no terminal context.

func (*Session) GetWorkingDir

func (s *Session) GetWorkingDir() string

GetWorkingDir returns the working directory, or empty string if no filesystem context.

func (*Session) HasActivityTracking

func (s *Session) HasActivityTracking() bool

HasActivityTracking returns true if activity tracking is available.

func (*Session) HasCloudContext

func (s *Session) HasCloudContext() bool

HasCloudContext returns true if cloud context is available.

func (*Session) HasFilesystemContext

func (s *Session) HasFilesystemContext() bool

HasFilesystemContext returns true if filesystem context is available.

func (*Session) HasGitContext

func (s *Session) HasGitContext() bool

HasGitContext returns true if Git context is available.

func (*Session) HasTerminalContext

func (s *Session) HasTerminalContext() bool

HasTerminalContext returns true if terminal context is available.

func (*Session) HasUIPreferences

func (s *Session) HasUIPreferences() bool

HasUIPreferences returns true if UI preferences are available.

func (*Session) IsCloudConfigured

func (s *Session) IsCloudConfigured() bool

IsCloudConfigured returns true if the cloud context is properly configured.

func (*Session) NeedsReviewQueueAttention

func (s *Session) NeedsReviewQueueAttention() bool

NeedsReviewQueueAttention returns true if session has unacknowledged output.

func (*Session) WithActivityTracking

func (s *Session) WithActivityTracking(activity *ActivityTracking) *Session

WithActivityTracking adds activity tracking to the session.

func (*Session) WithCloudContext

func (s *Session) WithCloudContext(cloud *CloudContext) *Session

WithCloudContext adds cloud context to the session.

func (*Session) WithFilesystemContext

func (s *Session) WithFilesystemContext(fs *FilesystemContext) *Session

WithFilesystemContext adds filesystem context to the session.

func (*Session) WithGitContext

func (s *Session) WithGitContext(git *GitContext) *Session

WithGitContext adds Git context to the session.

func (*Session) WithTerminalContext

func (s *Session) WithTerminalContext(terminal *TerminalContext) *Session

WithTerminalContext adds terminal context to the session.

func (*Session) WithUIPreferences

func (s *Session) WithUIPreferences(ui *UIPreferences) *Session

WithUIPreferences adds UI preferences to the session.

type SessionHealthChecker

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

SessionHealthChecker manages session health validation and recovery

func NewSessionHealthChecker

func NewSessionHealthChecker(storage *Storage) *SessionHealthChecker

NewSessionHealthChecker creates a new session health checker

func (*SessionHealthChecker) CheckAllSessions

func (h *SessionHealthChecker) CheckAllSessions() ([]HealthCheckResult, error)

CheckAllSessions performs a health check on all active sessions

func (*SessionHealthChecker) RecoverUnhealthySessions

func (h *SessionHealthChecker) RecoverUnhealthySessions() error

RecoverUnhealthySessions attempts to recover all unhealthy sessions

func (*SessionHealthChecker) ScheduledHealthCheck

func (h *SessionHealthChecker) ScheduledHealthCheck(interval time.Duration, stopChan <-chan struct{})

ScheduledHealthCheck runs health checks at regular intervals

type SessionType

type SessionType string

SessionType indicates the type of session workflow to use

const (
	// SessionTypeDirectory creates a simple directory session without git worktree
	SessionTypeDirectory SessionType = "directory"
	// SessionTypeNewWorktree creates a new git worktree for the session
	SessionTypeNewWorktree SessionType = "new_worktree"
	// SessionTypeExistingWorktree uses an existing git worktree
	SessionTypeExistingWorktree SessionType = "existing_worktree"
)

func (SessionType) IsValid

func (st SessionType) IsValid() bool

IsValid reports whether st is a recognized session type.

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
	// NeedsApproval is if the instance is waiting for user approval on a prompt.
	NeedsApproval
	// Creating is the status when the instance is being initialized.
	Creating
	// Stopped is a terminal state: the instance has been shut down and cannot transition further.
	Stopped
)

func StatusFromDetected

func StatusFromDetected(detected detection.DetectedStatus) Status

StatusFromDetected maps a DetectedStatus to the corresponding lifecycle Status. This documents the intended transition table even though the review queue poller currently does not update Instance.Status directly on every detection cycle.

Key design decisions captured here:

  • Error and TestsFailing keep the lifecycle as Running because the instance process is still executing; only the output signals a problem.
  • NeedsApproval and InputRequired both map to NeedsApproval because both mean "the instance is blocked, waiting for the user".

func (Status) String

func (s Status) String() string

String returns a human-readable name for the status.

type StatusChange

type StatusChange struct {
	Timestamp time.Time
	Status    detection.DetectedStatus
	Context   string
}

StatusChange represents a change in detected status during execution.

type Storage

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

Storage handles saving and loading instances via the repository backend.

func NewStorageWithRepository

func NewStorageWithRepository(repo Repository) (*Storage, error)

NewStorageWithRepository creates a Storage backed by a Repository.

func (*Storage) AddInstance

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

AddInstance adds a new instance to storage. Unlike SaveInstances, this does not require instance.Started() to be true.

func (*Storage) Close

func (s *Storage) Close() error

Close performs graceful shutdown of storage.

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

func (s *Storage) GetSession(ctx context.Context, title string, opts ContextOptions) (*Session, error)

GetSession retrieves a session by title using the Session domain model. Use ContextOptions presets (ContextMinimal, ContextUIView, etc.) to control what is loaded.

func (*Storage) ListSessions

func (s *Storage) ListSessions(ctx context.Context, opts ContextOptions) ([]*Session, error)

ListSessions retrieves all sessions using the Session domain model. Use ContextOptions presets (ContextMinimal, ContextUIView, etc.) to control what is loaded.

func (*Storage) LoadInstances

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

LoadInstances loads the list of instances from the repository.

func (*Storage) SaveInstances

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

SaveInstances upserts each started instance into the repository.

func (*Storage) SaveInstancesSync

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

SaveInstancesSync saves instances synchronously (same as SaveInstances for the repo backend).

func (*Storage) SaveSession

func (s *Storage) SaveSession(ctx context.Context, session *Session) error

SaveSession upserts a session using the Session domain model. If the session exists it is updated; otherwise it is created. Deprecated InstanceData-based methods (SaveInstances, LoadInstances) remain for backward compatibility.

func (*Storage) UpdateInstance

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

UpdateInstance updates an existing instance in storage.

func (*Storage) UpdateInstanceLastAddedToQueue

func (s *Storage) UpdateInstanceLastAddedToQueue(title string, lastAddedToQueue time.Time) error

UpdateInstanceLastAddedToQueue updates ONLY the LastAddedToQueue field for a specific instance.

func (*Storage) UpdateInstanceLastUserResponse

func (s *Storage) UpdateInstanceLastUserResponse(title string, lastUserResponse time.Time) error

UpdateInstanceLastUserResponse updates just the LastUserResponse timestamp for a specific instance.

func (*Storage) UpdateInstanceProcessingGrace

func (s *Storage) UpdateInstanceProcessingGrace(title string, processingGraceUntil time.Time) error

UpdateInstanceProcessingGrace updates just the ProcessingGraceUntil timestamp for a specific instance.

func (*Storage) UpdateInstanceTimestampsOnly

func (s *Storage) UpdateInstanceTimestampsOnly(title string, lastTerminalUpdate, lastMeaningfulOutput time.Time, lastOutputSignature string, lastViewed time.Time) error

UpdateInstanceTimestampsOnly updates ONLY the timestamp fields in storage without creating Instance objects. This preserves in-memory state like controllers. This is critical for WebSocket terminal streaming which updates timestamps frequently.

type Subscriber

type Subscriber struct {
	ID string
	Ch chan ResponseChunk
	// contains filtered or unexported fields
}

Subscriber represents a client that is receiving response chunks.

type TagManager

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

TagManager provides CRUD operations for session tags. It is a pure data structure with no I/O or external dependencies. Thread safety is provided by Instance.stateMutex -- callers must hold the lock when calling TagManager methods.

TagManager stores a pointer to the Instance.Tags slice so that mutations are automatically visible via inst.Tags (used by instance_adapter.go, review_queue_poller.go, and ToInstanceData for serialization).

func NewTagManager

func NewTagManager(tags *[]string) TagManager

NewTagManager creates a TagManager backed by the given slice pointer.

func (*TagManager) Add

func (tm *TagManager) Add(tag string) error

Add adds a tag if it does not already exist and does not exceed MaxTagLength. Returns ErrTagTooLong if the tag exceeds MaxTagLength. Returns ErrDuplicateTag if the tag already exists.

func (*TagManager) All

func (tm *TagManager) All() []string

All returns a copy of the tag slice.

func (*TagManager) Has

func (tm *TagManager) Has(tag string) bool

Has returns true if the tag exists.

func (*TagManager) Remove

func (tm *TagManager) Remove(tag string)

Remove removes a tag by value. No-op if the tag does not exist.

func (*TagManager) Set

func (tm *TagManager) Set(tags []string) error

Set replaces all tags with a new deduplicated set. Returns ErrTagTooLong on the first tag that exceeds MaxTagLength.

type TerminalContext

type TerminalContext struct {
	// Height is the terminal height in rows
	Height int `json:"height,omitempty"`

	// Width is the terminal width in columns
	Width int `json:"width,omitempty"`

	// TmuxSessionName is the name of the tmux session
	TmuxSessionName string `json:"tmux_session_name,omitempty"`

	// TmuxPrefix is the prefix used for tmux session naming
	TmuxPrefix string `json:"tmux_prefix,omitempty"`

	// TmuxServerSocket is the path to the tmux server socket
	TmuxServerSocket string `json:"tmux_server_socket,omitempty"`

	// TerminalType indicates the terminal backend type
	// Possible values: "tmux", "mux", "pty", "web"
	TerminalType string `json:"terminal_type,omitempty"`
}

TerminalContext represents the terminal-related context for a session. This includes terminal dimensions, tmux configuration, and terminal type.

func (*TerminalContext) IsEmpty

func (t *TerminalContext) IsEmpty() bool

IsEmpty returns true if the TerminalContext has no meaningful data

type TerminalState

type TerminalState struct {

	// Terminal dimensions
	Rows int
	Cols int

	// Terminal screen buffer (2D grid)
	Grid [][]Cell

	// Cursor state
	CursorRow     int
	CursorCol     int
	CursorVisible bool

	// Current text style for new characters
	CurrentStyle CellStyle

	// State version for delta tracking
	Version uint64
	// contains filtered or unexported fields
}

TerminalState maintains the current terminal screen state

func NewTerminalState

func NewTerminalState(rows, cols int) *TerminalState

NewTerminalState creates a new terminal state with given dimensions

func (*TerminalState) Clone

func (ts *TerminalState) Clone() *TerminalState

Clone creates a deep copy of the terminal state

func (*TerminalState) GenerateDelta

func (ts *TerminalState) GenerateDelta(fromState *TerminalState) *sessionv1.TerminalData

GenerateDelta generates a delta from another state to this state

func (*TerminalState) GenerateState

func (ts *TerminalState) GenerateState() *sessionv1.TerminalData

GenerateState generates a complete terminal state message (MOSH-style). This is the preferred method over GenerateDelta for robust synchronization.

func (*TerminalState) ProcessOutput

func (ts *TerminalState) ProcessOutput(data []byte) error

ProcessOutput processes terminal output and updates state

func (*TerminalState) Resize

func (ts *TerminalState) Resize(rows, cols int)

Resize resizes the terminal state

type TimeRestriction

type TimeRestriction struct {
	DaysOfWeek []time.Weekday `json:"days_of_week"` // Empty = all days
	StartHour  int            `json:"start_hour"`   // 0-23
	EndHour    int            `json:"end_hour"`     // 0-23
}

TimeRestriction limits when a policy is active.

type TmuxProcessManager

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

TmuxProcessManager owns the tmux session and preview-size tracking state that were previously scattered as bare fields on Instance.

Instance keeps thin wrapper methods (with started/paused guards) that delegate here. TmuxProcessManager itself has no knowledge of Instance lifecycle; it only manages the tmux session and the preview-resize bookkeeping.

func (*TmuxProcessManager) Attach

func (tm *TmuxProcessManager) Attach() (chan struct{}, error)

Attach returns a channel that closes when the user detaches from the session.

func (*TmuxProcessManager) CapturePaneContent

func (tm *TmuxProcessManager) CapturePaneContent() (string, error)

CapturePaneContent returns the current visible pane content.

func (*TmuxProcessManager) CapturePaneContentRaw

func (tm *TmuxProcessManager) CapturePaneContentRaw() (string, error)

CapturePaneContentRaw returns pane content with ANSI escape codes preserved.

func (*TmuxProcessManager) CapturePaneContentWithOptions

func (tm *TmuxProcessManager) CapturePaneContentWithOptions(startLine, endLine string) (string, error)

CapturePaneContentWithOptions captures pane content between startLine and endLine.

func (*TmuxProcessManager) CaptureViewport

func (tm *TmuxProcessManager) CaptureViewport(lines int) (string, error)

CaptureViewport captures the last N lines of the pane. If lines <= 0, captures the current viewport height.

func (*TmuxProcessManager) Close

func (tm *TmuxProcessManager) Close() error

Close terminates the tmux session.

func (*TmuxProcessManager) DetachSafely

func (tm *TmuxProcessManager) DetachSafely() error

DetachSafely detaches the current tmux client from the session without closing it.

func (*TmuxProcessManager) DoesSessionExist

func (tm *TmuxProcessManager) DoesSessionExist() bool

DoesSessionExist returns true if the tmux session name is registered with the server.

func (*TmuxProcessManager) FilterBanners

func (tm *TmuxProcessManager) FilterBanners(content string) (string, int)

FilterBanners strips banner/header content from terminal output.

func (*TmuxProcessManager) GetCursorPosition

func (tm *TmuxProcessManager) GetCursorPosition() (x, y int, err error)

GetCursorPosition returns the current cursor column and row (0-based).

func (*TmuxProcessManager) GetPTY

func (tm *TmuxProcessManager) GetPTY() (*os.File, error)

GetPTY returns the PTY master file for reading terminal output.

func (*TmuxProcessManager) GetPaneDimensions

func (tm *TmuxProcessManager) GetPaneDimensions() (width, height int, err error)

GetPaneDimensions returns the current pane width and height.

func (*TmuxProcessManager) HasMeaningfulContent

func (tm *TmuxProcessManager) HasMeaningfulContent(content string) bool

HasMeaningfulContent reports whether the terminal output contains substantive content.

func (*TmuxProcessManager) HasSession

func (tm *TmuxProcessManager) HasSession() bool

HasSession reports whether a tmux session has been initialized.

func (*TmuxProcessManager) HasUpdated

func (tm *TmuxProcessManager) HasUpdated() (updated bool, hasPrompt bool)

HasUpdated reports whether the pane content has changed since the last check.

func (*TmuxProcessManager) IsAlive

func (tm *TmuxProcessManager) IsAlive() bool

IsAlive reports whether the tmux session process is still running.

func (*TmuxProcessManager) RefreshClient

func (tm *TmuxProcessManager) RefreshClient() error

RefreshClient forces the tmux client to redraw.

func (*TmuxProcessManager) RestoreWithWorkDir

func (tm *TmuxProcessManager) RestoreWithWorkDir(workDir string) error

RestoreWithWorkDir re-attaches to an existing session in the given directory.

func (*TmuxProcessManager) SendKeys

func (tm *TmuxProcessManager) SendKeys(keys string) (int, error)

SendKeys sends a string of keys to the tmux session and returns the number of bytes written.

func (*TmuxProcessManager) SendPromptWithEnter

func (tm *TmuxProcessManager) SendPromptWithEnter(prompt string) error

SendPromptWithEnter sends text to the session followed by Enter key. Includes a brief pause between text and Enter to prevent interpretation issues.

func (*TmuxProcessManager) Session

func (tm *TmuxProcessManager) Session() *tmux.TmuxSession

Session returns the underlying tmux session (may be nil before Start).

func (*TmuxProcessManager) SetDetachedSize

func (tm *TmuxProcessManager) SetDetachedSize(width, height int, instanceTitle string) error

SetDetachedSize updates the tmux window dimensions without attaching. Rate-limits PTY-not-initialized warnings to avoid log spam.

func (*TmuxProcessManager) SetSession

func (tm *TmuxProcessManager) SetSession(s *tmux.TmuxSession)

SetSession replaces the underlying tmux session. Used by tests and by Instance.start() when reusing a pre-created session.

func (*TmuxProcessManager) SetWindowSize

func (tm *TmuxProcessManager) SetWindowSize(cols, rows int) error

SetWindowSize resizes the tmux window to the given columns and rows.

func (*TmuxProcessManager) Start

func (tm *TmuxProcessManager) Start(dir string) error

Start creates and starts the tmux session in the given directory.

func (*TmuxProcessManager) TapEnter

func (tm *TmuxProcessManager) TapEnter() error

TapEnter sends an Enter key to the session.

type UIPreferences

type UIPreferences struct {
	// Category is the organizational category for the session
	Category string `json:"category,omitempty"`

	// IsExpanded indicates if the session is expanded in grouped views
	IsExpanded bool `json:"is_expanded,omitempty"`

	// Tags are the user-defined tags for multi-dimensional organization
	Tags []string `json:"tags,omitempty"`

	// GroupingStrategy is the current grouping mode (e.g., "category", "tag", "branch")
	GroupingStrategy string `json:"grouping_strategy,omitempty"`

	// SortOrder is the preferred sort order (e.g., "name", "date", "status")
	SortOrder string `json:"sort_order,omitempty"`
}

UIPreferences represents the UI-related preferences for a session. This includes categorization, tags, and display preferences.

func (*UIPreferences) HasTag

func (u *UIPreferences) HasTag(tag string) bool

HasTag returns true if the UIPreferences contains the specified tag

func (*UIPreferences) IsEmpty

func (u *UIPreferences) IsEmpty() bool

IsEmpty returns true if the UIPreferences has no meaningful data

type UsageLimit

type UsageLimit struct {
	MaxUses     int           `json:"max_uses"`     // 0 = unlimited
	TimeWindow  time.Duration `json:"time_window"`  // 0 = no time window
	PerApproval bool          `json:"per_approval"` // Track per approval type vs globally
}

UsageLimit restricts how many times a policy can be used.

type VCSInfo

type VCSInfo struct {
	// VCSType is "jj" or "git"
	VCSType string
	// HasJJ indicates if JJ is available
	HasJJ bool
	// HasGit indicates if Git is available
	HasGit bool
	// IsColocated indicates if this is a JJ+Git colocated repo
	IsColocated bool
	// RepoPath is the repository root path
	RepoPath string
	// CurrentBookmark is the current branch/bookmark name
	CurrentBookmark string
	// CurrentRevision is the current revision (short ID)
	CurrentRevision string
	// HasUncommittedChanges indicates if there are uncommitted changes
	HasUncommittedChanges bool
	// ModifiedFileCount is the count of modified/added/deleted files
	ModifiedFileCount int
}

VCSInfo contains version control information for a session

type WorkspaceSwitchRequest

type WorkspaceSwitchRequest struct {
	// Type is the type of switch operation
	Type WorkspaceSwitchType
	// Target is the destination (directory path, revision/branch, or worktree path)
	Target string
	// ChangeStrategy determines how to handle uncommitted changes
	ChangeStrategy vcs.ChangeStrategy
	// CreateIfMissing creates the bookmark/branch/worktree if it doesn't exist
	CreateIfMissing bool
	// BaseRevision is the base for new bookmark creation (empty = current)
	BaseRevision string
	// VCSPreference overrides the default VCS preference for this operation
	VCSPreference vcs.VCSPreference
}

WorkspaceSwitchRequest represents a request to switch the workspace

type WorkspaceSwitchResult

type WorkspaceSwitchResult struct {
	// Success indicates if the switch was successful
	Success bool
	// Error contains any error that occurred
	Error error
	// PreviousRevision is the revision before the switch
	PreviousRevision string
	// CurrentRevision is the revision after the switch
	CurrentRevision string
	// VCSType is the VCS that was used
	VCSType vcs.VCSType
	// ChangesHandled describes how uncommitted changes were handled
	ChangesHandled string
}

WorkspaceSwitchResult contains the result of a workspace switch operation

type WorkspaceSwitchType

type WorkspaceSwitchType int

WorkspaceSwitchType defines the type of workspace switch operation

const (
	// SwitchTypeDirectory is a simple directory change (no VCS, no restart)
	SwitchTypeDirectory WorkspaceSwitchType = iota
	// SwitchTypeRevision switches to a different revision/branch
	SwitchTypeRevision
	// SwitchTypeWorktree switches to or creates a different worktree
	SwitchTypeWorktree
)

func (WorkspaceSwitchType) String

func (t WorkspaceSwitchType) String() string

type WorktreeInfo

type WorktreeInfo struct {
	// IsWorktree is true if the path is a git worktree (not the main repo)
	IsWorktree bool
	// MainRepoPath is the path to the main repository's .git directory
	// For a worktree at ~/.stapler-squad/worktrees/foo, this might be /path/to/main/repo/.git
	MainRepoPath string
	// MainRepoRoot is the working directory root of the main repository
	MainRepoRoot string
	// RemoteURL is the git remote origin URL (e.g., https://github.com/owner/repo.git)
	RemoteURL string
	// GitHubOwner is the owner extracted from a GitHub remote URL
	GitHubOwner string
	// GitHubRepo is the repo name extracted from a GitHub remote URL
	GitHubRepo string
}

WorktreeInfo contains information about a git worktree

func DetectWorktree

func DetectWorktree(path string) (*WorktreeInfo, error)

DetectWorktree checks if the given path is a git worktree and extracts relevant info. Returns WorktreeInfo with IsWorktree=false if it's not a worktree or not a git repo.

type WorktreeTarget

type WorktreeTarget struct {
	Name       string
	Path       string
	Bookmark   string
	RevisionID string
	IsCurrent  bool
}

WorktreeTarget represents a worktree as a switch target

Directories

Path Synopsis
ent
tag
Package framebuffer provides Mosh-style terminal state diffing.
Package framebuffer provides Mosh-style terminal state diffing.
Package mux provides PTY multiplexing functionality for external Claude sessions.
Package mux provides PTY multiplexing functionality for external Claude sessions.
Package vcs provides an abstraction layer over version control systems.
Package vcs provides an abstraction layer over version control systems.
Package workspace provides workspace tracking and status management for stapler-squad sessions.
Package workspace provides workspace tracking and status management for stapler-squad sessions.

Jump to

Keyboard shortcuts

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