Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Stores Reference

All stores use SolidJS createStore for reactive state. Each store exposes a state getter and action methods.

terminalsStore

File: src/stores/terminals.ts

Manages terminal instances, active tab selection, split pane layout, and closed tab history.

State Shape

FieldTypeDescription
terminalsRecord<string, TerminalData>All terminals by ID
activeIdstring | nullCurrently active terminal
layoutTabLayoutSplit pane layout state

Key Types

interface TerminalData {
  id: string;
  sessionId: string | null;
  name: string;
  nameIsCustom: boolean;            // When true, OSC/status-line title changes are ignored
  fontSize: number;
  cwd: string | null;               // Current working directory (from OSC 7)
  awaitingInput: AwaitingInputType; // "question" | "error" | null
  awaitingInputConfident: boolean;  // High-confidence detection — don't clear on idle→busy
  shellState: ShellState;           // "busy" | "idle" | null
  activity: boolean;
  unseen: boolean;                  // Terminal completed work while user wasn't viewing it
  progress: number | null;          // OSC 9;4 progress (0-100), null when inactive
  agentType: AgentType | null;      // Detected foreground agent process (e.g. "claude")
  pendingResumeCommand: string | null; // Set at restore time, consumed on first shell idle
  pendingInitCommand: string | null;   // Setup/run script to auto-execute on first shell idle
  usageLimit: { percentage: number; limitType: string } | null;
  lastDataAt: number | null;        // Timestamp of last PTY output
  lastPrompt: string | null;        // Last relevant user prompt (>= 10 words), set by Rust
  agentIntent: string | null;       // LLM-declared intent via intent: token
  currentTask: string | null;       // Current agent task from status-line parsing
  activeSubTasks: number;           // Count of running sub-agents from ›› status line
  isRemote: boolean;                // Created via HTTP/MCP (not locally by the UI)
  agentSessionId: string | null;    // Agent session ID for session-specific resume
  tuicSession: string | null;       // Stable tab UUID — injected as TUIC_SESSION env var
  suggestedActions: string[] | null; // Follow-up suggestions from suggest: token
  suggestDismissed: boolean;        // true after user dismissed — prevents re-show
}

interface TabLayout {
  direction: SplitDirection;  // "none" | "vertical" | "horizontal"
  panes: string[];            // Terminal IDs (up to MAX_SPLIT_PANES = 6)
  ratios: number[];           // N fractions summing to 1.0 (length === panes.length)
  activePaneIndex: number;    // 0..N-1
}

Actions

MethodDescription
add(data)Add a terminal
remove(id)Remove a terminal
setActive(id)Set active terminal (clears activity flag)
update(id, data)Partial update terminal data
setSessionId(id, sessionId)Update session ID
setFontSize(id, fontSize)Update font size
setAwaitingInput(id, type)Set awaiting input indicator
clearAwaitingInput(id)Clear awaiting input
splitPane(direction)Split into two panes
closeSplitPane(index)Collapse back to single pane
setSplitRatio(ratio)Adjust split ratio
setActivePaneIndex(index)Switch active pane

Queries

MethodDescription
get(id)Get terminal by ID
getActive()Get active terminal
getIds()Get all terminal IDs
getCount()Get terminal count
hasAwaitingInput()Any terminal awaiting input?
getAwaitingInputIds()Get IDs of terminals awaiting input

repositoriesStore

File: src/stores/repositories.ts

Manages saved repositories, branches, terminal associations, and PR status cache.

State Shape

FieldTypeDescription
reposRecord<string, RepositoryState>Repositories by path
activePathstring | nullActive repository path

Key Types

interface RepositoryState {
  path: string;
  displayName: string;
  initials: string;
  isGitRepo?: boolean;    // false for plain directories
  expanded: boolean;      // Show branch list
  collapsed: boolean;     // Icon-only mode
  parked: boolean;        // Hidden from sidebar (recallable via popover)
  branches: Record<string, BranchState>;
  activeBranch: string | null;
}

interface BranchState {
  name: string;
  isMain: boolean;
  isShell?: boolean;               // true for non-git directory shell entries
  worktreePath: string | null;
  terminals: string[];             // Terminal IDs
  hadTerminals: boolean;           // Suppresses auto-spawn after close-all
  lastActiveTerminal: string | null;
  additions: number;
  deletions: number;
  isMerged: boolean;               // Fully merged into main branch
  lastCommitTs: number | null;     // Unix timestamp of last commit
  runCommand?: string;
  savedTerminals?: SavedTerminal[];
  ciAutoHeal?: { enabled: boolean; attempts: number; lastRunId?: number; healing?: boolean };
  layout?: TabLayout;              // Split layout persisted per-branch
}

Actions

MethodDescription
hydrate()Load from Rust backend
add(repo)Add repository
remove(path)Remove repository
setActive(path)Set active repository
toggleExpanded(path)Toggle branch list visibility
toggleCollapsed(path)Toggle icon-only mode
setBranch(repoPath, branchName, data)Add/update branch
setActiveBranch(repoPath, branchName)Set active branch
addTerminalToBranch(repoPath, branchName, terminalId)Link terminal
removeTerminalFromBranch(repoPath, branchName, terminalId)Unlink terminal
setRunCommand(repoPath, branchName, command)Save run command
updateBranchStats(repoPath, branchName, additions, deletions)Update diff stats
removeBranch(repoPath, branchName)Remove branch
renameBranch(repoPath, oldName, newName)Rename branch
reorderTerminals(repoPath, branchName, fromIndex, toIndex)Reorder tabs

