session

package
v0.8.7 Latest Latest
Warning

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

Go to latest
Published: Jan 5, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultProfile is the name of the default profile
	DefaultProfile = "default"

	// ProfilesDirName is the directory containing all profiles
	ProfilesDirName = "profiles"

	// ConfigFileName is the global config file name
	ConfigFileName = "config.json"
)
View Source
const DefaultGroupName = "My Sessions"

DefaultGroupName is the display name for the default group where ungrouped sessions go

View Source
const DefaultGroupPath = "my-sessions"

DefaultGroupPath is the normalized path for the default group (used for lookups and protection)

View Source
const TierThresholdBalanced = 500 * 1024 * 1024

TierThresholdBalanced is the max size for balanced tier (500MB)

View Source
const TierThresholdInstant = 100 * 1024 * 1024

TierThresholdInstant is the max size for instant tier (100MB)

View Source
const UserConfigFileName = "config.toml"

UserConfigFileName is the TOML config file for user preferences

Variables

This section is empty.

Functions

func ClearMCPCache added in v0.5.3

func ClearMCPCache(projectPath string)

ClearMCPCache invalidates the MCP cache for a project path

func ClearProjectMCPs added in v0.5.3

func ClearProjectMCPs(projectPath string) error

ClearProjectMCPs removes all MCPs from projects[path].mcpServers in Claude's config

func CreateExampleConfig added in v0.3.0

func CreateExampleConfig() error

CreateExampleConfig creates an example config file if none exists

func CreateProfile added in v0.3.0

func CreateProfile(profile string) error

CreateProfile creates a new empty profile

func DeleteProfile added in v0.3.0

func DeleteProfile(profile string) error

DeleteProfile deletes a profile and all its data

func GetAgentDeckDir added in v0.3.0

func GetAgentDeckDir() (string, error)

GetAgentDeckDir returns the base agent-deck directory (~/.agent-deck)

func GetAvailableMCPNames added in v0.5.3

func GetAvailableMCPNames() []string

GetAvailableMCPNames returns sorted list of MCP names from config.toml

func GetAvailableMCPs added in v0.5.3

func GetAvailableMCPs() map[string]MCPDef

GetAvailableMCPs returns MCPs from config.toml as a map This replaces the old catalog-based approach with explicit user configuration

func GetClaudeConfigDir added in v0.4.1

func GetClaudeConfigDir() string

GetClaudeConfigDir returns the Claude config directory Priority: 1) CLAUDE_CONFIG_DIR env, 2) UserConfig setting, 3) ~/.claude

func GetClaudeSessionID added in v0.4.1

func GetClaudeSessionID(projectPath string) (string, error)

GetClaudeSessionID returns the ACTIVE session ID for a project path It first tries to find the currently running session by checking recently modified .jsonl files, then falls back to lastSessionId from config

func GetConfigPath added in v0.3.0

func GetConfigPath() (string, error)

GetConfigPath returns the path to the global config file

func GetDefaultTool added in v0.4.3

func GetDefaultTool() string

GetDefaultTool returns the user's preferred default tool for new sessions Returns empty string if not configured (defaults to shell)

func GetEffectiveProfile added in v0.3.0

func GetEffectiveProfile(explicit string) string

GetEffectiveProfile returns the profile to use, considering: 1. Explicitly provided profile (from -p flag) 2. Environment variable AGENTDECK_PROFILE 3. Config default profile 4. Fallback to "default"

func GetGeminiConfigDir added in v0.8.0

func GetGeminiConfigDir() string

GetGeminiConfigDir returns ~/.gemini Unlike Claude, Gemini has no GEMINI_CONFIG_DIR env var override

func GetGeminiMCPNames added in v0.8.1

func GetGeminiMCPNames() []string

GetGeminiMCPNames returns names of configured MCPs from settings.json

func GetGeminiSessionsDir added in v0.8.0

func GetGeminiSessionsDir(projectPath string) string

GetGeminiSessionsDir returns the chats directory for a project Format: ~/.gemini/tmp/<project_hash>/chats/

func GetGlobalMCPNames added in v0.5.3

func GetGlobalMCPNames() []string

GetGlobalMCPNames returns the names of MCPs currently in Claude's global config

func GetGlobalPool added in v0.6.2

func GetGlobalPool() *mcppool.Pool

GetGlobalPool returns the global pool instance (may be nil if disabled)

func GetGroupLevel

func GetGroupLevel(path string) int

GetGroupLevel returns the nesting level of a group (0 for root, 1 for child, etc.)

func GetProfileDir added in v0.3.0

func GetProfileDir(profile string) (string, error)

GetProfileDir returns the path to a specific profile's directory

func GetProfilesDir added in v0.3.0

func GetProfilesDir() (string, error)

GetProfilesDir returns the path to the profiles directory

func GetProjectMCPNames added in v0.5.3

func GetProjectMCPNames(projectPath string) []string

GetProjectMCPNames returns MCPs from projects[path].mcpServers in Claude's config

func GetStoragePath

func GetStoragePath() (string, error)

GetStoragePath returns the path to the sessions.json file for the default profile. DEPRECATED: Use GetStoragePathForProfile for explicit profile support.

func GetStoragePathForProfile added in v0.3.0

func GetStoragePathForProfile(profile string) (string, error)

GetStoragePathForProfile returns the path to the sessions.json file for a specific profile.

func GetToolBusyPatterns added in v0.3.0

func GetToolBusyPatterns(toolName string) []string

GetToolBusyPatterns returns busy patterns for a tool (custom + built-in)

func GetToolIcon added in v0.3.0

