services

package
v1.1.1 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	// ToolCategoryAny matches any tool (empty string — default behaviour).
	ToolCategoryAny = ""
	// ToolCategoryBuiltin matches any Claude Code built-in tool (no "__" in name).
	// Examples: Bash, Read, Write, Edit, Glob, Grep, Task, WebFetch, WebSearch, ToolSearch.
	ToolCategoryBuiltin = "builtin"
	// ToolCategoryBuiltinAgent matches planning / task-management built-ins that pose no risk.
	// Examples: ExitPlanMode, EnterPlanMode, AskUserQuestion, TodoWrite, Task*, Skill, NotebookEdit.
	ToolCategoryBuiltinAgent = "builtin-agent"
	// ToolCategoryMCP matches any MCP tool (name contains "__").
	ToolCategoryMCP = "mcp"
	// ToolCategoryMCPRead matches MCP tools whose operation names are read-only.
	// Determined by CategorizeToolName; covers context7, sequential-thinking, and
	// filesystem/repomix read operations.
	ToolCategoryMCPRead = "mcp-read"
	// ToolCategoryMCPWrite matches MCP tools whose operation names mutate state.
	ToolCategoryMCPWrite = "mcp-write"
)

ToolCategory constants classify tool names into coarse groups for use in Rule.ToolCategory. This lets seed rules match whole classes of tools without fragile long regex patterns.

Variables

This section is empty.

Functions

func CategorizeToolName

func CategorizeToolName(name string) string

CategorizeToolName returns the ToolCategory constant for a given tool name. The classification uses Claude Code naming conventions:

  • MCP tools follow the pattern "mcp__<server>__<operation>" (contains "__").
  • Built-in tools never contain "__".
  • Agent tools are a named subset of built-ins.

func ExtractDomainsFromCommand

func ExtractDomainsFromCommand(cmd string) []string

ExtractDomainsFromCommand parses network-relevant Bash commands and returns the eTLD+1 (registered domain) for each URL found, deduplicated.

func FormatSecretDenyMessage

func FormatSecretDenyMessage(patternName string) string

FormatSecretDenyMessage returns a user-facing denial message for a secret scan hit.

func InjectHookConfig

func InjectHookConfig(rootDir, sessionTitle string) error

InjectHookConfig writes (or merges) the stapler-squad PermissionRequest HTTP hook into <rootDir>/.claude/settings.local.json.

If the file already contains a hook pointing to hookApprovalURL, it is left unchanged. If the file exists but lacks our hook, the hook is prepended to PermissionRequest. If the file does not exist, it is created with just our hook config.

func StartExpirationCleanup

func StartExpirationCleanup(ctx context.Context, store *ApprovalStore)

StartExpirationCleanup starts a background goroutine that periodically removes expired approvals. The goroutine stops when ctx is canceled.

func WriteSnapshot

func WriteSnapshot(snap *DebugSnapshot, dir string) (string, error)

WriteSnapshot serializes the snapshot to a JSON file in the given directory. Returns the absolute path of the written file.

Types

type AnalyticsEntry

type AnalyticsEntry struct {
	ID             string    `json:"id"`
	Timestamp      time.Time `json:"timestamp"`
	SessionID      string    `json:"session_id"`
	ToolName       string    `json:"tool_name"`
	CommandPreview string    `json:"command_preview"` // first 200 chars
	Cwd            string    `json:"cwd"`
	// Decision: "auto_allow" | "auto_deny" | "escalate" | "manual_allow" | "manual_deny"
	Decision    string `json:"decision"`
	RiskLevel   string `json:"risk_level"`
	RuleID      string `json:"rule_id,omitempty"`
	RuleName    string `json:"rule_name,omitempty"`
	Reason      string `json:"reason,omitempty"`
	Alternative string `json:"alternative,omitempty"`
	DurationMs  int64  `json:"duration_ms"`
	ApprovalID  string `json:"approval_id,omitempty"`

	// AST-derived command categorization (Bash tool only).
	// CommandProgram is the primary executable being called (e.g., "git", "npm").
	CommandProgram string `json:"command_program,omitempty"`
	// CommandCategory groups CommandProgram into a high-level category (e.g., "vcs", "node").
	CommandCategory string `json:"command_category,omitempty"`
	// CommandSubcategory is the first positional subcommand (e.g., "commit" for "git commit").
	CommandSubcategory string `json:"command_subcommand,omitempty"`
	// PythonImports lists top-level module names imported in inline Python (-c) invocations.
	PythonImports []string `json:"python_imports,omitempty"`
}

AnalyticsEntry records a single classification decision.

func ReclassifyGaps

func ReclassifyGaps(entries []AnalyticsEntry, c Classifier) []AnalyticsEntry

ReclassifyGaps re-runs the current classifier against entries that were previously escalated with no matching rule (coverage gaps). Any entry that the current rules would now auto-allow or auto-deny has its Decision and RuleID updated in the returned copy — the underlying JSONL file is unchanged.

Call this before ComputeSummary when you want coverage-gap metrics to reflect the CURRENT rule set rather than the rules that were active when the entry was recorded. This prevents historical gaps from artificially inflating the gap rate after new rules are added.

type AnalyticsStore

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

AnalyticsStore writes AnalyticsEntry records asynchronously to a JSONL file and provides in-memory query aggregations.

func NewAnalyticsStore

func NewAnalyticsStore(filePath string) *AnalyticsStore

NewAnalyticsStore creates an AnalyticsStore backed by the given JSONL file. Call Start() to begin the background flush goroutine.

func (*AnalyticsStore) DroppedCount

func (s *AnalyticsStore) DroppedCount() int64

DroppedCount returns the number of entries dropped due to buffer overflow.

func (*AnalyticsStore) LoadWindow

func (s *AnalyticsStore) LoadWindow(since time.Time) ([]AnalyticsEntry, error)

LoadWindow reads JSONL entries from disk with timestamps >= since. Malformed lines are skipped with a warning.

func (*AnalyticsStore) Record

func (s *AnalyticsStore) Record(entry AnalyticsEntry)

Record enqueues an analytics entry for async write. Non-blocking. If the buffer is full, the entry is dropped and the dropped counter incremented.

func (*AnalyticsStore) RecordFromResult

func (s *AnalyticsStore) RecordFromResult(payload PermissionRequestPayload, result ClassificationResult, sessionID, approvalID string, durationMs int64)

RecordFromResult builds and records an AnalyticsEntry from classification output.

func (*AnalyticsStore) RecordManualDecision

func (s *AnalyticsStore) RecordManualDecision(approvalID, sessionID, toolName, cwd, decision string)

RecordManualDecision records a manual approve/deny decision for an approval.

func (*AnalyticsStore) Start

func (s *AnalyticsStore) Start(ctx interface{ Done() <-chan struct{} })

Start launches the background goroutine that flushes entries to disk. It stops when ctx is canceled.

type AnalyticsSummary

type AnalyticsSummary struct {
	TotalDecisions    int            `json:"total_decisions"`
	DecisionCounts    map[string]int `json:"decision_counts"`
	TopTools          []ToolStat     `json:"top_tools"`
	TopDeniedCommands []CommandStat  `json:"top_denied_commands"`
	TopTriggeredRules []RuleStat     `json:"top_triggered_rules"`
	// TopCommandPrograms lists the most frequently invoked programs via the Bash tool.
	TopCommandPrograms []ProgramStat `json:"top_command_programs"`
	// TopPythonImports lists the most frequently imported Python modules from inline (-c) invocations.
	TopPythonImports []ImportStat `json:"top_python_imports"`
	AutoApproveRate  float64      `json:"auto_approve_rate"`
	ManualReviewRate float64      `json:"manual_review_rate"`
	WindowStart      time.Time    `json:"window_start"`
	WindowEnd        time.Time    `json:"window_end"`

	// Coverage gap: decisions that escaped all rules (escalated with no rule_id).
	// These are prime candidates for new rules to reduce manual review.
	CoverageGapCount     int           `json:"coverage_gap_count"`
	CoverageGapRate      float64       `json:"coverage_gap_rate"` // percentage 0–100
	TopUncoveredTools    []ToolStat    `json:"top_uncovered_tools"`
	TopUncoveredPrograms []ProgramStat `json:"top_uncovered_programs"`

	// CommandSubcommandStats is the complete (program, subcommand) distribution — not
	// truncated to top-N. Use this for drill-down analysis such as "which gh subcommands
	// does Claude use most?" or "what sed patterns need rules?".
	CommandSubcommandStats []SubcommandStat `json:"command_subcommand_stats"`
}

