session

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Dec 16, 2025 License: MIT Imports: 16 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 = "default"

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

View Source
const UserConfigFileName = "config.toml"

UserConfigFileName is the TOML config file for user preferences

Variables

This section is empty.

Functions

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 FindSessionForInstance added in v0.4.1

func FindSessionForInstance(projectPath string, createdAfter time.Time, excludeIDs map[string]bool) string

FindSessionForInstance finds the session file for a specific instance Parameters:

  • projectPath: the project directory
  • createdAfter: only consider files with internal timestamp >= this time
  • excludeIDs: session IDs already claimed by other instances

Returns the session ID or empty string if not found

func GetAgentDeckDir added in v0.3.0

func GetAgentDeckDir() (string, error)

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

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 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 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 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 UpdateClaudeSessionsWithDedup added in v0.4.1

func UpdateClaudeSessionsWithDedup(instances []*Instance)

UpdateClaudeSessionsWithDedup updates Claude sessions for all instances with deduplication This should be called from the manager/storage layer that has access to all instances It both fixes existing duplicates AND prevents new duplicates during detection

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"`
}

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 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) 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"
	Command     string    `json:"command"`
	Tool        string    `json:"tool"`
	Status      Status    `json:"status"`
	CreatedAt   time.Time `json:"created_at"`

	// Claude Code integration
	ClaudeSessionID  string    `json:"claude_session_id,omitempty"`
	ClaudeDetectedAt time.Time `json:"claude_detected_at,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 (has recent Claude session)

func (*Instance) CanRestart added in v0.4.1

func (i *Instance) CanRestart() bool

CanRestart returns true if the session can be restarted (is in error state)

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 Returns the claude command string to run in the new tmux session

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

func (i *Instance) Kill() error

Kill terminates the tmux session

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 recreates the tmux session for a dead/errored session For Claude sessions with known session ID: resumes the conversation (--resume) For other sessions or unknown ID: runs the original command

func (*Instance) Start

func (i *Instance) Start() error

Start starts the session in tmux

func (*Instance) UpdateClaudeSession added in v0.4.1

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

UpdateClaudeSession updates the Claude session ID using detection Priority: 1) tmux environment (for sessions we started), 2) file scanning (legacy/imported) excludeIDs contains session IDs already claimed by other instances Pass nil to skip deduplication (when called from UpdateStatus)

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 Claude to create a session file (for forked sessions) Returns the detected session ID or empty string after timeout Uses FindSessionForInstance with timestamp filtering to ensure we only detect session files created AFTER this instance started (not parent's pre-existing file)

func (*Instance) WaitForClaudeSessionWithExclude added in v0.5.0

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

WaitForClaudeSessionWithExclude waits for Claude to create a session file with exclusion list This is more robust than WaitForClaudeSession as it explicitly excludes known session IDs Use this when forking to ensure the fork's new session is detected, not an existing one

type InstanceData

type InstanceData struct {
	ID          string    `json:"id"`
	Title       string    `json:"title"`
	ProjectPath string    `json:"project_path"`
	GroupPath   string    `json:"group_path"`
	Command     string    `json:"command"`
	Tool        string    `json:"tool"`
	Status      Status    `json:"status"`
	CreatedAt   time.Time `json:"created_at"`
	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"`
}

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
}

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

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) 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) 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 UserConfig added in v0.3.0

type UserConfig struct {
	// DefaultTool is the pre-selected AI tool when creating new sessions
	// Valid values: "claude", "gemini", "aider", "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"`

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

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