Queries

MethodDescription
get(path)Get repository by path
getActive()Get active repository
getPaths()Get all repository paths
getActiveTerminals()Get terminal IDs for active branch
isEmpty()Check if no repositories

settingsStore

File: src/stores/settings.ts

Application settings: font, shell, IDE, theme, confirmations.

State Fields

FieldTypeDefaultDescription
ideIdeType"cursor"IDE for “Open in…”
fontFontType"JetBrains Mono"Terminal font
agentstring"claude"Primary agent
defaultFontSizenumber12Default font size
shellstring""Shell override
themestring"dark"Terminal theme
confirmBeforeQuitbooleantrueQuit confirmation
confirmBeforeClosingTabbooleantrueTab close confirmation
maxTabNameLengthnumber20Max tab name length

Constants

  • IDE_NAMES — Display names for IDEs
  • IDE_ICONS — Emoji icons
  • IDE_ICON_PATHS — SVG icon paths
  • IDE_CATEGORIES — IDE grouping (editors, terminals, git, utilities)
  • FONT_FAMILIES — CSS font-family strings

githubStore

File: src/stores/github.ts

GitHub PR and CI data with background polling.

Actions

MethodDescription
updateRepoData(repoPath, prStatuses)Update PR data for all branches (detects state transitions for notifications)
startPolling()Start background polling (30s base, 2m when hidden, 5m backoff on rate limit)
stopPolling()Stop polling
pollRepo(path)Immediately poll a single repo (debounced 2s to coalesce rapid git events)
setRemoteStatus(repoPath, remote)Set remote tracking status directly (used by simulator)

Queries

MethodDescription
getCheckSummary(repoPath, branch)Get CI check summary
getPrStatus(repoPath, branch)Get PR status
getCheckDetails(repoPath, branch)Get CI check details
getBranchPrData(repoPath, branch)Get full BranchPrStatus
getRemoteStatus(repoPath)Get remote tracking status (ahead/behind)

promptLibraryStore

File: src/stores/promptLibrary.ts

Prompt template management with variable substitution.

State Fields

FieldTypeDescription
promptsSavedPrompt[]All prompts
drawerOpenbooleanDrawer visibility
searchQuerystringSearch filter
selectedCategoryPromptCategoryCategory filter
recentIdsstring[]Recently used prompt IDs

Actions

MethodDescription
hydrate()Load from Rust
openDrawer() / closeDrawer() / toggleDrawer()Drawer visibility
createPrompt(data)Create new prompt
updatePrompt(id, data)Update prompt
deletePrompt(id)Delete prompt
toggleFavorite(id)Toggle pinned status
markAsUsed(id)Add to recent list
processContent(prompt, variables)Substitute variables (via Rust)
extractVariables(content)Parse {{variable}} placeholders (via Rust)

statusBarTicker

File: src/stores/statusBarTicker.ts

Rotating message ticker for the status bar. Plugins and native features post messages; the highest-priority message is displayed, with rotation among equal-priority messages.

TickerMessage Type

interface TickerMessage {
  id: string;           // Unique message ID (scoped to plugin)
  pluginId: string;     // Plugin that posted the message
  text: string;         // Display text (~40 chars max)
  icon?: string;        // Optional inline SVG icon
  priority: number;     // Higher = more visible. >=80 gets warning styling
  ttlMs: number;        // Time-to-live in ms (0 = persistent until removed)
  createdAt: number;    // Timestamp when added
  onClick?: () => void; // Optional click handler
}

Actions

MethodDescription
addMessage(msg)Add or replace a message (by id + pluginId). Resets TTL on replace.
removeMessage(id, pluginId)Remove a specific message
removeAllForPlugin(pluginId)Remove all messages from a plugin
clear()Clear all messages and stop timers

Queries

MethodDescription
getCurrentMessage()Get the highest-priority non-expired message (rotates among equal-priority)
getAll()Get all active (non-expired) messages

Internals

  • Rotation: Messages at the same priority level rotate every 5 seconds.
  • Scavenging: Expired messages (past TTL) are cleaned up every 1 second.
  • StatusBar integration: The claude-usage ticker message (pluginId "claude-usage") is absorbed into the agent badge when the active terminal runs Claude, and suppressed from the separate ticker area.

notesStore

File: src/stores/notes.ts

Persistent notes/ideas with per-repo tagging and usage tracking.

Note Type

interface Note {
  id: string;
  text: string;
  createdAt: number;
  repoPath: string | null;
  repoDisplayName: string | null;
  usedAt: number | null;      // Timestamp when sent to terminal
}

Actions