AnalyticsSummary aggregates decisions over a time window.

func ComputeSummary

func ComputeSummary(entries []AnalyticsEntry) AnalyticsSummary

ComputeSummary aggregates a slice of entries into an AnalyticsSummary. Pure function -- no I/O.

type ApprovalDecision

type ApprovalDecision struct {
	Behavior string // "allow" or "deny"
	Message  string // Optional reason shown to Claude on deny
}

ApprovalDecision is the user's response to a pending approval.

type ApprovalDetail

type ApprovalDetail struct {
	ID              string                 `json:"id"`
	SessionID       string                 `json:"session_id"`
	ClaudeSessionID string                 `json:"claude_session_id"`
	ToolName        string                 `json:"tool_name"`
	ToolInput       map[string]interface{} `json:"tool_input,omitempty"`
	Cwd             string                 `json:"cwd"`
	PermissionMode  string                 `json:"permission_mode"`
	CreatedAt       time.Time              `json:"created_at"`
	ExpiresAt       time.Time              `json:"expires_at"`
}

ApprovalDetail captures the fields of a single pending approval.

type ApprovalHandler

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

ApprovalHandler handles Claude Code HTTP hooks for PermissionRequest events. It blocks the HTTP connection open while waiting for the user's decision, then returns the decision in the hookSpecificOutput JSON format.

func NewApprovalHandler

func NewApprovalHandler(store *ApprovalStore, storage *session.Storage, eventBus *events.EventBus) *ApprovalHandler

NewApprovalHandler creates a new ApprovalHandler.

func (*ApprovalHandler) HandlePermissionRequest

func (h *ApprovalHandler) HandlePermissionRequest(w http.ResponseWriter, r *http.Request)

HandlePermissionRequest handles POST /api/hooks/permission-request. This endpoint is configured as an HTTP hook in Claude Code's settings. It blocks until the user approves/denies or the context is canceled.

func (*ApprovalHandler) SetAnalyticsStore

func (h *ApprovalHandler) SetAnalyticsStore(a *AnalyticsStore)

SetAnalyticsStore injects an AnalyticsStore for recording classification decisions.

func (*ApprovalHandler) SetClassifier

func (h *ApprovalHandler) SetClassifier(c *RuleBasedClassifier)

SetClassifier injects a RuleBasedClassifier for auto-approving/denying tool use requests before they reach the manual review queue.

func (*ApprovalHandler) SetDomainChecker

func (h *ApprovalHandler) SetDomainChecker(d *DomainAgeChecker)

SetDomainChecker injects a DomainAgeChecker for escalating requests to newly-registered domains.

func (*ApprovalHandler) SetNotificationStamper

func (h *ApprovalHandler) SetNotificationStamper(s approvalNotificationStamper)

SetNotificationStamper injects a stamper for persisting approval outcomes on notification records. When set, resolved and timed-out approvals are stamped with approval_decision in their metadata so the notification panel can show a persistent badge after page refresh.

func (*ApprovalHandler) SetQueueChecker

func (h *ApprovalHandler) SetQueueChecker(checker ReviewQueueChecker)

SetQueueChecker injects a ReviewQueueChecker for triggering immediate review queue updates when a new approval is created. This provides <100ms feedback instead of waiting for the next 2-second poll cycle.

type ApprovalService

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

ApprovalService handles Claude Code hook approval RPCs.

func NewApprovalService

func NewApprovalService(store *ApprovalStore) *ApprovalService

NewApprovalService creates an ApprovalService with the given ApprovalStore.

func (*ApprovalService) ListPendingApprovals

ListPendingApprovals returns all pending approval requests, optionally filtered by session ID.

func (*ApprovalService) ResolveApproval

ResolveApproval sends the user's decision to the blocked HTTP hook handler.

func (*ApprovalService) SetNotificationStore

func (as *ApprovalService) SetNotificationStore(store notificationMetadataStore)

SetNotificationStore wires in the notification history store so that resolved approvals are stamped with their decision in the notification metadata.

type ApprovalSnapshot

type ApprovalSnapshot struct {
	PendingCount int              `json:"pending_count"`
	Pending      []ApprovalDetail `json:"pending,omitempty"`
}

ApprovalSnapshot captures the pending approvals state.

type ApprovalStore

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

ApprovalStore manages pending approval requests with thread-safe access.

func NewApprovalStore

func NewApprovalStore(filePath string) *ApprovalStore

NewApprovalStore creates a new ApprovalStore. If filePath is non-empty, persisted approvals are loaded from disk and marked as orphaned.

func (*ApprovalStore) CancelSession

func (s *ApprovalStore) CancelSession(sessionID string) []string

CancelSession denies all pending approvals for a session (e.g., on restart).

func (*ApprovalStore) CleanupExpired

func (s *ApprovalStore) CleanupExpired() []string

CleanupExpired removes approvals past their ExpiresAt and denies them with a timeout message. Also removes orphaned approvals older than orphanedCleanupThreshold (4 hours). Returns the IDs of cleaned-up approvals.

func (*ApprovalStore) Create

func (s *ApprovalStore) Create(a *PendingApproval) error

Create adds a new pending approval to the store and initializes its decision channel.

func (*ApprovalStore) Get

func (s *ApprovalStore) Get(id string) (*PendingApproval, bool)

Get retrieves a pending approval by ID.

func (*ApprovalStore) GetApprovalMetadataBySession

func (s *ApprovalStore) GetApprovalMetadataBySession(sessionID string) []session.ApprovalMetadata

GetApprovalMetadataBySession implements session.ApprovalMetadataProvider. Returns approval metadata for all pending approvals matching the given session ID.

func (*ApprovalStore) GetBySession

func (s *ApprovalStore) GetBySession(sessionID string) []*PendingApproval

GetBySession returns all pending approvals for a given session.

func (*ApprovalStore) GetFilePath

func (s *ApprovalStore) GetFilePath() string

GetFilePath returns the file path used for persistence (for testing/wiring).

func (*ApprovalStore) ListAll

func (s *ApprovalStore) ListAll() []*PendingApproval

ListAll returns all currently pending approvals.

func (*ApprovalStore) Remove

func (s *ApprovalStore) Remove(id string)

Remove removes an approval from the store without sending a decision. The pending HTTP handler will detect context cancellation or its own timeout.

func (*ApprovalStore) Resolve

func (s *ApprovalStore) Resolve(id string, decision ApprovalDecision) error

Resolve sends a decision to the pending approval and removes it from the store. Returns an error if the approval doesn't exist or was already resolved. For orphaned approvals (loaded from disk after restart), the record is simply removed since there is no live HTTP connection to send the decision to.

type CircuitBreakerHandler

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

CircuitBreakerHandler provides a debug endpoint to inspect circuit breaker state.

func NewCircuitBreakerHandler

func NewCircuitBreakerHandler() *CircuitBreakerHandler

NewCircuitBreakerHandler creates a new handler using the global registry.

func (*CircuitBreakerHandler) HandleCircuitBreakers

func (h *CircuitBreakerHandler) HandleCircuitBreakers(w http.ResponseWriter, r *http.Request)

HandleCircuitBreakers returns the current state of all circuit breakers. GET /api/debug/circuit-breakers

func (*CircuitBreakerHandler) RegisterRoutes

func (h *CircuitBreakerHandler) RegisterRoutes(mux *http.ServeMux)

RegisterRoutes registers the circuit breaker debug routes on the given mux.

type ClassificationContext

type ClassificationContext struct {
	Cwd        string
	IsGitRepo  bool
	RepoRoot   string
	IsWorktree bool
}