func GetToolIcon(toolName string) string

GetToolIcon returns the icon for a tool (custom or built-in)

func GetUserConfigPath added in v0.3.0

func GetUserConfigPath() (string, error)

GetUserConfigPath returns the path to the user config file

func GroupByProject

func GroupByProject(instances []*Instance) map[string][]*Instance

GroupByProject groups sessions by their parent project directory

func HashProjectPath added in v0.8.0

func HashProjectPath(projectPath string) string

HashProjectPath generates SHA256 hash of absolute project path This matches Gemini CLI's project hash algorithm for session storage VERIFIED: echo -n "/Users/ashesh" | shasum -a 256 NOTE: Must resolve symlinks (e.g., /tmp -> /private/tmp on macOS)

func InitializeGlobalPool added in v0.6.2

func InitializeGlobalPool(ctx context.Context, config *UserConfig, sessions []*Instance) (*mcppool.Pool, error)

InitializeGlobalPool creates and starts the global MCP pool

func ListProfiles added in v0.3.0

func ListProfiles() ([]string, error)

ListProfiles returns all available profile names

func NeedsMigration added in v0.3.0

func NeedsMigration() (bool, error)

NeedsMigration checks if migration from old layout is needed

func ProfileExists added in v0.3.0

func ProfileExists(profile string) (bool, error)

ProfileExists checks if a profile exists

func SaveConfig added in v0.3.0

func SaveConfig(config *Config) error

SaveConfig saves the global configuration

func SetDefaultProfile added in v0.3.0

func SetDefaultProfile(profile string) error

SetDefaultProfile sets the default profile in the config

func ShutdownGlobalPool added in v0.6.2

func ShutdownGlobalPool() error

ShutdownGlobalPool stops the global pool

func TierName added in v0.5.3

func TierName(tier SearchTier) string

TierName returns a human-readable name for the tier

func ToggleLocalMCP added in v0.5.3

func ToggleLocalMCP(projectPath, mcpName string) error

ToggleLocalMCP toggles a Local MCP on/off It respects the existing mode (whitelist vs blacklist) or initializes with blacklist

func UpdateClaudeSessionsWithDedup added in v0.4.1

func UpdateClaudeSessionsWithDedup(instances []*Instance)

UpdateClaudeSessionsWithDedup clears duplicate Claude session IDs across instances. The oldest session (by CreatedAt) keeps its ID, newer duplicates are cleared. With tmux env being authoritative, duplicates shouldn't occur in normal use, but we handle them defensively for loaded/migrated sessions.

func WriteGeminiMCPSettings added in v0.8.1

func WriteGeminiMCPSettings(enabledNames []string) error

WriteGeminiMCPSettings writes MCPs to ~/.gemini/settings.json Preserves existing config fields (security, theme, etc.) Uses atomic write with .tmp file for safety

func WriteGlobalMCP added in v0.5.3

func WriteGlobalMCP(enabledNames []string) error

WriteGlobalMCP adds or removes MCPs from Claude's global config This modifies ~/.claude-work/.claude.json → mcpServers

func WriteMCPJsonFromConfig added in v0.5.3

func WriteMCPJsonFromConfig(projectPath string, enabledNames []string) error

WriteMCPJsonFromConfig writes enabled MCPs from config.toml to project's .mcp.json

Types

type ClaudeConfig added in v0.4.1

type ClaudeConfig struct {
	Projects map[string]ClaudeProject `json:"projects"`
}

ClaudeConfig represents the structure of .claude.json

type ClaudeProject added in v0.4.1

type ClaudeProject struct {
	LastSessionId string `json:"lastSessionId"`
}

ClaudeProject represents a project entry in Claude's config

type ClaudeSettings added in v0.4.1

type ClaudeSettings struct {
	// ConfigDir is the path to Claude's config directory
	// Default: ~/.claude (or CLAUDE_CONFIG_DIR env var)
	ConfigDir string `toml:"config_dir"`

	// DangerousMode enables --dangerously-skip-permissions flag for Claude sessions
	// Default: false
	DangerousMode bool `toml:"dangerous_mode"`
}

ClaudeSettings defines Claude Code configuration

type Config added in v0.3.0

type Config struct {
	// DefaultProfile is the profile to use when none is specified
	DefaultProfile string `json:"default_profile"`

	// LastUsed is the most recently used profile (for future use)
	LastUsed string `json:"last_used,omitempty"`

	// Version tracks config format for future migrations
	Version int `json:"version"`
}

Config represents the global agent-deck configuration

func LoadConfig added in v0.3.0

func LoadConfig() (*Config, error)

LoadConfig loads the global configuration

type FileTracker added in v0.5.3

type FileTracker struct {
	Path       string
	LastOffset int64
	LastSize   int64
	LastMod    time.Time
}

FileTracker tracks file state for incremental updates

type GeminiMCPConfig added in v0.8.1

type GeminiMCPConfig struct {
	MCPServers map[string]MCPServerConfig `json:"mcpServers"`
}

GeminiMCPConfig represents settings.json structure VERIFIED: Actual settings.json does NOT have mcp.allowed/excluded (Simplified structure compared to research docs)

type GeminiSessionInfo added in v0.8.1

type GeminiSessionInfo struct {
	SessionID    string // Full UUID
	Filename     string // session-2025-12-26T15-09-4d8fcb4d.json
	StartTime    time.Time
	LastUpdated  time.Time
	MessageCount int
}

GeminiSessionInfo holds parsed session metadata

func ListGeminiSessions added in v0.8.1

func ListGeminiSessions(projectPath string) ([]GeminiSessionInfo, error)

