session

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package session provides multi-workspace session management for Claude CLI instances.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type HistoryInfo

type HistoryInfo struct {
	SessionID    string    `json:"session_id"`
	Summary      string    `json:"summary"`
	MessageCount int       `json:"message_count"`
	LastUpdated  time.Time `json:"last_updated"`
	Branch       string    `json:"branch,omitempty"`
}

HistoryInfo represents historical session information from the session cache.

type Info

type Info struct {
	ID          string    `json:"id"`
	WorkspaceID string    `json:"workspace_id"`
	Status      Status    `json:"status"`
	StartedAt   time.Time `json:"started_at"`
	LastActive  time.Time `json:"last_active"`
	Error       string    `json:"error,omitempty"`
	// Viewers is the list of client IDs currently viewing this session.
	// Populated by workspace/list when session focus info is available.
	Viewers []string `json:"viewers,omitempty"`
}

Info is a serializable representation of a session.

type Manager

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

Manager orchestrates multiple Claude sessions across workspaces.

func NewManager

func NewManager(hub ports.EventHub, cfg *config.Config, logger *slog.Logger) *Manager

NewManager creates a new session manager.

func (*Manager) ActivateSession

func (m *Manager) ActivateSession(workspaceID, sessionID string) error

ActivateSession sets the active session for a workspace. This allows iOS clients to switch which session they are viewing/interacting with. Multiple clients can have different active sessions for the same workspace.

func (*Manager) CancelSessionFileWatcher

func (m *Manager) CancelSessionFileWatcher(workspaceID string)

CancelSessionFileWatcher cancels an active session file watcher for a workspace. Called when a session is stopped or workspace is removed. Does NOT emit any event - use FailSessionIDResolution if you need to emit an event.

func (*Manager) CountActiveSessionsForWorkspace

func (m *Manager) CountActiveSessionsForWorkspace(workspaceID string) int

CountActiveSessionsForWorkspace returns the count of active sessions for a workspace.

func (*Manager) DeleteHistorySession

func (m *Manager) DeleteHistorySession(workspaceID, sessionID string) error

DeleteHistorySession deletes a historical Claude session file. This removes the .jsonl file from ~/.claude/projects/<encoded-path>/

func (*Manager) EmitPermissionResolved

func (m *Manager) EmitPermissionResolved(sessionID, clientID, input string)

EmitPermissionResolved broadcasts a pty_permission_resolved event to all devices. This is called when one device responds to a permission prompt, so other devices can dismiss their permission popup.

func (*Manager) FailSessionIDResolution

func (m *Manager) FailSessionIDResolution(workspaceID, temporaryID, reason, message string)

FailSessionIDResolution cancels the session file watcher and emits a session_id_failed event. Called when Claude exits without creating a session (e.g., user declined trust folder). Parameters:

  • workspaceID: The workspace ID
  • temporaryID: The temporary session ID that was waiting for resolution
  • reason: "trust_declined", "claude_exited", or "error"
  • message: Optional human-readable message

func (*Manager) GetActiveSession

func (m *Manager) GetActiveSession(workspaceID string) string

GetActiveSession returns the active session ID for a workspace. Returns empty string if no session is explicitly activated.

func (*Manager) GetGitDiff

func (m *Manager) GetGitDiff(workspaceID string, staged bool) (string, error)

GetGitDiff returns git diff for a workspace. If staged is true, returns staged changes; otherwise returns unstaged changes.

func (*Manager) GetGitDiffWithMeta

func (m *Manager) GetGitDiffWithMeta(workspaceID string, path string) (diff string, isStaged bool, isNew bool, err error)

GetGitDiffWithMeta returns git diff with metadata (isStaged, isNew). This matches the git/diff response format.

func (*Manager) GetGitEnhancedStatus

func (m *Manager) GetGitEnhancedStatus(workspaceID string) (*git.EnhancedStatus, error)

GetGitEnhancedStatus returns enhanced git status for a workspace.

func (*Manager) GetGitStatus

func (m *Manager) GetGitStatus(workspaceID string) (interface{}, error)

GetGitStatus returns git status for a workspace.

func (*Manager) GetLatestSessionID

func (m *Manager) GetLatestSessionID(workspaceID string) (string, error)

GetLatestSessionID returns the most recently modified session ID from .claude/projects. This is the source of truth for Claude Code sessions. Only returns main sessions (UUID-formatted files with user interaction), not agent sub-sessions.