ClassificationContext provides local-environment context to the classifier.

type ClassificationDecision

type ClassificationDecision int

ClassificationDecision is the action taken by the classifier.

const (
	// AutoAllow bypasses the manual review queue and immediately allows the request.
	AutoAllow ClassificationDecision = iota
	// AutoDeny immediately denies the request, optionally suggesting an alternative.
	AutoDeny
	// Escalate sends the request to the manual review queue for human review.
	Escalate
)

type ClassificationResult

type ClassificationResult struct {
	Decision    ClassificationDecision
	RiskLevel   RiskLevel
	Reason      string
	Alternative string
	RuleID      string
	RuleName    string
}

ClassificationResult holds the outcome of classifying a tool use request.

type Classifier

type Classifier interface {
	Classify(payload PermissionRequestPayload, ctx ClassificationContext) ClassificationResult
	BuildContext(cwd string) ClassificationContext
}

Classifier classifies a PermissionRequestPayload to determine the action to take.

type ClaudePermissions

type ClaudePermissions struct {
	Allow []string `json:"allow"` // tool patterns, e.g. "Bash(git log*)"
	Deny  []string `json:"deny,omitempty"`
}

ClaudePermissions mirrors the "permissions" key in ~/.claude/settings.json.

func ParseClaudeSettings

func ParseClaudeSettings(path string) (*ClaudePermissions, error)

ParseClaudeSettings reads a Claude settings.json file and extracts permissions. Returns nil permissions (no error) if the file does not exist or has no permissions key.

type CommandCriteria

type CommandCriteria struct {
	// Programs lists the allowed primary programs. Empty means any program matches.
	// Prefix matching handles versioned interpreters (e.g., "python3" matches "python3.11").
	Programs []string
	// Subcommands lists allowed subcommand values. Empty means any (or no) subcommand matches.
	// For deep-subcommand programs (gh, aws, etc.) multi-word entries are supported ("pr view").
	Subcommands []string
	// BlockedSubcommands lists subcommands that prevent this rule from matching.
	BlockedSubcommands []string
	// RequiredFlags: at least one of the listed flags must be present in the command args.
	// Uses exact token matching (e.g., RequiredFlags: ["--hard"] matches git reset --hard only).
	RequiredFlags []string
	// RequiredFlagPrefixes: like RequiredFlags but uses prefix matching.
	// Useful when a flag accepts an optional inline value (e.g., sed -i.bak satisfies prefix "-i").
	RequiredFlagPrefixes []string
	// ForbiddenFlags: if any of these flags appear in args, the rule does not match.
	ForbiddenFlags []string
	// PythonModes restricts matching to specific Python invocation modes.
	// Valid values: "inline" (-c), "module" (-m), "version" (-V/--version), "script" (*.py).
	// Empty means no Python-mode check is performed.
	PythonModes []string
}

CommandCriteria provides structured, composable matching criteria for Bash commands. It is evaluated against a ParsedCommand and allows precise rules without complex regex. When multiple fields are set, all must match (AND semantics).

func (*CommandCriteria) Matches

func (cc *CommandCriteria) Matches(pc ParsedCommand) bool

Matches returns true if pc satisfies all criteria fields.

type CommandInfo

type CommandInfo struct {
	// Program is the primary executable being invoked (first non-env-var, non-wrapper token).
	Program string
	// Subcommand is the first positional argument after the program, if it looks like a
	// subcommand (i.e., does not start with '-').
	Subcommand string
	// Category classifies Program into a high-level category (e.g., "vcs", "runtime").
	Category string
	// AllPrograms contains all distinct programs found across the full command line,
	// including across pipes, semicolons, and logical operators.
	AllPrograms []string
}

CommandInfo contains parsed information extracted from a Bash command string.

func ParseBashCommand

func ParseBashCommand(command string) CommandInfo

ParseBashCommand extracts structured categorization information from a Bash command. It handles pipelines (|), sequential commands (;, &&, ||), environment variable prefixes, path-qualified program names (/usr/bin/git), and sudo/exec wrappers.

type CommandStat

type CommandStat struct {
	Preview  string `json:"preview"`
	ToolName string `json:"tool_name"`
	Count    int    `json:"count"`
}

CommandStat is a command preview with a count.

type ConfigService

type ConfigService struct{}

ConfigService handles Claude configuration file RPC methods.

It is dependency-light: each call creates a fresh ClaudeConfigManager so there is no shared state to synchronise.

func NewConfigService

func NewConfigService() *ConfigService

NewConfigService creates a ConfigService.

func (*ConfigService) GetClaudeConfig

GetClaudeConfig retrieves a Claude configuration file by name.

func (*ConfigService) ListClaudeConfigs

ListClaudeConfigs returns all configuration files in the ~/.claude directory.

func (*ConfigService) UpdateClaudeConfig

UpdateClaudeConfig updates a Claude configuration file with atomic write and backup.

type ConnectRPCWebSocketHandler

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

func NewConnectRPCWebSocketHandler

func NewConnectRPCWebSocketHandler(sessionService *SessionService, scrollbackManager *scrollback.ScrollbackManager, tmuxStreamerManager *session.ExternalTmuxStreamerManager, streamingMode string) *ConnectRPCWebSocketHandler

NewConnectRPCWebSocketHandler creates a new ConnectRPC WebSocket handler tmuxStreamerManager is required for ALL sessions (managed and external) since they all use tmux capture-pane polling

func (*ConnectRPCWebSocketHandler) HandleWebSocket

func (h *ConnectRPCWebSocketHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request)

HandleWebSocket upgrades HTTP connection to WebSocket and handles ConnectRPC protocol

func (*ConnectRPCWebSocketHandler) SetExternalSessionSupport

func (h *ConnectRPCWebSocketHandler) SetExternalSessionSupport(
	discovery *session.ExternalSessionDiscovery,
)

SetExternalSessionSupport configures external session discovery support This enables the handler to discover and stream external sessions (via mux socket monitoring) Note: tmuxStreamerManager is already set in constructor since ALL sessions use it

type DailyBucket

type DailyBucket struct {
	Date        string `json:"date"` // "2006-01-02" in local time
	AutoAllow   int    `json:"auto_allow"`
	AutoDeny    int    `json:"auto_deny"`
	Escalate    int    `json:"escalate"`
	ManualAllow int    `json:"manual_allow"`
	ManualDeny  int    `json:"manual_deny"`
	Total       int    `json:"total"`
}

DailyBucket aggregates classification decisions for a single calendar day.

func ComputeDailyBuckets

func ComputeDailyBuckets(entries []AnalyticsEntry) []DailyBucket

ComputeDailyBuckets groups entries by calendar day (local time) sorted ascending. Pure function — no I/O.

func (DailyBucket) AutoApproveRate

func (b DailyBucket) AutoApproveRate() float64

AutoApproveRate returns the fraction of decisions that were auto-allowed.

type DatabaseService

type DatabaseService struct{}

DatabaseService implements the database/workspace switcher RPC methods. It is stateless: each call reads the filesystem directly.

func NewDatabaseService

func NewDatabaseService() *DatabaseService

NewDatabaseService creates a DatabaseService.

func (*DatabaseService) GetCurrentDatabase

GetCurrentDatabase returns metadata for the currently active workspace database.

func (*DatabaseService) ListDatabases

ListDatabases returns all discovered workspace databases with metadata.

func (*DatabaseService) MergeDatabase

MergeDatabase copies sessions from a source workspace into the current one. Uses INSERT OR IGNORE so existing sessions (matched by title) are never overwritten.

func (*DatabaseService) SwitchDatabase

SwitchDatabase writes a preference file and triggers an exec-based server self-restart. The client should poll until the server is back up, then reload the page.

type DebugSnapshot

type DebugSnapshot struct {
	Version    int                `json:"version"`
	Timestamp  time.Time          `json:"timestamp"`
	Note       string             `json:"note,omitempty"`
	Server     ServerInfo         `json:"server"`
	Sessions   []SessionSnapshot  `json:"sessions"`
	Tmux       TmuxSnapshot       `json:"tmux"`
	Approvals  ApprovalSnapshot   `json:"approvals"`
	RecentLogs RecentLogsSnapshot `json:"recent_logs"`
	Errors     []string           `json:"errors,omitempty"`
}