ListGeminiSessions returns all sessions for a project path Scans ~/.gemini/tmp/<hash>/chats/ and parses session files Sorted by LastUpdated (most recent first)

type GlobalSearchIndex added in v0.5.3

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

GlobalSearchIndex manages the searchable session index

func NewGlobalSearchIndex added in v0.5.3

func NewGlobalSearchIndex(claudeDir string, config GlobalSearchSettings) (*GlobalSearchIndex, error)

NewGlobalSearchIndex creates a new search index

func (*GlobalSearchIndex) Close added in v0.5.3

func (idx *GlobalSearchIndex) Close()

Close shuts down the index

func (*GlobalSearchIndex) EntryCount added in v0.5.3

func (idx *GlobalSearchIndex) EntryCount() int

EntryCount returns the number of indexed entries

func (*GlobalSearchIndex) FuzzySearch added in v0.5.3

func (idx *GlobalSearchIndex) FuzzySearch(query string) []*SearchResult

FuzzySearch performs fuzzy matching with typo tolerance

func (*GlobalSearchIndex) GetTier added in v0.5.3

func (idx *GlobalSearchIndex) GetTier() SearchTier

GetTier returns the current search tier

func (*GlobalSearchIndex) IsLoading added in v0.5.3

func (idx *GlobalSearchIndex) IsLoading() bool

IsLoading returns true if the index is still loading

func (*GlobalSearchIndex) Search added in v0.5.3

func (idx *GlobalSearchIndex) Search(query string) []*SearchResult

Search performs a simple substring search

type GlobalSearchSettings added in v0.5.3

type GlobalSearchSettings struct {
	// Enabled enables/disables global search feature (default: true when loaded via LoadUserConfig)
	Enabled bool `toml:"enabled"`

	// Tier controls search strategy: "auto", "instant", "balanced", "disabled"
	// auto: Auto-detect based on data size (recommended)
	// instant: Force full in-memory (fast, uses more RAM)
	// balanced: Force LRU cache mode (slower, capped RAM)
	// disabled: Disable global search entirely
	Tier string `toml:"tier"`

	// MemoryLimitMB caps memory usage for search index (default: 100)
	// Only applies to balanced tier
	MemoryLimitMB int `toml:"memory_limit_mb"`

	// RecentDays limits search to sessions from last N days (0 = all)
	// Reduces index size for users with long history (default: 90)
	RecentDays int `toml:"recent_days"`

	// IndexRateLimit limits files indexed per second during background indexing
	// Lower = less CPU impact (default: 20)
	IndexRateLimit int `toml:"index_rate_limit"`
}

GlobalSearchSettings defines global conversation search configuration

type Group

type Group struct {
	Name     string
	Path     string // Full path like "projects" or "projects/devops"
	Expanded bool
	Sessions []*Instance
	Order    int
}

Group represents a group of sessions

type GroupData

type GroupData struct {
	Name     string `json:"name"`
	Path     string `json:"path"`
	Expanded bool   `json:"expanded"`
	Order    int    `json:"order"`
}

GroupData represents serializable group data

type GroupTree

type GroupTree struct {
	Groups    map[string]*Group // path -> group
	GroupList []*Group          // Ordered list of groups
	Expanded  map[string]bool   // Collapsed state persistence
}

GroupTree manages hierarchical session organization

func NewGroupTree

func NewGroupTree(instances []*Instance) *GroupTree

NewGroupTree creates a new group tree from instances

func NewGroupTreeWithGroups

func NewGroupTreeWithGroups(instances []*Instance, storedGroups []*GroupData) *GroupTree

NewGroupTreeWithGroups creates a group tree from instances and stored group data

func (*GroupTree) AddSession

func (t *GroupTree) AddSession(inst *Instance)

AddSession adds a session to the appropriate group

func (*GroupTree) CollapseGroup

func (t *GroupTree) CollapseGroup(path string)

CollapseGroup collapses a group

func (*GroupTree) CreateGroup

func (t *GroupTree) CreateGroup(name string) *Group

CreateGroup creates a new empty group

func (*GroupTree) CreateSubgroup

func (t *GroupTree) CreateSubgroup(parentPath, name string) *Group

CreateSubgroup creates a new empty group under a parent group

func (*GroupTree) DeleteGroup

func (t *GroupTree) DeleteGroup(path string) []*Instance

DeleteGroup deletes a group, all its subgroups, and moves all sessions to default

func (*GroupTree) ExpandGroup

func (t *GroupTree) ExpandGroup(path string)

ExpandGroup expands a group

func (*GroupTree) ExpandGroupWithParents

func (t *GroupTree) ExpandGroupWithParents(path string)

ExpandGroupWithParents expands a group and all its parent groups This ensures the group and its contents are visible in the flattened view

func (*GroupTree) Flatten

func (t *GroupTree) Flatten() []Item

Flatten returns a flat list of items for cursor navigation

func (*GroupTree) GetAllInstances

func (t *GroupTree) GetAllInstances() []*Instance

GetAllInstances returns all instances in order

func (*GroupTree) GetGroupNames

func (t *GroupTree) GetGroupNames() []string

GetGroupNames returns all group names for selection

func (*GroupTree) GetGroupPaths

func (t *GroupTree) GetGroupPaths() []string

GetGroupPaths returns all group paths for selection

func (*GroupTree) GroupCount

func (t *GroupTree) GroupCount() int

GroupCount returns total group count

func (*GroupTree) MoveGroupDown

func (t *GroupTree) MoveGroupDown(path string)

MoveGroupDown moves a group down in the order (only within siblings at same level)