func (*Manager) GetSession

func (m *Manager) GetSession(sessionID string) (*Session, error)

GetSession returns a session by ID.

func (*Manager) GetSessionForWorkspace

func (m *Manager) GetSessionForWorkspace(workspaceID string) *Session

GetSessionForWorkspace returns the first active session for a workspace (if any). Used for operations that need any session (e.g., git operations).

func (*Manager) GetSessionMessages

func (m *Manager) GetSessionMessages(workspaceID, sessionID string, limit, offset int, order string) (*SessionMessagesResult, error)

GetSessionMessages returns messages from a historical Claude session. This reads from the Claude session files at ~/.claude/projects/<encoded-path>

func (*Manager) GetSessionsForWorkspace

func (m *Manager) GetSessionsForWorkspace(workspaceID string) []*Session

GetSessionsForWorkspace returns all sessions for a workspace.

func (*Manager) GetWatchedSession

func (m *Manager) GetWatchedSession() *WatchInfo

GetWatchedSession returns information about the currently watched session.

func (*Manager) GetWorkspace

func (m *Manager) GetWorkspace(workspaceID string) (*workspace.Workspace, error)

GetWorkspace returns a workspace by ID.

func (*Manager) GitBranches

func (m *Manager) GitBranches(workspaceID string) (*git.BranchesResult, error)

GitBranches lists branches for a workspace.

func (*Manager) GitCheckout

func (m *Manager) GitCheckout(workspaceID string, branch string, create bool) (*git.CheckoutResult, error)

GitCheckout checks out a branch for a workspace.

func (*Manager) GitCommit

func (m *Manager) GitCommit(workspaceID string, message string, push bool) (*git.CommitResult, error)

GitCommit commits staged changes for a workspace.

func (*Manager) GitDeleteBranch

func (m *Manager) GitDeleteBranch(workspaceID string, branch string, force bool) (*git.DeleteBranchResult, error)

GitDeleteBranch deletes a branch for a workspace.

func (*Manager) GitDiscard

func (m *Manager) GitDiscard(workspaceID string, paths []string) error

GitDiscard discards changes for a workspace.

func (*Manager) GitFetch

func (m *Manager) GitFetch(workspaceID string, remote string, prune bool) (*git.FetchResult, error)

GitFetch fetches from a remote for a workspace.

func (*Manager) GitGetStatus

func (m *Manager) GitGetStatus(workspaceID string) (*git.Status, error)

GitGetStatus returns the comprehensive git status for a workspace.

func (*Manager) GitInit

func (m *Manager) GitInit(workspaceID string, initialBranch string, initialCommit bool, commitMessage string) (*git.InitResult, error)

GitInit initializes a git repository for a workspace. This method works on non-git directories to initialize them.

func (*Manager) GitLog

func (m *Manager) GitLog(workspaceID string, limit int, skip int, branch string, path string, graph bool) (*git.LogResult, error)

GitLog returns the commit log for a workspace.

func (*Manager) GitMerge

func (m *Manager) GitMerge(workspaceID string, branch string, noFastForward bool, message string) (*git.MergeResult, error)

GitMerge merges a branch for a workspace.

func (*Manager) GitMergeAbort

func (m *Manager) GitMergeAbort(workspaceID string) (*git.MergeResult, error)

GitMergeAbort aborts a merge for a workspace.

func (*Manager) GitPull

func (m *Manager) GitPull(workspaceID string, rebase bool) (*git.PullResult, error)

GitPull pulls changes from remote for a workspace.

func (*Manager) GitPush

func (m *Manager) GitPush(workspaceID string, force bool, setUpstream bool, remote, branch string) (*git.PushResult, error)

GitPush pushes commits to remote for a workspace.

func (*Manager) GitRemoteAdd

func (m *Manager) GitRemoteAdd(workspaceID string, name string, url string, fetch bool) (*git.RemoteAddResult, error)

GitRemoteAdd adds a remote to a workspace.

func (*Manager) GitRemoteList

func (m *Manager) GitRemoteList(workspaceID string) (*git.RemoteListResult, error)

GitRemoteList lists remotes for a workspace.

func (*Manager) GitRemoteRemove

func (m *Manager) GitRemoteRemove(workspaceID string, name string) (*git.RemoteRemoveResult, error)

GitRemoteRemove removes a remote from a workspace.