DebugSnapshot is the top-level JSON structure written to disk.

func CollectSnapshot

func CollectSnapshot(ctx context.Context, note string, instances []*session.Instance, approvalStore *ApprovalStore, logLines int) *DebugSnapshot

CollectSnapshot gathers all diagnostic data into a DebugSnapshot. Individual subsystem failures are recorded in Errors and do not abort the collection.

type DomainAgeChecker

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

DomainAgeChecker extracts domains from Bash commands and checks their registration age using RDAP (Registration Data Access Protocol). Results are cached for 24h.

A domain is considered "new" if its registration date is within the configured threshold (default 30 days). New domains from network-oriented commands are escalated for review.

func NewDomainAgeChecker

func NewDomainAgeChecker(enabled bool) *DomainAgeChecker

NewDomainAgeChecker creates a DomainAgeChecker with sensible defaults. Set enabled=false to disable RDAP lookups (no-op mode).

func (*DomainAgeChecker) IsNewlyRegistered

func (d *DomainAgeChecker) IsNewlyRegistered(ctx context.Context, domain string) (bool, error)

IsNewlyRegistered returns true if the domain was registered within the threshold and the check is enabled. Returns (false, nil) for any lookup failure, to avoid blocking legitimate operations on RDAP outages.

func (*DomainAgeChecker) NewDomainThreshold

func (d *DomainAgeChecker) NewDomainThreshold() time.Duration

NewDomainThreshold returns how old a domain must be to be considered "established".

type EscapeCodeHandler

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

EscapeCodeHandler provides REST endpoints for escape code analytics

func NewEscapeCodeHandler

func NewEscapeCodeHandler() *EscapeCodeHandler

NewEscapeCodeHandler creates a new handler using the global store

func (*EscapeCodeHandler) HandleClear

func (h *EscapeCodeHandler) HandleClear(w http.ResponseWriter, r *http.Request)

HandleClear clears all recorded escape codes DELETE /api/debug/escape-codes

func (*EscapeCodeHandler) HandleExport

func (h *EscapeCodeHandler) HandleExport(w http.ResponseWriter, r *http.Request)

HandleExport exports all data as JSON GET /api/debug/escape-codes/export

func (*EscapeCodeHandler) HandleGetAll

func (h *EscapeCodeHandler) HandleGetAll(w http.ResponseWriter, r *http.Request)

HandleGetAll returns all escape code entries GET /api/debug/escape-codes

func (*EscapeCodeHandler) HandleGetByCategory

func (h *EscapeCodeHandler) HandleGetByCategory(w http.ResponseWriter, r *http.Request)

HandleGetByCategory returns entries for a specific category GET /api/debug/escape-codes/category/{category}

func (*EscapeCodeHandler) HandleGetBySession

func (h *EscapeCodeHandler) HandleGetBySession(w http.ResponseWriter, r *http.Request)

HandleGetBySession returns entries for a specific session GET /api/debug/escape-codes/session/{sessionId}

func (*EscapeCodeHandler) HandleGetStats

func (h *EscapeCodeHandler) HandleGetStats(w http.ResponseWriter, r *http.Request)

HandleGetStats returns aggregated statistics GET /api/debug/escape-codes/stats

func (*EscapeCodeHandler) HandleStatus

func (h *EscapeCodeHandler) HandleStatus(w http.ResponseWriter, r *http.Request)

HandleStatus returns the current tracking status GET /api/debug/escape-codes/status

func (*EscapeCodeHandler) HandleToggle

func (h *EscapeCodeHandler) HandleToggle(w http.ResponseWriter, r *http.Request)

HandleToggle enables or disables escape code tracking POST /api/debug/escape-codes/toggle Body: {"enabled": true/false}

func (*EscapeCodeHandler) RegisterRoutes

func (h *EscapeCodeHandler) RegisterRoutes(mux *http.ServeMux)

RegisterRoutes registers all escape code handler routes on the given mux

type ExternalWebSocketHandler

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

ExternalWebSocketHandler handles approval monitoring for external mux sessions. Terminal streaming has been migrated to the unified ConnectRPC WebSocket handler.

func NewExternalWebSocketHandler

func NewExternalWebSocketHandler(
	discovery *session.ExternalSessionDiscovery,
	tmuxStreamerManager *session.ExternalTmuxStreamerManager,
	approvalMonitor *session.ExternalApprovalMonitor,
	eventBus *events.EventBus,
) *ExternalWebSocketHandler

NewExternalWebSocketHandler creates a new handler for external session approval monitoring. Note: tmuxStreamerManager parameter is kept for backward compatibility but is no longer used since terminal streaming has been migrated to the unified ConnectRPC WebSocket handler.

func (*ExternalWebSocketHandler) HandleApprovalResponse

func (h *ExternalWebSocketHandler) HandleApprovalResponse(w http.ResponseWriter, r *http.Request)

HandleApprovalResponse handles user response to an approval request

func (*ExternalWebSocketHandler) HandleApprovals

func (h *ExternalWebSocketHandler) HandleApprovals(w http.ResponseWriter, r *http.Request)

HandleApprovals returns pending approvals for an external session

type GitHubService

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

GitHubService handles all GitHub PR RPC methods.

These methods shell out to the `gh` CLI and have no dependency on review queue, terminal streaming, or search. They only need to look up a session by ID and call PR operations on it.

func NewGitHubService

func NewGitHubService(storage *session.Storage) *GitHubService

NewGitHubService creates a GitHubService backed by the given storage.

func (*GitHubService) ClosePR

ClosePR closes the PR without merging for a session.

func (*GitHubService) GetPRComments

GetPRComments retrieves all comments on the PR for a session.

func (*GitHubService) GetPRInfo

GetPRInfo retrieves the latest PR information for a session.

func (*GitHubService) MergePR

MergePR merges the PR for a session using the specified merge method.

func (*GitHubService) PostPRComment

PostPRComment posts a new comment to the PR for a session.

type ImportStat

type ImportStat struct {
	Module string `json:"module"`
	Count  int    `json:"count"`
}

ImportStat is a Python module import with its usage count.

type NotificationRateLimiter

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

NotificationRateLimiter provides per-session rate limiting for notifications. Prevents notification flooding from individual sessions while allowing legitimate notification volumes across all sessions.

func NewNotificationRateLimiter

func NewNotificationRateLimiter(r float64, b int) *NotificationRateLimiter

NewNotificationRateLimiter creates a rate limiter. rate: notifications per second (e.g., 10) burst: max burst size (e.g., 20)

func (*NotificationRateLimiter) Allow

func (rl *NotificationRateLimiter) Allow(sessionID string) bool

Allow checks if a notification is allowed for the given session. Returns true if the notification should be processed, false if rate limited.

func (*NotificationRateLimiter) Cleanup

func (rl *NotificationRateLimiter) Cleanup(activeSessions []string)

Cleanup removes rate limiters for sessions that are no longer active. Should be called periodically to prevent memory leaks.

func (*NotificationRateLimiter) Count

func (rl *NotificationRateLimiter) Count() int

Count returns the number of active rate limiters (for monitoring).

func (*NotificationRateLimiter) Reset

func (rl *NotificationRateLimiter) Reset(sessionID string)

Reset removes the rate limiter for a specific session. Useful for testing or when a session is recreated.

type NotificationService

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

NotificationService handles notification sending and history RPCs.

Dependencies:

  • notificationStore: persists notification history
  • notificationRateLimiter: rate-limits per-session notification sends
  • eventBus: broadcasts notification events to connected clients
  • reviewQueuePoller: late-wired; used to resolve session names

func NewNotificationService

func NewNotificationService(
	rateLimiter *NotificationRateLimiter,
	eventBus *events.EventBus,
) *NotificationService

NewNotificationService creates a NotificationService with the given dependencies.