func (*GroupTree) MoveGroupUp

func (t *GroupTree) MoveGroupUp(path string)

MoveGroupUp moves a group up in the order (only within siblings at same level)

func (*GroupTree) MoveSessionDown

func (t *GroupTree) MoveSessionDown(inst *Instance)

MoveSessionDown moves a session down within its group

func (*GroupTree) MoveSessionToGroup

func (t *GroupTree) MoveSessionToGroup(inst *Instance, newGroupPath string)

MoveSessionToGroup moves a session to a different group

func (*GroupTree) MoveSessionUp

func (t *GroupTree) MoveSessionUp(inst *Instance)

MoveSessionUp moves a session up within its group

func (*GroupTree) RemoveSession

func (t *GroupTree) RemoveSession(inst *Instance)

RemoveSession removes a session from its group

func (*GroupTree) RenameGroup

func (t *GroupTree) RenameGroup(oldPath, newName string)

RenameGroup renames a group and updates all subgroups

func (*GroupTree) SessionCount

func (t *GroupTree) SessionCount() int

SessionCount returns total session count

func (*GroupTree) ShallowCopyForSave added in v0.7.0

func (t *GroupTree) ShallowCopyForSave() *GroupTree

ShallowCopyForSave creates a copy of the GroupTree that's safe to use from a goroutine for saving purposes. It deep copies the Group structs to prevent data races when the main thread modifies group fields (Name, Path, Expanded, Order) while a background goroutine reads them.

func (*GroupTree) SyncWithInstances

func (t *GroupTree) SyncWithInstances(instances []*Instance)

SyncWithInstances updates the tree with a new set of instances while preserving existing group structure (including empty groups)

func (*GroupTree) ToggleGroup

func (t *GroupTree) ToggleGroup(path string)

ToggleGroup toggles the expanded state of a group

type Instance

type Instance struct {
	ID              string    `json:"id"`
	Title           string    `json:"title"`
	ProjectPath     string    `json:"project_path"`
	GroupPath       string    `json:"group_path"`                  // e.g., "projects/devops"
	ParentSessionID string    `json:"parent_session_id,omitempty"` // Links to parent session (makes this a sub-session)
	Command         string    `json:"command"`
	Tool            string    `json:"tool"`
	Status          Status    `json:"status"`
	CreatedAt       time.Time `json:"created_at"`
	LastAccessedAt  time.Time `json:"last_accessed_at,omitempty"` // When user last attached

	// Claude Code integration
	ClaudeSessionID  string    `json:"claude_session_id,omitempty"`
	ClaudeDetectedAt time.Time `json:"claude_detected_at,omitempty"`

	// Gemini CLI integration
	GeminiSessionID  string    `json:"gemini_session_id,omitempty"`
	GeminiDetectedAt time.Time `json:"gemini_detected_at,omitempty"`

	// MCP tracking - which MCPs were loaded when session started/restarted
	// Used to detect pending MCPs (added after session start) and stale MCPs (removed but still running)
	LoadedMCPNames []string `json:"loaded_mcp_names,omitempty"`
	// contains filtered or unexported fields
}

Instance represents a single agent/shell session

func DiscoverExistingTmuxSessions

func DiscoverExistingTmuxSessions(existingInstances []*Instance) ([]*Instance, error)

DiscoverExistingTmuxSessions finds all tmux sessions and converts them to instances

func FilterByQuery

func FilterByQuery(instances []*Instance, query string) []*Instance

FilterByQuery filters sessions by title, project path, tool, or status Supports status filters: "waiting", "running", "idle", "error"

func NewInstance

func NewInstance(title, projectPath string) *Instance

NewInstance creates a new session instance

func NewInstanceWithGroup

func NewInstanceWithGroup(title, projectPath, groupPath string) *Instance

NewInstanceWithGroup creates a new session instance with explicit group

func NewInstanceWithGroupAndTool added in v0.4.1

func NewInstanceWithGroupAndTool(title, projectPath, groupPath, tool string) *Instance

NewInstanceWithGroupAndTool creates a new session with explicit group and tool

func NewInstanceWithTool added in v0.4.1

func NewInstanceWithTool(title, projectPath, tool string) *Instance

NewInstanceWithTool creates a new session with tool-specific initialization

func (*Instance) CanFork added in v0.4.1

func (i *Instance) CanFork() bool

CanFork returns true if this session can be forked

func (*Instance) CanRestart added in v0.4.1

func (i *Instance) CanRestart() bool

CanRestart returns true if the session can be restarted For Claude sessions with known ID: can always restart (interrupt and resume) For Gemini sessions with known ID: can always restart (interrupt and resume) For other sessions: only if dead/error state

func (*Instance) CaptureLoadedMCPs added in v0.5.3

func (i *Instance) CaptureLoadedMCPs()

CaptureLoadedMCPs captures the current MCP names as the "loaded" state This should be called when a session starts or restarts, so we can track which MCPs are actually loaded in the running Claude session vs just configured

func (*Instance) ClearParent added in v0.7.0

func (inst *Instance) ClearParent()

ClearParent removes the parent session link

func (*Instance) CreateForkedInstance added in v0.4.1

func (i *Instance) CreateForkedInstance(newTitle, newGroupPath string) (*Instance, string, error)

CreateForkedInstance creates a new Instance configured for forking

func (*Instance) Exists

func (i *Instance) Exists() bool

Exists checks if the tmux session still exists

func (*Instance) Fork added in v0.4.1

func (i *Instance) Fork(newTitle, newGroupPath string) (string, error)