MethodDescription
hydrate()Load notes from Rust backend
addNote(text, repoPath?, repoDisplayName?)Add a new note, optionally tagged with a repo
removeNote(id)Remove a note by ID
reassignNote(id, repoPath, repoDisplayName)Reassign a note to a different project
markUsed(id)Mark a note as used (sets usedAt timestamp)

Queries

MethodDescription
getFilteredNotes(activeRepo)Get notes for repo (global + repo-specific). null = all notes.
filteredCount(activeRepo)Count of notes visible for the given repo filter
count()Total note count

Other Stores

repoSettingsStore (repoSettings.ts)

Per-repository settings (base branch, scripts, worktree options).

uiStore (ui.ts)

Panel visibility (sidebar, diff, markdown, notes, file browser), sidebar width, dropdown state, loading state.

notificationsStore (notifications.ts)

Notification sound preferences and playback. Remote orchestration muting uses the terminal’s backend-preserved isRemote origin; completion lifecycle code sets a per-busy-cycle latch before playback so idle and exit cannot both chime.

dictationStore (dictation.ts)

Whisper dictation config, model management, recording state.

errorHandlingStore (errorHandling.ts)

Error retry configuration and active retry tracking.

rateLimitStore (ratelimit.ts)

Active rate limit tracking per session.

tasksStore (tasks.ts)

Agent task queue management.

promptStore (prompt.ts)

Active prompt overlay state and agent stats buffer.

diffTabsStore (diffTabs.ts) / mdTabsStore (mdTabs.ts)

Open diff and markdown tab management (identical API patterns).

updaterStore (updater.ts)

App update check, download, and install. Supports stable (Tauri built-in), beta, and nightly channels.

keybindingsStore (keybindings.ts)

Rebindable keyboard shortcuts (persisted, auto-populated from action registry).

commandPaletteStore (commandPalette.ts)

Command palette visibility and search state.

activityDashboardStore (activityDashboard.ts)

Activity center (bell dropdown) visibility.

prNotificationsStore (prNotifications.ts)

PR state transition notifications (merged, closed, blocked, CI failed, etc.).

userActivityStore (userActivity.ts)

Tracks last user activity timestamp. Used for merged PR grace period calculations.

worktreeManagerStore (worktreeManager.ts)

Worktree Manager overlay state and selection.

State Shape:

FieldTypeDescription
isOpenbooleanOverlay visibility
selectedIdsSet<string>Multi-select worktree IDs
repoFilterstring | nullFilter by repo path
textFilterstringFree-text search filter

Actions: open(), close() (resets all state), toggle(), toggleSelect(id), selectAll(ids), clearSelection(), setRepoFilter(path), setTextFilter(text).

agentConfigsStore (agentConfigs.ts)

Per-agent configuration (spawn args, environment overrides).

editorTabsStore (editorTabs.ts)

Open code editor tabs (CodeEditorTab).

activityStore (activityStore.ts)

Session activity history and timeline data.

branchSwitcher (branchSwitcher.ts)

Branch switch state and loading indicators.

contextMenuActionsStore (contextMenuActionsStore.ts)

Dynamic context menu action registration.

errorLog (errorLog.ts)

Error ring buffer and error panel state.

pluginStore (pluginStore.ts)

Loaded plugin instances and lifecycle state.

registryStore (registryStore.ts)

Remote plugin registry cache and install state.

repoDefaults (repoDefaults.ts)

Default settings applied to newly added repositories.

tabManager (tabManager.ts)

Tab ordering, branch-key mapping, and tab persistence logic.

Exclusive pane activation. TerminalArea renders terminals, diffs, markdown and editors as four independent For lists, each marking its pane active from its OWN store’s activeId — so “only one pane shows” is a cross-store invariant. createTabManager registers a deactivator per store (registerPaneDeactivator); terminals.ts registers its own since it doesn’t use the factory. Activating a tab — setActive(id) with a non-null id, or _addTab — calls activatePaneExclusively(storeName), which clears every other store’s activeId. setActive(null) and the _addTabBackground variants are local: a background open must not yank the user out of the pane they’re in.

Call sites therefore must NOT hand-roll setActive(null) on the other stores. This replaced the useTabActivationSync hook, which enforced the same rule from deferred on(activeId) effects: an effect keyed on a change cannot enforce an invariant that has to hold on every activation request, so re-activating an already-active tab (Edit on a file whose editor tab was already the active one) wrote the same value, fired nothing, and left the other pane rendered underneath. Pinned by src/__tests__/stores/paneExclusivity.test.ts.

appLogger (appLogger.ts)

Centralized logging — replaces direct console.* calls. Writes to ring buffer, forwards to console, and surfaces in ErrorLogPanel.

debugRegistry (debugRegistry.ts)

Dynamic snapshot registry for MCP invoke_js introspection. Stores self-register a snapshot function at init time, exposed on window.__TUIC__ as stores() (list names) and store(name) (get snapshot).

Registered stores: github, globalWorkspace, keybindings, notes, paneLayout, repositories, settings, tasks, ui.

Adding a new store — append 2 lines at the end of the store file:

import { registerDebugSnapshot } from "./debugRegistry";
registerDebugSnapshot("storeName", () => ({ /* fields to expose */ }));

Each store decides what to expose — no need to modify debugGlobals.ts.