func (*NotificationService) ClearNotificationHistory

ClearNotificationHistory removes notifications from the history.

func (*NotificationService) GetNotificationHistory

GetNotificationHistory returns persisted notification history with optional filtering.

func (*NotificationService) GetNotificationStore

func (ns *NotificationService) GetNotificationStore() *notifications.NotificationHistoryStore

GetNotificationStore returns the notification history store.

func (*NotificationService) MarkNotificationRead

MarkNotificationRead marks specific notifications as read. If notification_ids is empty, marks all notifications as read.

func (*NotificationService) SendNotification

SendNotification allows tmux sessions and external Claude processes to send notifications. Enforces localhost-only restriction and rate limiting. Accepts both managed sessions and external sessions (e.g., Claude running in IntelliJ, VS Code, or other terminals).

func (*NotificationService) SetNotificationStore

func (ns *NotificationService) SetNotificationStore(store *notifications.NotificationHistoryStore)

SetNotificationStore sets the notification history store (late-wired).

func (*NotificationService) SetReviewQueuePoller

func (ns *NotificationService) SetReviewQueuePoller(poller *session.ReviewQueuePoller)

SetReviewQueuePoller sets the review queue poller for resolving session names.

type ParsedCommand

type ParsedCommand struct {
	// Program is the primary executable (path-stripped).
	Program string
	// Args is the list of remaining tokens.
	Args []string
	// Raw is the reconstructed "program arg1 arg2 …" string for pattern matching.
	Raw string
}

ParsedCommand is a single simple command extracted from a (potentially compound) shell command.

func ExtractAllCommands

func ExtractAllCommands(cmd string) []ParsedCommand

ExtractAllCommands parses cmd with mvdan.cc/sh and recursively walks the AST, returning all CallExpr nodes — including those inside $(), backticks, and process substitutions. Falls back to splitCommandParts() on parse error.

type PendingApproval

type PendingApproval struct {
	ID              string
	SessionID       string // stapler-squad session title (mapped from hook)
	ClaudeSessionID string // Claude Code's internal session_id
	ToolName        string
	ToolInput       map[string]interface{}
	Cwd             string
	PermissionMode  string
	CreatedAt       time.Time
	ExpiresAt       time.Time

	// Orphaned is true for approvals loaded from disk after a server restart.
	// These have no live HTTP connection, so they cannot be resolved via the decision channel.
	Orphaned bool
	// contains filtered or unexported fields
}

PendingApproval represents an in-flight hook approval waiting for a user decision.

type PermissionRequestPayload

type PermissionRequestPayload struct {
	SessionID      string                 `json:"session_id"`
	TranscriptPath string                 `json:"transcript_path"`
	Cwd            string                 `json:"cwd"`
	PermissionMode string                 `json:"permission_mode"`
	HookEventName  string                 `json:"hook_event_name"`
	ToolName       string                 `json:"tool_name"`
	ToolInput      map[string]interface{} `json:"tool_input"`
}

PermissionRequestPayload is the JSON payload from Claude Code's PermissionRequest HTTP hook.

type PersistedApproval

type PersistedApproval struct {
	ID              string                 `json:"id"`
	SessionID       string                 `json:"session_id"`
	ClaudeSessionID string                 `json:"claude_session_id"`
	ToolName        string                 `json:"tool_name"`
	ToolInput       map[string]interface{} `json:"tool_input"`
	Cwd             string                 `json:"cwd"`
	PermissionMode  string                 `json:"permission_mode"`
	CreatedAt       time.Time              `json:"created_at"`
	ExpiresAt       time.Time              `json:"expires_at"`
	Orphaned        bool                   `json:"orphaned"`
}

PersistedApproval is the JSON-serializable representation of a PendingApproval for disk storage.

type ProgramStat

type ProgramStat struct {
	Program  string `json:"program"`
	Category string `json:"category"`
	Count    int    `json:"count"`
}

ProgramStat is a command program with its category and usage count.

type PythonInfo

type PythonInfo struct {
	// Imports contains top-level module names imported in inline Python code.
	// Only populated when -c is used (inline code), not for script files.
	Imports []string
	// IsInline is true when code was passed via the -c flag.
	IsInline bool
}

PythonInfo contains information extracted from a Python command invocation.

func ParsePythonCommand

func ParsePythonCommand(command string) PythonInfo

ParsePythonCommand extracts Python import information from a python/python3 invocation. Only parses inline code passed via the -c flag; script files are not read.

type ReactiveQueueManager

type ReactiveQueueManager interface {
	AddStreamClient(ctx context.Context, filters interface{}) (<-chan *sessionv1.ReviewQueueEvent, string)
	RemoveStreamClient(clientID string)
}

ReactiveQueueManager is an interface to avoid circular dependencies. The actual implementation is in server/review_queue_manager.go

type RecentLogsSnapshot

type RecentLogsSnapshot struct {
	LogFilePath string   `json:"log_file_path"`
	LineCount   int      `json:"line_count"`
	Lines       []string `json:"lines"`
}

RecentLogsSnapshot contains the most recent log lines.

type ReviewQueueChecker

type ReviewQueueChecker interface {
	FindInstance(sessionID string) *session.Instance
	CheckSession(inst *session.Instance)
}

ReviewQueueChecker is an interface for triggering immediate review queue checks. This avoids importing the session package's concrete ReviewQueuePoller type directly.

type ReviewQueueService

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

ReviewQueueService handles all review-queue-related RPC methods, extracted from the monolithic SessionService for separation of concerns.

Dependencies it owns (moved out of SessionService):

  • reviewQueue: stateful queue managed by ReviewQueuePoller
  • reactiveQueueMgr: streams live review queue events to clients

Dependencies it borrows (still on SessionService, passed via setters):

  • storage: needed by AcknowledgeSession to persist ack timestamps
  • reviewQueuePoller: needed by AcknowledgeSession to refresh poller refs
  • eventBus: needed by AcknowledgeSession and LogUserInteraction

func NewReviewQueueService

func NewReviewQueueService(
	reviewQueue *session.ReviewQueue,
	storage *session.Storage,
	eventBus *events.EventBus,
) *ReviewQueueService

NewReviewQueueService creates a ReviewQueueService with the required state.

func (*ReviewQueueService) AcknowledgeSession

AcknowledgeSession marks a session as acknowledged in the review queue. The session won't reappear in the queue until it receives an update.

func (*ReviewQueueService) GetQueue

func (rqs *ReviewQueueService) GetQueue() *session.ReviewQueue

GetQueue returns the underlying ReviewQueue for wiring reactive components.

func (*ReviewQueueService) GetReviewQueue

GetReviewQueue returns sessions needing user attention with priority ordering. Uses the global stateful queue managed by ReviewQueuePoller, with optional filtering.

func (*ReviewQueueService) LogUserInteraction

LogUserInteraction logs a user interaction event for audit trail and analytics.

func (*ReviewQueueService) SetApprovalStore

func (rqs *ReviewQueueService) SetApprovalStore(store *ApprovalStore)

SetApprovalStore injects the ApprovalStore for enriching APPROVAL_PENDING items with their pending_approval_id metadata.

func (*ReviewQueueService) SetReactiveQueueManager

func (rqs *ReviewQueueService) SetReactiveQueueManager(mgr ReactiveQueueManager)

SetReactiveQueueManager injects the ReactiveQueueManager (dependency injection). Must be called before WatchReviewQueue is used.

func (*ReviewQueueService) SetReviewQueuePoller

func (rqs *ReviewQueueService) SetReviewQueuePoller(poller *session.ReviewQueuePoller)

SetReviewQueuePoller injects the ReviewQueuePoller used to refresh instance references after acknowledgement.

func (*ReviewQueueService) WatchReviewQueue

WatchReviewQueue streams real-time review queue events.

type RiskLevel

type RiskLevel int

RiskLevel indicates the severity of a tool use request.

const (
	RiskLow RiskLevel = iota
	RiskMedium
	RiskHigh
	RiskCritical
)

type Rule