Fork returns the command to create a forked Claude session Uses capture-resume pattern: starts fork in print mode to get new session ID, stores in tmux environment, then resumes interactively

func (*Instance) GetActualWorkDir added in v0.4.1

func (i *Instance) GetActualWorkDir() string

GetActualWorkDir returns the actual working directory from tmux, or falls back to ProjectPath

func (*Instance) GetLastActivityTime added in v0.5.6

func (inst *Instance) GetLastActivityTime() time.Time

GetLastActivityTime returns when the session was last active (content changed) Returns CreatedAt if no activity has been tracked yet

func (*Instance) GetLastResponse added in v0.7.0

func (i *Instance) GetLastResponse() (*ResponseOutput, error)

GetLastResponse returns the last assistant response from the session For Claude: Parses the JSONL file for the last assistant message For Gemini: Parses the JSON session file for the last assistant message For Codex/Others: Attempts to parse terminal output

func (*Instance) GetMCPInfo added in v0.5.3

func (i *Instance) GetMCPInfo() *MCPInfo

GetMCPInfo returns MCP server information for this session Returns nil if not a Claude or Gemini session

func (*Instance) GetSessionIDFromTmux added in v0.5.0

func (i *Instance) GetSessionIDFromTmux() string

GetSessionIDFromTmux reads Claude session ID from tmux environment This is the primary method for sessions started with the capture-resume pattern

func (*Instance) GetTmuxSession

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

GetTmuxSession returns the tmux session object

func (*Instance) HasUpdated

func (i *Instance) HasUpdated() bool

HasUpdated checks if there's new output since last check

func (*Instance) IsSubSession added in v0.7.0

func (inst *Instance) IsSubSession() bool

IsSubSession returns true if this session has a parent

func (*Instance) Kill

func (i *Instance) Kill() error

Kill terminates the tmux session

func (*Instance) MarkAccessed added in v0.5.3

func (inst *Instance) MarkAccessed()

MarkAccessed updates the LastAccessedAt timestamp to now

func (*Instance) Preview

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

Preview returns the last 3 lines of terminal output

func (*Instance) PreviewFull

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

PreviewFull returns all terminal output

func (*Instance) Restart added in v0.4.1

func (i *Instance) Restart() error

Restart restarts the Claude session For Claude sessions with known ID: sends Ctrl+C twice and resume command to existing session For dead sessions or unknown ID: recreates the tmux session

func (*Instance) SetParent added in v0.7.0

func (inst *Instance) SetParent(parentID string)

SetParent sets the parent session ID

func (*Instance) Start

func (i *Instance) Start() error

Start starts the session in tmux

func (*Instance) StartWithMessage added in v0.6.2

func (i *Instance) StartWithMessage(message string) error

StartWithMessage starts the session and sends an initial message when ready The message is sent synchronously after detecting the agent's prompt This approach is more reliable than embedding send logic in the tmux command Works for Claude, Gemini, OpenCode, and other agents

func (*Instance) UpdateClaudeSession added in v0.4.1

func (i *Instance) UpdateClaudeSession(excludeIDs map[string]bool)

UpdateClaudeSession updates the Claude session ID from tmux environment. The capture-resume pattern (used in Start/Fork/Restart) sets CLAUDE_SESSION_ID in the tmux environment, making this the single authoritative source.

No file scanning fallback - we rely on the consistent capture-resume pattern.

func (*Instance) UpdateGeminiSession added in v0.8.1

func (i *Instance) UpdateGeminiSession(excludeIDs map[string]bool)

UpdateGeminiSession updates the Gemini session ID from tmux environment. The capture-resume pattern (used in Start/Restart) sets GEMINI_SESSION_ID in the tmux environment, making this the single authoritative source.

No file scanning fallback - we rely on the consistent capture-resume pattern.

func (*Instance) UpdateStatus

func (i *Instance) UpdateStatus() error

UpdateStatus updates the session status by checking tmux

func (*Instance) WaitForClaudeSession added in v0.4.1

func (i *Instance) WaitForClaudeSession(maxWait time.Duration) string

WaitForClaudeSession waits for the tmux environment variable to be set. The capture-resume pattern sets CLAUDE_SESSION_ID in tmux env, so we poll for that. Returns the detected session ID or empty string after timeout.

func (*Instance) WaitForClaudeSessionWithExclude added in v0.5.0

func (i *Instance) WaitForClaudeSessionWithExclude(maxWait time.Duration, excludeIDs map[string]bool) string

WaitForClaudeSessionWithExclude waits for the tmux environment variable to be set. The excludeIDs parameter is kept for API compatibility but not used since tmux env is authoritative and won't return duplicate IDs.

type InstanceData

type InstanceData struct {
	ID              string    `json:"id"`
	Title           string    `json:"title"`
	ProjectPath     string    `json:"project_path"`
	GroupPath       string    `json:"group_path"`
	ParentSessionID string    `json:"parent_session_id,omitempty"` // Links to parent session (sub-session support)
	Command         string    `json:"command"`
	Tool            string    `json:"tool"`
	Status          Status    `json:"status"`
	CreatedAt       time.Time `json:"created_at"`
	LastAccessedAt  time.Time `json:"last_accessed_at,omitempty"`
	TmuxSession     string    `json:"tmux_session"`

	// Claude session (persisted for resume after app restart)
	ClaudeSessionID  string    `json:"claude_session_id,omitempty"`
	ClaudeDetectedAt time.Time `json:"claude_detected_at,omitempty"`

	// Gemini session (persisted for resume after app restart)
	GeminiSessionID  string    `json:"gemini_session_id,omitempty"`
	GeminiDetectedAt time.Time `json:"gemini_detected_at,omitempty"`

	// MCP tracking (persisted for sync status display)
	LoadedMCPNames []string `json:"loaded_mcp_names,omitempty"`
}