func (*Manager) GitSetUpstream

func (m *Manager) GitSetUpstream(workspaceID string, branch string, upstream string) (*git.SetUpstreamResult, error)

GitSetUpstream sets the upstream for a branch.

func (*Manager) GitStage

func (m *Manager) GitStage(workspaceID string, paths []string) error

GitStage stages files for a workspace.

func (*Manager) GitStash

func (m *Manager) GitStash(workspaceID string, message string, includeUntracked bool) (*git.StashResult, error)

GitStash creates a stash for a workspace.

func (*Manager) GitStashApply

func (m *Manager) GitStashApply(workspaceID string, index int) (*git.StashResult, error)

GitStashApply applies a stash for a workspace.

func (*Manager) GitStashDrop

func (m *Manager) GitStashDrop(workspaceID string, index int) (*git.StashResult, error)

GitStashDrop drops a stash for a workspace.

func (*Manager) GitStashList

func (m *Manager) GitStashList(workspaceID string) (*git.StashListResult, error)

GitStashList lists stashes for a workspace.

func (*Manager) GitStashPop

func (m *Manager) GitStashPop(workspaceID string, index int) (*git.StashResult, error)

GitStashPop pops a stash for a workspace.

func (*Manager) GitUnstage

func (m *Manager) GitUnstage(workspaceID string, paths []string) error

GitUnstage unstages files for a workspace.

func (*Manager) HasActiveSessionFileWatcher

func (m *Manager) HasActiveSessionFileWatcher(workspaceID string) bool

HasActiveSessionFileWatcher returns true if there's an active watcher for the workspace.

func (*Manager) ListHistory

func (m *Manager) ListHistory(workspaceID string, limit int) ([]HistoryInfo, error)

ListHistory returns historical Claude sessions for a workspace. This reads from the Claude session cache at ~/.claude/projects/<encoded-path>

func (*Manager) ListSessions

func (m *Manager) ListSessions(workspaceID string) []*Info

ListSessions returns all sessions, optionally filtered by workspace.

func (*Manager) ListWorkspaces

func (m *Manager) ListWorkspaces() []*workspace.Workspace

ListWorkspaces returns all registered workspaces.

func (*Manager) OnClientDisconnect

func (m *Manager) OnClientDisconnect(clientID string, subscribedWorkspaces []string)

OnClientDisconnect handles cleanup when a client disconnects. This is called by the unified server when a WebSocket connection is closed. It decrements git watcher counts and session streamer counts for the disconnected client.

func (*Manager) PublishEvent

func (m *Manager) PublishEvent(event *events.BaseEvent)

PublishEvent publishes an event to the hub. Used by RPC handlers to emit events.

func (*Manager) RegisterWorkspace

func (m *Manager) RegisterWorkspace(ws *workspace.Workspace)

RegisterWorkspace registers a workspace with the manager.

func (*Manager) RespondToPermission

func (m *Manager) RespondToPermission(sessionID string, allow bool) error

RespondToPermission responds to a permission request in a session.

func (*Manager) RespondToQuestion

func (m *Manager) RespondToQuestion(sessionID string, response string) error

RespondToQuestion responds to an interactive question in a session.

func (*Manager) SendInput

func (m *Manager) SendInput(sessionID string, input string) error

SendInput sends input to a session's Claude PTY (for interactive responses). Supports both managed sessions (started by cdev) and LIVE sessions (user's terminal). This is used to respond to permission prompts when running in interactive mode.

func (*Manager) SendKey

func (m *Manager) SendKey(sessionID string, key string) error

SendKey sends a special key (like arrow keys, enter, escape) to a session. For LIVE sessions, uses platform-specific key code injection instead of text keystroke.

func (*Manager) SendPrompt

func (m *Manager) SendPrompt(sessionID string, prompt string, mode string, permissionMode string, yoloMode bool) error

SendPrompt sends a prompt to a session's Claude instance. Supports both managed sessions (started by cdev) and LIVE sessions (user's terminal). permissionMode controls how Claude handles permissions: - "default": Standard permission prompts (may hang if stdin is closed) - "acceptEdits": Auto-accept file edits - "bypassPermissions": Skip all permission checks - "plan": Plan mode only - "interactive": Use PTY mode for true interactive permission handling yoloMode is runtime-agnostic bypass intent (mapped to runtime-specific flags when supported).

func (*Manager) SessionFileExists