type Rule struct {
	ID   string
	Name string
	// ToolName is an exact match on the tool name (case-insensitive). If non-empty, ToolPattern is ignored.
	ToolName string
	// ToolPattern matches against the tool name when ToolName is empty.
	ToolPattern *regexp.Regexp
	// ToolCategory matches against the structural category returned by CategorizeToolName.
	// Evaluated after ToolName/ToolPattern (those take precedence when non-empty).
	// Use one of the ToolCategory* constants. Empty string means any category matches.
	ToolCategory string
	// Criteria provides structured matching for Bash command programs, subcommands and flags.
	// When set alongside CommandPattern, both must match (AND semantics).
	Criteria *CommandCriteria
	// CommandPattern matches against tool_input["command"]. nil means any command matches.
	CommandPattern *regexp.Regexp
	// FilePattern matches against tool_input["file_path"]. nil means any file path matches.
	FilePattern *regexp.Regexp
	Decision    ClassificationDecision
	RiskLevel   RiskLevel
	Reason      string
	Alternative string
	// Priority determines rule evaluation order. Higher values are evaluated first.
	Priority int
	Enabled  bool
	// Source tracks how the rule was loaded: "seed", "user", or "claude-settings".
	Source string
}

Rule is a single classification rule evaluated against a tool use request.

func LoadClaudeSettingsRules

func LoadClaudeSettingsRules(projectDir string) []Rule

LoadClaudeSettingsRules parses both the global and project-level Claude settings and returns AutoAllow rules derived from their permissions.allow lists.

Search order:

  1. ~/.claude/settings.json (global)
  2. ~/.claude/settings.local.json (global local overrides)
  3. <projectDir>/.claude/settings.json (project)
  4. <projectDir>/.claude/settings.local.json (project local)

Project settings take precedence: if both define the same tool pattern, the project rule will be checked first due to higher priority.

func SeedRules

func SeedRules() []Rule

SeedRules returns the built-in rule set, sorted by Priority descending. Priority tiers:

1000 — AutoDeny (critical, must fire before any allow)
 500 — Escalate-before-allow (targeted escalations that override allow rules at 100)
 100 — AutoAllow (standard development operations)
  50 — Escalate catch-all (operations with no allow rule; provides a helpful reason)

Criteria-based rules provide precise matching without complex regex; CommandPattern is retained only where regex expressiveness is needed.

type RuleBasedClassifier

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

RuleBasedClassifier evaluates a priority-ordered list of Rules.

func NewRuleBasedClassifier

func NewRuleBasedClassifier() *RuleBasedClassifier

NewRuleBasedClassifier creates a classifier pre-loaded with seed rules.

func (*RuleBasedClassifier) AddRules

func (c *RuleBasedClassifier) AddRules(rules []Rule)

AddRules appends additional rules and re-sorts by priority.

func (*RuleBasedClassifier) BuildContext

func (c *RuleBasedClassifier) BuildContext(cwd string) ClassificationContext

BuildContext detects git repository state for the given working directory.

func (*RuleBasedClassifier) Classify

Classify evaluates rules in priority order and returns the first match. For Bash commands, compound commands (with &&, |, ;, $(), etc.) are evaluated using classifyCompound to ensure every sub-command is covered. If no rule matches, returns Escalate for human review.

func (*RuleBasedClassifier) ReplaceRules

func (c *RuleBasedClassifier) ReplaceRules(rules []Rule)

ReplaceRules atomically replaces all rules with the provided list.

func (*RuleBasedClassifier) Rules

func (c *RuleBasedClassifier) Rules() []Rule

Rules returns a copy of the current rule set.

type RuleSpec

type RuleSpec struct {
	ID             string    `json:"id"`
	Name           string    `json:"name"`
	ToolName       string    `json:"tool_name,omitempty"`
	ToolPattern    string    `json:"tool_pattern,omitempty"`
	CommandPattern string    `json:"command_pattern,omitempty"`
	FilePattern    string    `json:"file_pattern,omitempty"`
	Decision       string    `json:"decision"`   // "auto_allow" | "auto_deny" | "escalate"
	RiskLevel      string    `json:"risk_level"` // "low" | "medium" | "high" | "critical"
	Reason         string    `json:"reason,omitempty"`
	Alternative    string    `json:"alternative,omitempty"`
	Priority       int       `json:"priority"`
	Enabled        bool      `json:"enabled"`
	Source         string    `json:"source"` // "user" | "seed" | "claude-settings"
	CreatedAt      time.Time `json:"created_at"`
}

RuleSpec is the JSON-serializable form of a Rule. CommandPattern and FilePattern are stored as strings (compiled on load).

type RuleStat

type RuleStat struct {
	RuleID   string `json:"rule_id"`
	RuleName string `json:"rule_name"`
	Count    int    `json:"count"`
}

RuleStat is a rule with its trigger count.

type RulesFile

type RulesFile struct {
	Version int        `json:"version"`
	Rules   []RuleSpec `json:"rules"`
}

RulesFile is the top-level structure of auto_approve_rules.json.

type RulesService

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

RulesService handles auto-approval rule management and analytics RPCs.

func NewRulesService

func NewRulesService(rulesStore *RulesStore, analyticsStore *AnalyticsStore, classifier *RuleBasedClassifier) *RulesService

NewRulesService creates a RulesService.

func (*RulesService) DeleteApprovalRule

DeleteApprovalRule removes a user rule by ID.

func (*RulesService) GetApprovalAnalytics

GetApprovalAnalytics returns aggregated analytics for the requested time window.

func (*RulesService) ListApprovalRules

ListApprovalRules returns all rules: user + seed + claude-settings.

func (*RulesService) UpsertApprovalRule

UpsertApprovalRule creates or updates a user rule.

type RulesStore

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

RulesStore manages user-defined rules persisted to disk. Thread-safe for concurrent reads.

func NewRulesStore

func NewRulesStore(filePath string) (*RulesStore, error)

NewRulesStore creates a RulesStore backed by the given file path. If the file does not exist, an empty store is returned (no error).

func (*RulesStore) All

func (s *RulesStore) All() []RuleSpec

All returns user rules as compiled Rules (source="user" only).

func (*RulesStore) Delete

func (s *RulesStore) Delete(id string) error

Delete removes a user rule by ID. Returns error if not found or not a user rule.

func (*RulesStore) ToRules

func (s *RulesStore) ToRules() []Rule

ToRules converts specs to compiled Rules, skipping specs with invalid regex.

func (*RulesStore) Upsert

func (s *RulesStore) Upsert(spec RuleSpec) (RuleSpec, error)

Upsert creates or updates a user rule. Source must be "user". Returns the upserted spec.

func (*RulesStore) WatchAndReload

func (s *RulesStore) WatchAndReload(ctx context.Context)

WatchAndReload starts a goroutine that reloads rules when the file changes. The goroutine exits when ctx is canceled.

type SearchService

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

SearchService handles all Claude history and full-text search RPC methods.

It owns the history cache and search engine state that were previously scattered across SessionService.

Bug note: historyCacheMu protects the history cache fields from concurrent access. Without this, concurrent ListClaudeHistory calls would race on cache refresh (previously unprotected on SessionService).

func NewSearchService

func NewSearchService(
	searchEngine *search.SearchEngine,
	snippetGenerator *search.SnippetGenerator,
	historyCacheTTL time.Duration,
) *SearchService

NewSearchService creates a SearchService with the given search components.

func (*SearchService) GetClaudeHistoryDetail

GetClaudeHistoryDetail retrieves detailed information for a specific history entry.

func (*SearchService) GetClaudeHistoryMessages

GetClaudeHistoryMessages retrieves messages from a specific conversation.

func (*SearchService) ListClaudeHistory

ListClaudeHistory returns Claude session history entries with optional filtering.

func (*SearchService) SearchClaudeHistory

SearchClaudeHistory performs full-text search across Claude conversation history.

type SecretScanResult

type SecretScanResult struct {
	Found       bool
	PatternName string // name of the first matching pattern
}

SecretScanResult holds the result of scanning for secrets.

func ScanForSecrets