InstanceData represents the serializable session data

type Item

type Item struct {
	Type                ItemType
	Group               *Group
	Session             *Instance
	Level               int    // Indentation level (0 for root groups, 1 for sessions)
	Path                string // Group path for this item
	IsLastInGroup       bool   // True if this is the last session in its group (for tree rendering)
	RootGroupNum        int    // Pre-computed root group number for hotkey display (1-9, 0 if not a root group)
	IsSubSession        bool   // True if this session has a parent session
	IsLastSubSession    bool   // True if this is the last sub-session of its parent (for tree rendering)
	ParentIsLastInGroup bool   // True if parent session is last top-level item (for tree line rendering)
}

Item represents a single item in the flattened group tree view

type ItemType

type ItemType int

ItemType represents the type of item in the flattened list

const (
	ItemTypeGroup ItemType = iota
	ItemTypeSession
)

type LocalMCP added in v0.6.1

type LocalMCP struct {
	Name       string // MCP name
	SourcePath string // Directory containing the .mcp.json file
}

LocalMCP represents an MCP defined in a local .mcp.json file

type LogSettings added in v0.5.3

type LogSettings struct {
	// MaxSizeMB is the maximum size in MB before a log file is truncated
	// When a log exceeds this size, it keeps only the last MaxLines lines
	// Default: 10 (10MB)
	MaxSizeMB int `toml:"max_size_mb"`

	// MaxLines is the number of lines to keep when truncating
	// Default: 10000
	MaxLines int `toml:"max_lines"`

	// RemoveOrphans removes log files for sessions that no longer exist
	// Default: true
	RemoveOrphans bool `toml:"remove_orphans"`
}

LogSettings defines log file management configuration

func GetLogSettings added in v0.5.3

func GetLogSettings() LogSettings

GetLogSettings returns log management settings with defaults applied

type MCPDef added in v0.5.3

type MCPDef struct {
	// Command is the executable to run (e.g., "npx", "docker", "node")
	// Required for stdio MCPs, optional for HTTP/SSE MCPs
	Command string `toml:"command"`

	// Args are command-line arguments
	Args []string `toml:"args"`

	// Env is optional environment variables
	Env map[string]string `toml:"env"`

	// Description is optional help text shown in the MCP Manager
	Description string `toml:"description"`

	// URL is the endpoint for HTTP/SSE MCPs (e.g., "http://localhost:8000/mcp")
	// If set, this MCP uses HTTP or SSE transport instead of stdio
	URL string `toml:"url"`

	// Transport specifies the MCP transport type: "stdio" (default), "http", or "sse"
	// Only needed when URL is set; defaults to "http" if URL is present
	Transport string `toml:"transport"`
}

MCPDef defines an MCP server configuration for the MCP Manager

func GetMCPDef added in v0.5.3

func GetMCPDef(name string) *MCPDef

GetMCPDef returns a specific MCP definition by name Returns nil if not found

type MCPInfo added in v0.5.3

type MCPInfo struct {
	Global    []string   // From CLAUDE_CONFIG_DIR/.claude.json mcpServers
	Project   []string   // From CLAUDE_CONFIG_DIR/.claude.json projects[path].mcpServers
	LocalMCPs []LocalMCP // From .mcp.json files (walks up parent directories)
}

MCPInfo contains MCP server information for a session

func GetGeminiMCPInfo added in v0.8.1

func GetGeminiMCPInfo(projectPath string) *MCPInfo

GetGeminiMCPInfo reads MCP configuration from settings.json Returns MCPInfo with Global MCPs only (Gemini has no project-level MCPs) VERIFIED: settings.json structure is simple {"mcpServers": {...}}

func GetMCPInfo added in v0.5.3

func GetMCPInfo(projectPath string) *MCPInfo

GetMCPInfo retrieves MCP server information for a project path (cached) It reads from three sources: 1. Global MCPs: CLAUDE_CONFIG_DIR/.claude.json → mcpServers 2. Project MCPs: CLAUDE_CONFIG_DIR/.claude.json → projects[projectPath].mcpServers 3. Local MCPs: {projectPath}/.mcp.json → mcpServers

func (*MCPInfo) AllNames added in v0.5.3

func (m *MCPInfo) AllNames() []string

AllNames returns a deduplicated, sorted list of all MCP names across all sources Used for capturing loaded MCPs at session start for sync tracking

func (*MCPInfo) HasAny added in v0.5.3

func (m *MCPInfo) HasAny() bool

HasAny returns true if any MCPs are configured

func (*MCPInfo) Local added in v0.5.3

func (m *MCPInfo) Local() []string

Local returns MCP names for backward compatibility Use LocalMCPs directly if you need source path information

func (*MCPInfo) Total added in v0.5.3

func (m *MCPInfo) Total() int

Total returns total number of MCPs across all sources

type MCPMode added in v0.5.3

type MCPMode int

MCPMode indicates how MCP enabling/disabling is configured

const (
	MCPModeDefault   MCPMode = iota // No explicit config, all enabled
	MCPModeWhitelist                // enabledMcpjsonServers is set
	MCPModeBlacklist                // disabledMcpjsonServers is set
)

func GetMCPMode added in v0.5.3

func GetMCPMode(projectPath string) MCPMode

GetMCPMode determines the MCP configuration mode for a project

type MCPPoolSettings added in v0.6.2