func (m *Manager) SessionFileExists(workspaceID string, sessionID string) (bool, error)

SessionFileExists checks if a session file exists in .claude/projects for the workspace. This validates against the source of truth for Claude Code sessions.

func (*Manager) SetGitTrackerManager

func (m *Manager) SetGitTrackerManager(gtm *workspace.GitTrackerManager)

SetGitTrackerManager sets the shared git tracker manager.

func (*Manager) SetLiveSessionSupport

func (m *Manager) SetLiveSessionSupport(workspacePath string)

SetLiveSessionSupport enables LIVE session support. This allows sending messages to Claude instances running in the user's terminal. The detector is created dynamically per workspace, but the injector is shared.

func (*Manager) Start

func (m *Manager) Start() error

Start starts the session manager and idle monitor.

func (*Manager) StartGitWatcher

func (m *Manager) StartGitWatcher(workspaceID string) error

StartGitWatcher starts watching git state changes for a workspace. This is called when a client subscribes to a workspace (workspace/subscribe). The watcher emits git_status_changed events when staging/commits/branch changes occur. Uses reference counting - multiple clients can subscribe, watcher starts on first subscriber. Returns nil if git is disabled.

func (*Manager) StartSession

func (m *Manager) StartSession(workspaceID string) (*Session, error)

StartSession starts a new Claude session for a workspace. It automatically uses the most recent historical session ID from ~/.claude/projects/ so that session/send with mode "continue" will properly resume the conversation.

func (*Manager) Stop

func (m *Manager) Stop() error

Stop stops all sessions and the manager.

func (*Manager) StopGitWatcher

func (m *Manager) StopGitWatcher(workspaceID string)

StopGitWatcher decrements the subscriber count for a workspace's git watcher. The watcher is only stopped when the last subscriber unsubscribes. This is called when a client unsubscribes from a workspace (workspace/unsubscribe).

func (*Manager) StopSession

func (m *Manager) StopSession(sessionID string) error

StopSession stops a running session. For managed sessions (started via cdev), this stops the Claude process. For LIVE sessions (watched but not started by cdev), this unwatches and clears active status.

func (*Manager) UnregisterWorkspace

func (m *Manager) UnregisterWorkspace(workspaceID string) error

UnregisterWorkspace removes a workspace from the manager.

func (*Manager) UnwatchWorkspaceSession

func (m *Manager) UnwatchWorkspaceSession(clientID string, sessionID string) *WatchInfo

UnwatchWorkspaceSession stops watching a session for one client. The streamer continues running until all clients have stopped watching. If sessionID is empty, one watched session is removed deterministically for backward compatibility.

func (*Manager) WatchForNewSessionFile

func (m *Manager) WatchForNewSessionFile(ctx context.Context, workspaceID, temporaryID, repoPath string)

WatchForNewSessionFile watches the .claude/projects directory for new session files. When a new .jsonl file is created (after trust folder is accepted), it emits a session_id_resolved event with the real session ID from Claude.

Thread-safety: Only one watcher per workspace is allowed. If a watcher already exists for this workspace, this call is a no-op. The watcher is automatically cleaned up on completion, timeout, or cancellation.

func (*Manager) WatchWorkspaceSession

func (m *Manager) WatchWorkspaceSession(clientID, workspaceID, sessionID string) (*WatchInfo, error)

WatchWorkspaceSession starts watching a session file for live message updates. This is used by iOS to receive real-time claude_message events when new messages are added to the session file.

Multiple clients can watch the same session. The streamer uses client tracking to keep watching until the last client stops watching. The clientID parameter identifies the client making this request.

type RuntimeState

type RuntimeState struct {
	// Session info
	ID          string    `json:"id"`
	WorkspaceID string    `json:"workspace_id"`
	Status      Status    `json:"status"`
	StartedAt   time.Time `json:"started_at"`
	LastActive  time.Time `json:"last_active"`
	Error       string    `json:"error,omitempty"`

	// Claude state
	ClaudeState      string `json:"claude_state"`      // idle, running, error, waiting
	ClaudeSessionID  string `json:"claude_session_id"` // For conversation continuity
	IsRunning        bool   `json:"is_running"`        // Is Claude process running
	WaitingForInput  bool   `json:"waiting_for_input"` // Is Claude waiting for user input
	PendingToolUseID string `json:"pending_tool_use_id,omitempty"`
	PendingToolName  string `json:"pending_tool_name,omitempty"`
}