func ScanForSecrets(text string) SecretScanResult

ScanForSecrets checks text for known secret patterns. Returns the first match found, or an empty result if none. Only the first 4096 bytes are scanned to bound performance on very long commands.

type ServerInfo

type ServerInfo struct {
	PID           int    `json:"pid"`
	UptimeSeconds int64  `json:"uptime_seconds"`
	GoVersion     string `json:"go_version"`
	OS            string `json:"os"`
	Arch          string `json:"arch"`
}

ServerInfo contains runtime metadata for the server process.

type SessionService

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

SessionService implements the SessionServiceHandler interface for ConnectRPC.

func NewSessionService

func NewSessionService(storage session.InstanceStore, eventBus *events.EventBus) *SessionService

NewSessionService creates a new SessionService with the given storage and event bus. NOTE: Instances are NOT loaded here to prevent double-loading and initialization timing issues. Instances will be loaded in server.go after dependencies (statusManager, reviewQueue) are wired.

func NewSessionServiceFromConfig

func NewSessionServiceFromConfig() (*SessionService, error)

NewSessionServiceFromConfig creates a SessionService using EntRepository as storage backend. On first startup, if the legacy state.json exists and Ent DB is empty, sessions are auto-migrated from JSON to Ent.

func (*SessionService) AcknowledgeSession

AcknowledgeSession marks a session as acknowledged in the review queue. The session won't reappear in the queue until it receives an update.

func (*SessionService) ClearNotificationHistory

ClearNotificationHistory removes notifications from the history.

func (*SessionService) ClosePR

ClosePR closes the PR without merging for a session.

func (*SessionService) CreateCheckpoint

CreateCheckpoint captures the current state of a session as a named bookmark.

func (*SessionService) CreateDebugSnapshot

CreateDebugSnapshot captures diagnostic information and writes a JSON file to the log directory.

func (*SessionService) CreateSession

CreateSession initializes a new AI agent session with tmux and git worktree.

func (*SessionService) DeleteApprovalRule

DeleteApprovalRule removes a user-defined auto-approval rule by ID.

func (*SessionService) DeleteSession

DeleteSession stops and removes a session, cleaning up resources.

func (*SessionService) FocusWindow

FocusWindow activates a window for the specified application.

func (*SessionService) ForkSession

ForkSession creates a new independent session branched from a checkpoint on an existing session.

func (*SessionService) GetAnalyticsStore

func (s *SessionService) GetAnalyticsStore() *AnalyticsStore

GetAnalyticsStore returns the analytics store for wiring up the ApprovalHandler.

func (*SessionService) GetApprovalAnalytics

GetApprovalAnalytics returns aggregated analytics for classification decisions.

func (*SessionService) GetApprovalStore

func (s *SessionService) GetApprovalStore() *ApprovalStore

GetApprovalStore returns the approval store for wiring up the HTTP hook handler.

func (*SessionService) GetClassifier

func (s *SessionService) GetClassifier() *RuleBasedClassifier

GetClassifier returns the rule-based classifier for wiring up the ApprovalHandler.

func (*SessionService) GetClaudeConfig

GetClaudeConfig retrieves a Claude configuration file by name.

func (*SessionService) GetClaudeHistoryDetail

GetClaudeHistoryDetail retrieves detailed information for a specific history entry.

func (*SessionService) GetClaudeHistoryMessages

GetClaudeHistoryMessages retrieves messages from a specific conversation.

func (*SessionService) GetCurrentDatabase

GetCurrentDatabase returns metadata for the currently active workspace database.

func (*SessionService) GetEventBus

func (s *SessionService) GetEventBus() *events.EventBus

GetEventBus returns the event bus instance for wiring up reactive components.

func (*SessionService) GetInstanceStore added in v1.1.0

func (s *SessionService) GetInstanceStore() session.InstanceStore

GetInstanceStore returns the InstanceStore interface, suitable for both production and test code.

func (*SessionService) GetLogs

GetLogs retrieves application logs with optional filtering and search.

func (*SessionService) GetNotificationHistory

GetNotificationHistory returns persisted notification history with optional filtering.

func (*SessionService) GetNotificationStore

func (s *SessionService) GetNotificationStore() *notifications.NotificationHistoryStore

GetNotificationStore returns the notification history store.

func (*SessionService) GetPRComments

GetPRComments retrieves all comments on the PR for a session.

func (*SessionService) GetPRInfo

GetPRInfo retrieves the latest PR information for a session.

func (*SessionService) GetReviewQueue

GetReviewQueue returns sessions needing user attention with priority ordering.

func (*SessionService) GetReviewQueueInstance

func (s *SessionService) GetReviewQueueInstance() *session.ReviewQueue

GetReviewQueueInstance returns the review queue instance for wiring up reactive components.

func (*SessionService) GetSession

GetSession retrieves a specific session by ID (Title).

func (*SessionService) GetSessionDiff

GetSessionDiff retrieves the current git diff for a session.

func (*SessionService) GetStorage

func (s *SessionService) GetStorage() *session.Storage

GetStorage returns the concrete *session.Storage for components that haven't migrated to InstanceStore yet. Returns nil when SessionService was constructed with a fake InstanceStore (e.g., in unit tests). Prefer using the session.InstanceStore interface via GetInstanceStore() for new code.

func (*SessionService) GetVCSStatus

GetVCSStatus retrieves the current version control status for a session.

func (*SessionService) GetWorkspaceInfo

GetWorkspaceInfo retrieves VCS and workspace information for a session.

func (*SessionService) ListApprovalRules

ListApprovalRules returns all auto-approval rules (user, seed, and claude-settings).

func (*SessionService) ListCheckpoints

ListCheckpoints returns all checkpoints for the specified session.

func (*SessionService) ListClaudeConfigs

ListClaudeConfigs returns all configuration files in the ~/.claude directory.

func (*SessionService) ListClaudeHistory

ListClaudeHistory returns Claude session history entries with optional filtering.

func (*SessionService) ListDatabases

ListDatabases returns all discovered workspace databases with metadata.

func (*SessionService) ListPendingApprovals

ListPendingApprovals returns all pending Claude Code tool approval requests.

func (*SessionService) ListSessions

ListSessions returns all sessions with optional filtering. This includes both managed sessions and external mux-enabled sessions.

func (*SessionService) ListWorkspaceTargets

ListWorkspaceTargets returns available switch targets for a session.

func (*SessionService) LogUserInteraction

LogUserInteraction logs a user interaction event for audit trail and analytics.

func (*SessionService) MarkNotificationRead

MarkNotificationRead marks specific notifications as read.

func (*SessionService) MergeDatabase

MergeDatabase copies sessions from a source workspace into the current database.

func (*SessionService) MergePR

MergePR merges the PR for a session using the specified merge method.

func (*SessionService) PostPRComment

PostPRComment posts a new comment to the PR for a session.

func (*SessionService) RenameSession

RenameSession changes the title of an existing session. Validates that the new title doesn't conflict with existing sessions.

func (*SessionService) ResolveApproval

ResolveApproval allows the web UI to approve or deny a pending Claude Code tool use request.

func (*SessionService) RestartSession

RestartSession restarts a session by killing and recreating the tmux session. Optionally preserves terminal output for debugging purposes.

func (*SessionService) SearchClaudeHistory

SearchClaudeHistory performs full-text search across Claude conversation history.

func (*SessionService) SendNotification

SendNotification allows tmux sessions and external Claude processes to send notifications.

func (*SessionService) SetConfigService

func (s *SessionService) SetConfigService(svc *ConfigService)

SetConfigService wires the ConfigService for delegating config RPCs.

func (*SessionService) SetExternalDiscovery

func (s *SessionService) SetExternalDiscovery(discovery *session.ExternalSessionDiscovery)

SetExternalDiscovery sets the external session discovery for accessing mux-enabled sessions.

func (*SessionService) SetNotificationStore

func (s *SessionService) SetNotificationStore(store *notifications.NotificationHistoryStore)

SetNotificationStore sets the notification history store for the notification history RPCs and wires it into the approval service so resolved approvals are stamped with their decision.