type MCPPoolSettings struct {
	// Enabled enables HTTP pool mode (default: false)
	Enabled bool `toml:"enabled"`

	// AutoStart starts pool when agent-deck launches (default: true)
	AutoStart bool `toml:"auto_start"`

	// PortStart is the first port in the pool range (default: 8001)
	PortStart int `toml:"port_start"`

	// PortEnd is the last port in the pool range (default: 8050)
	PortEnd int `toml:"port_end"`

	// StartOnDemand starts MCPs lazily on first attach (default: false)
	StartOnDemand bool `toml:"start_on_demand"`

	// ShutdownOnExit stops HTTP servers when agent-deck quits (default: true)
	ShutdownOnExit bool `toml:"shutdown_on_exit"`

	// PoolMCPs is the list of MCPs to run in pool mode
	// Empty = auto-detect common MCPs (memory, exa, firecrawl, etc.)
	PoolMCPs []string `toml:"pool_mcps"`

	// FallbackStdio uses stdio for MCPs without socket support (default: true)
	FallbackStdio bool `toml:"fallback_to_stdio"`

	// ShowStatus shows pool status in TUI (default: true)
	ShowStatus bool `toml:"show_pool_status"`

	// PoolAll pools all MCPs by default (default: false)
	PoolAll bool `toml:"pool_all"`

	// ExcludeMCPs excludes specific MCPs from pool when pool_all = true
	ExcludeMCPs []string `toml:"exclude_mcps"`
}

MCPPoolSettings defines HTTP MCP pool configuration

type MCPServer added in v0.5.3

type MCPServer struct {
	Name    string
	Source  string // "local", "global", "project"
	Enabled bool
}

MCPServer represents an MCP with its enabled state

func GetLocalMCPState added in v0.5.3

func GetLocalMCPState(projectPath string) ([]MCPServer, error)

GetLocalMCPState returns Local MCPs with their enabled state

type MCPServerConfig added in v0.5.3

type MCPServerConfig struct {
	Type    string            `json:"type,omitempty"`
	Command string            `json:"command,omitempty"`
	Args    []string          `json:"args,omitempty"`
	Env     map[string]string `json:"env,omitempty"`
	URL     string            `json:"url,omitempty"` // For HTTP transport
}