RuntimeState contains the current runtime state of a session for reconnection sync.

type Session

type Session struct {
	ID          string    `json:"id"`
	WorkspaceID string    `json:"workspace_id"`
	Status      Status    `json:"status"`
	StartedAt   time.Time `json:"started_at"`
	LastActive  time.Time `json:"last_active"`
	Error       string    `json:"error,omitempty"`
	// contains filtered or unexported fields
}

Session represents an active Claude CLI instance for a workspace.

func NewSession

func NewSession(id, workspaceID string) *Session

NewSession creates a new session for a workspace.

func (*Session) ClaudeManager

func (s *Session) ClaudeManager() *claude.Manager

ClaudeManager returns the Claude manager for this session.

func (*Session) FileWatcher

func (s *Session) FileWatcher() *watcher.Watcher

FileWatcher returns the file watcher for this session.

func (*Session) GetID

func (s *Session) GetID() string

GetID returns the session ID (thread-safe).

func (*Session) GetLastActive

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

GetLastActive returns the last active timestamp.

func (*Session) GetStatus

func (s *Session) GetStatus() Status

GetStatus returns the current session status.

func (*Session) GitTracker

func (s *Session) GitTracker() *git.Tracker

GitTracker returns the git tracker for this session.

func (*Session) SetClaudeManager

func (s *Session) SetClaudeManager(m *claude.Manager)

SetClaudeManager sets the Claude manager for this session.

func (*Session) SetError

func (s *Session) SetError(err error)

SetError sets an error status with message.

func (*Session) SetFileWatcher

func (s *Session) SetFileWatcher(w *watcher.Watcher)

SetFileWatcher sets the file watcher for this session.

func (*Session) SetGitTracker

func (s *Session) SetGitTracker(t *git.Tracker)

SetGitTracker sets the git tracker for this session.

func (*Session) SetSessionID

func (s *Session) SetSessionID(newID string)

SetSessionID updates the session ID (thread-safe). This is used when the real session ID is detected from Claude. Also updates the ClaudeManager's session ID if present.

func (*Session) SetStatus

func (s *Session) SetStatus(status Status)

SetStatus updates the session status.

func (*Session) ToInfo

func (s *Session) ToInfo() *Info

ToInfo returns a serializable session info.

func (*Session) ToRuntimeState

func (s *Session) ToRuntimeState() *RuntimeState

ToRuntimeState returns the current runtime state for reconnection sync.

func (*Session) UpdateLastActive

func (s *Session) UpdateLastActive()

UpdateLastActive updates the last active timestamp.

type SessionMessage

type SessionMessage struct {
	ID        int64           `json:"id"`
	SessionID string          `json:"session_id"`
	Type      string          `json:"type"`
	UUID      string          `json:"uuid,omitempty"`
	Timestamp string          `json:"timestamp,omitempty"`
	GitBranch string          `json:"git_branch,omitempty"`
	Message   json.RawMessage `json:"message"`

	// IsContextCompaction is true when this is an auto-generated message
	// created by Claude Code when the context window was maxed out.
	IsContextCompaction bool `json:"is_context_compaction,omitempty"`

	// IsMeta is true for system-generated metadata messages (e.g., command caveats).
	IsMeta bool `json:"is_meta,omitempty"`
}

SessionMessage represents a message from a Claude session. This struct matches the format in methods.SessionMessage for consistency.

type SessionMessagesResult

type SessionMessagesResult struct {
	SessionID   string           `json:"session_id"`
	Messages    []SessionMessage `json:"messages"`
	Total       int              `json:"total"`
	Limit       int              `json:"limit"`
	Offset      int              `json:"offset"`
	HasMore     bool             `json:"has_more"`
	QueryTimeMs float64          `json:"query_time_ms"`
}

SessionMessagesResult represents the result of GetSessionMessages.

type Status

type Status string

Status represents the current state of a session.

const (
	StatusStopped  Status = "stopped"
	StatusStarting Status = "starting"
	StatusRunning  Status = "running"
	StatusStopping Status = "stopping"
	StatusError    Status = "error"
)

type WatchInfo

type WatchInfo struct {
	WorkspaceID string `json:"workspace_id"`
	SessionID   string `json:"session_id"`
	Watching    bool   `json:"watching"`
}

WatchInfo contains information about the currently watched session.

Jump to

Keyboard shortcuts

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