func (*SessionService) SetReactiveQueueManager

func (s *SessionService) SetReactiveQueueManager(mgr ReactiveQueueManager)

SetReactiveQueueManager sets the ReactiveQueueManager (dependency injection). This must be called before WatchReviewQueue is used.

func (*SessionService) SetReviewQueuePoller

func (s *SessionService) SetReviewQueuePoller(poller *session.ReviewQueuePoller)

SetReviewQueuePoller wires the ReviewQueuePoller so new/deleted sessions are added/removed from the poller and AcknowledgeSession updates poller references. Must be called during server startup before any session mutation RPCs are used.

func (*SessionService) SetScrollbackManager

func (s *SessionService) SetScrollbackManager(mgr scrollbackSequencer)

SetScrollbackManager wires a scrollback sequence provider for checkpoint creation.

func (*SessionService) SetStatusManager

func (s *SessionService) SetStatusManager(mgr *session.InstanceStatusManager)

SetStatusManager wires the InstanceStatusManager so that instances loaded via loadInstancesWithWiring (e.g., fallback path in ListSessions) receive status tracking. Must be called during server startup.

func (*SessionService) StreamTerminal

StreamTerminal provides bidirectional streaming for terminal I/O with delta compression. Implements bidirectional streaming where: - Client sends: terminal input and resize events - Server sends: terminal deltas (compressed output) or raw output (fallback)

func (*SessionService) SwitchDatabase

SwitchDatabase switches to a different workspace database and restarts the server.

func (*SessionService) SwitchWorkspace

SwitchWorkspace switches a session's workspace to a different branch, revision, or worktree.

func (*SessionService) UpdateClaudeConfig

UpdateClaudeConfig updates a Claude configuration file with atomic write and backup.

func (*SessionService) UpdateSession

UpdateSession modifies session properties (pause/resume, category, title).

func (*SessionService) UpsertApprovalRule

UpsertApprovalRule creates or updates a user-defined auto-approval rule.

func (*SessionService) WatchReviewQueue

WatchReviewQueue streams real-time review queue events.

func (*SessionService) WatchSessions

WatchSessions streams real-time session events (created/updated/deleted). Sends initial snapshot of all sessions, then subscribes to real-time updates.

type SessionSnapshot

type SessionSnapshot struct {
	Title                string    `json:"title"`
	Status               string    `json:"status"`
	Program              string    `json:"program"`
	Path                 string    `json:"path"`
	Branch               string    `json:"branch"`
	SessionType          string    `json:"session_type"`
	Category             string    `json:"category"`
	Tags                 []string  `json:"tags"`
	CreatedAt            time.Time `json:"created_at"`
	UpdatedAt            time.Time `json:"updated_at"`
	LastTerminalUpdate   time.Time `json:"last_terminal_update,omitempty"`
	LastMeaningfulOutput time.Time `json:"last_meaningful_output,omitempty"`
	LastOutputSignature  string    `json:"last_output_signature,omitempty"`
	PaneContent          string    `json:"pane_content,omitempty"`
	PaneContentRaw       string    `json:"pane_content_raw,omitempty"`
	PaneContentTruncated bool      `json:"pane_content_truncated,omitempty"`
	InstanceType         string    `json:"instance_type"`
	GitHubPRNumber       int       `json:"github_pr_number,omitempty"`
}

SessionSnapshot captures the state of a single session at snapshot time.

type SubcommandStat

type SubcommandStat struct {
	Program    string `json:"program"`
	Subcommand string `json:"subcommand"`
	Category   string `json:"category"`
	Count      int    `json:"count"`
}

SubcommandStat is a (program, subcommand) pair with its usage count. Subcommand may contain a space for two-level CLIs (e.g., "pr create" for gh).

type TerminalWebSocketHandler

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

TerminalWebSocketHandler handles WebSocket connections for terminal streaming

func NewTerminalWebSocketHandler

func NewTerminalWebSocketHandler(storage session.Storage, eventBus *events.EventBus) *TerminalWebSocketHandler

NewTerminalWebSocketHandler creates a new WebSocket handler for terminal streaming

func (*TerminalWebSocketHandler) HandleWebSocket

func (h *TerminalWebSocketHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request)

HandleWebSocket upgrades HTTP connection to WebSocket and handles terminal streaming

type TmuxSessionDetail

type TmuxSessionDetail struct {
	TmuxSessionName string `json:"tmux_session_name"`
	ListPanesOutput string `json:"list_panes_output,omitempty"`
	PaneContent     string `json:"pane_content,omitempty"`
}

TmuxSessionDetail captures per-tmux-session diagnostic info.

type TmuxSnapshot

type TmuxSnapshot struct {
	ListSessionsOutput string              `json:"list_sessions_output"`
	PerSession         []TmuxSessionDetail `json:"per_session"`
}

TmuxSnapshot captures global tmux state.

type ToolStat

type ToolStat struct {
	ToolName string `json:"tool_name"`
	Count    int    `json:"count"`
}

ToolStat is a tool name with a count.

type UtilityService

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

UtilityService handles miscellaneous utility RPCs: GetLogs, FocusWindow, and CreateDebugSnapshot.

Dependencies:

  • approvalStore: needed by CreateDebugSnapshot to capture pending approvals
  • reviewQueuePoller: late-wired; needed by CreateDebugSnapshot for live instances

func NewUtilityService

func NewUtilityService(approvalStore *ApprovalStore) *UtilityService

NewUtilityService creates a UtilityService with the given dependencies.

func (*UtilityService) CreateDebugSnapshot

CreateDebugSnapshot captures diagnostic information and writes a JSON file to the log directory.

func (*UtilityService) FocusWindow

FocusWindow activates a window for the specified application. Uses AppleScript on macOS to bring the application to front.

func (*UtilityService) GetLogs

GetLogs retrieves application logs with optional filtering and search.

func (*UtilityService) SetReviewQueuePoller

func (us *UtilityService) SetReviewQueuePoller(poller *session.ReviewQueuePoller)

SetReviewQueuePoller sets the review queue poller (late-wired).

type WatchReviewQueueFilters

type WatchReviewQueueFilters struct {
	PriorityFilter    []session.Priority
	ReasonFilter      []session.AttentionReason
	SessionIDs        []string
	IncludeStatistics bool
	InitialSnapshot   bool
}

WatchReviewQueueFilters contains filters for review queue event streaming.

func (*WatchReviewQueueFilters) GetIncludeStatistics

func (f *WatchReviewQueueFilters) GetIncludeStatistics() bool

func (*WatchReviewQueueFilters) GetInitialSnapshot

func (f *WatchReviewQueueFilters) GetInitialSnapshot() bool

func (*WatchReviewQueueFilters) GetPriorityFilter

func (f *WatchReviewQueueFilters) GetPriorityFilter() []session.Priority

Implement FilterProvider interface for type-safe conversion.

func (*WatchReviewQueueFilters) GetReasonFilter

func (f *WatchReviewQueueFilters) GetReasonFilter() []session.AttentionReason

func (*WatchReviewQueueFilters) GetSessionIDs

func (f *WatchReviewQueueFilters) GetSessionIDs() []string

type WorkspaceService

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

WorkspaceService handles all VCS/workspace RPC methods.

These methods operate on session workspace state (git/jj status, branch switching, worktrees) and may emit events after state-modifying operations.

func NewWorkspaceService

func NewWorkspaceService(storage *session.Storage, eventBus *events.EventBus) *WorkspaceService

NewWorkspaceService creates a WorkspaceService with the given dependencies.

func (*WorkspaceService) GetVCSStatus

GetVCSStatus retrieves the current version control status for a session.

func (*WorkspaceService) GetWorkspaceInfo

GetWorkspaceInfo retrieves VCS and workspace information for a session.

func (*WorkspaceService) ListWorkspaceTargets

ListWorkspaceTargets returns available switch targets for a session.

func (*WorkspaceService) SwitchWorkspace

SwitchWorkspace switches a session's workspace to a different branch, revision, or worktree.

Jump to

Keyboard shortcuts

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