MCPServerConfig represents an MCP server configuration (Claude's format)

type MatchRange added in v0.5.3

type MatchRange struct {
	Start int
	End   int
}

MatchRange represents a match position in content

type MigrationResult added in v0.3.0

type MigrationResult struct {
	Migrated     bool   // True if migration was performed
	ProfilePath  string // Path to the migrated profile
	SessionCount int    // Number of sessions migrated
	Message      string // Human-readable message
}

MigrationResult contains information about the migration outcome

func MigrateToProfiles added in v0.3.0

func MigrateToProfiles() (*MigrationResult, error)

MigrateToProfiles migrates from the old single-file layout to the profiles layout. This is safe to call multiple times - it will only migrate once.

Old layout:

~/.agent-deck/sessions.json
~/.agent-deck/sessions.json.bak
~/.agent-deck/sessions.json.bak.1
~/.agent-deck/sessions.json.bak.2

New layout:

~/.agent-deck/config.json
~/.agent-deck/profiles/default/sessions.json
~/.agent-deck/profiles/default/sessions.json.bak
~/.agent-deck/profiles/default/sessions.json.bak.1
~/.agent-deck/profiles/default/sessions.json.bak.2
~/.agent-deck/logs/ (unchanged)

type ProjectMCPSettings added in v0.5.3

type ProjectMCPSettings struct {
	EnableAllProjectMcpServers bool     `json:"enableAllProjectMcpServers,omitempty"`
	EnabledMcpjsonServers      []string `json:"enabledMcpjsonServers,omitempty"`
	DisabledMcpjsonServers     []string `json:"disabledMcpjsonServers,omitempty"`
}

ProjectMCPSettings represents .claude/settings.local.json

type ResponseOutput added in v0.7.0

type ResponseOutput struct {
	Tool      string `json:"tool"`                 // Tool type (claude, gemini, etc.)
	Role      string `json:"role"`                 // Always "assistant" for now
	Content   string `json:"content"`              // The actual response text
	Timestamp string `json:"timestamp,omitempty"`  // When the response was generated (Claude only)
	SessionID string `json:"session_id,omitempty"` // Claude session ID (if available)
}

ResponseOutput represents a parsed response from an agent session

type SearchEntry added in v0.5.3

type SearchEntry struct {
	SessionID    string    // Claude session UUID
	FilePath     string    // Path to .jsonl file
	CWD          string    // Project working directory
	Content      string    // Full conversation content (original case)
	ContentLower string    // Lowercased for search
	Summary      string    // First user message or summary
	ModTime      time.Time // File modification time
	FileSize     int64     // File size in bytes
}

SearchEntry represents a searchable Claude session

func (*SearchEntry) GetSnippet added in v0.5.3

func (e *SearchEntry) GetSnippet(query string, windowSize int) string

GetSnippet extracts a context window around the first match Uses rune-based indexing to safely handle UTF-8 content Optimized: Single rune conversion instead of triple conversion

func (*SearchEntry) Match added in v0.5.3

func (e *SearchEntry) Match(query string) []MatchRange

Match searches for query in entry content (case-insensitive) Returns match positions for highlighting

type SearchResult added in v0.5.3

type SearchResult struct {
	Entry   *SearchEntry
	Matches []MatchRange
	Score   int
	Snippet string
}

SearchResult represents a search result with match info

type SearchTier added in v0.5.3

type SearchTier int

SearchTier represents the search strategy tier

const (
	TierInstant  SearchTier = iota // < 100MB, full in-memory
	TierBalanced                   // 100MB-500MB, LRU cache
)

func DetectTier added in v0.5.3

func DetectTier(totalSize int64) SearchTier

DetectTier determines the appropriate search tier based on data size

type Status

type Status string

Status represents the current state of a session

const (
	StatusRunning  Status = "running"
	StatusWaiting  Status = "waiting"
	StatusIdle     Status = "idle"
	StatusError    Status = "error"
	StatusStarting Status = "starting" // Session is being created (tmux initializing)
)

type Storage

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

Storage handles persistence of session data Thread-safe with mutex protection for concurrent access

func NewStorage

func NewStorage() (*Storage, error)

NewStorage creates a new storage instance using the default profile. It automatically runs migration from old layout if needed.

func NewStorageWithProfile added in v0.3.0

func NewStorageWithProfile(profile string) (*Storage, error)

NewStorageWithProfile creates a storage instance for a specific profile. If profile is empty, uses the effective profile (from env var or config). Automatically runs migration from old layout if needed.

func (*Storage) GetUpdatedAt added in v0.6.1

func (s *Storage) GetUpdatedAt() (time.Time, error)

GetUpdatedAt returns the last modification timestamp of the storage file This is read from the UpdatedAt field in the JSON file. Returns an error if the file doesn't exist or can't be read.

func (*Storage) Load

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

Load reads instances from JSON file

func (*Storage) LoadWithGroups

func (s *Storage) LoadWithGroups() ([]*Instance, []*GroupData, error)

LoadWithGroups reads instances and groups from JSON file Automatically recovers from backup if main file is corrupted

func (*Storage) Path added in v0.8.1

func (s *Storage) Path() string

Path returns the file path this storage is using

func (*Storage) Profile added in v0.3.0

func (s *Storage) Profile() string

Profile returns the profile name this storage is using

func (*Storage) Save

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

Save persists instances to JSON file DEPRECATED: Use SaveWithGroups to ensure groups are not lost

func (*Storage) SaveWithGroups

func (s *Storage) SaveWithGroups(instances []*Instance, groupTree *GroupTree) error

SaveWithGroups persists instances and groups to JSON file Uses atomic write pattern with: - Mutex for thread safety - Rolling backups (3 generations) - fsync for durability - Data validation

type StorageData

type StorageData struct {
	Instances []*InstanceData `json:"instances"`
	Groups    []*GroupData    `json:"groups,omitempty"` // Persist empty groups
	UpdatedAt time.Time       `json:"updated_at"`
}

StorageData represents the JSON structure for persistence

type ToolDef added in v0.3.0

type ToolDef struct {
	// Command is the shell command to run
	Command string `toml:"command"`

	// Icon is the emoji/symbol to display
	Icon string `toml:"icon"`

	// BusyPatterns are strings that indicate the tool is busy
	BusyPatterns []string `toml:"busy_patterns"`
}

ToolDef defines a custom AI tool

func GetToolDef added in v0.3.0

func GetToolDef(toolName string) *ToolDef

GetToolDef returns a tool definition from user config Returns nil if tool is not defined

type UpdateSettings added in v0.8.2

type UpdateSettings struct {
	// AutoUpdate automatically installs updates without prompting
	// Default: false
	AutoUpdate bool `toml:"auto_update"`

	// CheckEnabled enables automatic update checks on startup
	// Default: true
	CheckEnabled bool `toml:"check_enabled"`

	// CheckIntervalHours is how often to check for updates (in hours)
	// Default: 24
	CheckIntervalHours int `toml:"check_interval_hours"`

	// NotifyInCLI shows update notification in CLI commands (not just TUI)
	// Default: true
	NotifyInCLI bool `toml:"notify_in_cli"`
}

UpdateSettings defines auto-update configuration

func GetUpdateSettings added in v0.8.2

func GetUpdateSettings() UpdateSettings

GetUpdateSettings returns update settings with defaults applied

type UserConfig added in v0.3.0

type UserConfig struct {
	// DefaultTool is the pre-selected AI tool when creating new sessions
	// Valid values: "claude", "gemini", "opencode", "codex", or any custom tool name
	// If empty or invalid, defaults to "shell" (no pre-selection)
	DefaultTool string `toml:"default_tool"`

	// Tools defines custom AI tool configurations
	Tools map[string]ToolDef `toml:"tools"`

	// MCPs defines available MCP servers for the MCP Manager
	// These can be attached/detached per-project via the MCP Manager (M key)
	MCPs map[string]MCPDef `toml:"mcps"`

	// Claude defines Claude Code integration settings
	Claude ClaudeSettings `toml:"claude"`

	// GlobalSearch defines global conversation search settings
	GlobalSearch GlobalSearchSettings `toml:"global_search"`

	// Logs defines session log management settings
	Logs LogSettings `toml:"logs"`

	// MCPPool defines HTTP MCP pool settings for shared MCP servers
	MCPPool MCPPoolSettings `toml:"mcp_pool"`

	// Updates defines auto-update settings
	Updates UpdateSettings `toml:"updates"`
}

UserConfig represents user-facing configuration in TOML format

func LoadUserConfig added in v0.3.0

func LoadUserConfig() (*UserConfig, error)

LoadUserConfig loads the user configuration from TOML file Returns cached config after first load

func ReloadUserConfig added in v0.3.0

func ReloadUserConfig() (*UserConfig, error)

ReloadUserConfig forces a reload of the user config

Jump to

Keyboard shortcuts

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