Agent System Overview
Tempest provides a unified interface for running multiple CLI-based AI coding agents (Claude Code, Gemini CLI, Opencode, and others) within isolated worktree environments. This guide explains how the agent system works internally and how sessions are managed.What Is an Agent Session?
An agent session in Tempest represents a single running instance of a CLI agent with the following components:PTY (Pseudo-Terminal): A pseudo-terminal spawned by the Tauri backend that captures all input and output between the agent and the user.
Working Directory (cwd): Either a git worktree branch or the project root. Each session is anchored to a filesystem location where the agent operates.
Git Context: Worktree sessions run on isolated git branches created automatically by Tempest. Root sessions run directly in the project root.
Conversation ID: A unique UUID that identifies the logical conversation thread. For resumable agents (Claude Code, Gemini CLI), this ID persists across restarts to maintain conversation context.
How Agents Are Launched
Command Construction
When you create a new agent session, Tempest performs these steps:- Generate a Session ID: A UUID is minted to uniquely identify this PTY instance.
-
Build the Agent Command: Tempest constructs the full command line based on the agent’s configuration in
AGENT_CONFIGS:- The agent’s executable name (e.g.,
claude,gemini) - Session/resume flags (if the agent supports resumption)
- An optional prompt passed by the user
- The agent’s executable name (e.g.,
- Spawn the PTY: The Rust backend invokes the native PTY system to create a pseudo-terminal at the session’s working directory.
Shell Integration
On Windows, agents run inside PowerShell with these flags:-NoExit / exec $SHELL -i flags ensure the terminal remains interactive after the agent process exits, allowing the user to type follow-up commands.
Argument Passing
Arguments are pre-assembled on the frontend inbuildAgentArgs() before being sent to the Rust backend. This includes:
- Session ID args: Passed on first spawn (e.g.,
--session-id <UUID>) - Resume args: Passed when reopening a saved session (e.g.,
--resume <UUID>) - Capture resume args: For agents like Opencode that print their ID (e.g.,
-s <captured-id>) - User prompt: Optional text the user wants the agent to start with
Work-Done Detection
Tempest automatically detects when an agent finishes its task so you know when to provide the next prompt. This is a multi-layered system that combines explicit signals from the agent with heuristic fallbacks.Work State States
A session can be in one of three work states:- Idle: No task is running; the agent is at its prompt waiting for input.
- Working: An agent is actively processing (after the user presses Enter).
- Done: The agent has finished its task and returned to its prompt, ready for the next input.
Signal-Based Detection (Explicit)
The SessionManager listens for explicit end-of-work signals encoded in terminal escape sequences: OSC 9;4 (Progress Bar) Windows Terminal and ConEmu’s progress bar protocol. State 0 signals task completion; other states indicate ongoing work. OSC 9 (Notification) An iTerm2 notification signal that many agents (including Claude Code) emit at turn completion. Highest priority signal. OSC 133 (FinalTerm Shell Integration) Shell integration protocol used by bash, zsh, and other modern shells:OSC 133;C: Command execution started (agent is busy)OSC 133;BorOSC 133;D: Command finished (agent is done)
Title-Based Detection (Agent-Specific)
For agents that set the terminal title via OSC 0/2, Tempest classifies the title to infer busy/idle state: Claude Code- Title starts with
✳(white dot): Agent is idle at its prompt. - Title starts with any other Unicode character: Agent is busy (spinner frames during thinking).
- Title starts with
◇: Idle at the prompt. - Title starts with
✦or✋: Busy/thinking.
Heuristic-Based Fallback (Timing)
If no explicit signals are detected, Tempest uses timing heuristics as a safety net:- Quiet Timer: Fires when 5 seconds pass with no PTY output.
- Ceiling Timer: Fires if the session remains in “working” state for more than 12 seconds (prevents false positives during long thinking).
- Dead Zone: Disables detection for 300ms after user input to avoid false positives during the agent’s silent thinking phase.
- Output Gate: Requires at least 200 bytes of output since the last user input before heuristic timers can fire. This prevents false “done” signals during extended thinking windows.
Session Persistence
Conversation IDs
Agent sessions are identified by two IDs:- Session ID: Ephemeral PTY identifier generated fresh each time the session opens. Not persisted.
- Conversation ID: Persisted UUID that uniquely identifies the logical conversation. For resumable agents (Claude Code, Gemini), this is set once on first spawn and reused across restarts. For agents without resume support, each spawn gets a fresh conversation ID (essentially a no-op).
Storage
Sessions are persisted to browser localStorage under thesessions slice of the runtime state. Each session stores:
name: Display name in the tab baragent: CLI command hint (e.g., “claude”, “gemini”)conversationId: The persistent UUID for resumptioninstanceId: Stable canonical identity (equals conversation ID or session ID depending on session type)projectId: Which project this session belongs toisRootSession: Whether it runs in the project root (true) or a worktree (false)noGit: Whether git was skipped for a root sessionclosed: Whether the session has been explicitly closed (soft deletion)
Worktree Sessions vs. Root Sessions
Worktree Sessions are persisted by their filesystem path as the key. They are safe to persist because the worktree path is stable on disk. Root Sessions (which run in the project root) cannot use the project path as a key since multiple sessions can share it. Instead, they use a unique key format:Agent Lifecycle
1. Session Creation (First Spawn)
- Generate a session UUID (becomes the conversation ID if the agent is resumable)
- Build the full command with session ID flags
- Invoke
create_pty_sessionon the Rust backend - Spawn the PTY in the target directory
- Stream output to the frontend via a Tauri Channel
- Save the session metadata to localStorage
- Display the agent session in a new tab
2. Running (User Interacts)
- User types in the terminal
- On
Enter, TerminalPane callsmarkUserInput()on the SessionManager - SessionManager enters “dead zone” (suppresses false positives for 300ms)
- All work-done detection systems (signals, title, timers) activate
- Agent processes and returns output
- When any detection system triggers, state becomes “done”
- A work-done badge (green dot) appears on the tab
3. Resumption (Session Reopened)
- On app startup, restoration loop collects all persisted sessions
- For each agent session, loads the stored
conversationId - Generates a new session UUID (fresh PTY spawn)
- Builds the command with resume flags:
claude --resume <stored-conversation-id> - Spawns the PTY
- User can continue the conversation from where they left off
4. Completion (Session Closed)
- Frontend calls
close_pty_sessionon the Rust backend - Rust terminates the PTY and all child processes
- Session is marked as
closed: truein localStorage (soft deletion) - Tab is removed from the sidebar
Broadcasting
Broadcasting allows you to send the same message to multiple agent sessions simultaneously. This is useful for running a command across all open agents or pausing work across projects.How It Works
- Press
Ctrl+Shift+M(or use the keyboard shortcut you configured) to open the Broadcast Dialog - Select which agents to target (or “All agents” for all open sessions)
- Type your message (e.g., “pause”, “check the logs”, etc.)
- Press
Ctrl+Enteror click “Send” to deliver it to all selected sessions
Broadcast Behavior
- All selected sessions are marked as “working”
- The message is encoded as UTF-8 bytes and sent to each session’s PTY
- Carriage return (
\r) is appended to simulate pressing Enter - Each session independently detects work completion using the standard work-done system
- A single broadcast instantly queues the same task across multiple agents
Use Cases
- Pause agents: Send “pause” or Ctrl+C to stop thinking
- Sync behavior: Run the same test or build across multiple branches
- Batch instructions: Tell all agents to review docs, check logs, or run linters
Message Queue
The message queue buffers messages for an agent when it is still working on a previous task. Instead of blocking, messages are queued and automatically sent when the agent returns to its prompt.Queue Behavior
- Agent is working: When you type a message and press Enter while the agent is still thinking, the message is queued instead of sent immediately.
- Agent finishes: When the agent’s work-done signal fires, the queue is checked. If a message is waiting, it is automatically sent.
- Queue persistence: Messages remain in the queue until the session closes or you manually clear them.
Accessing the Queue
PressCtrl+Shift+Q (or your configured shortcut) to open the QueuePanel for the active agent session. Here you can:
- View all queued messages in order
- Add new messages to the queue
- Remove individual messages
- Clear the entire queue
- See a badge on the tab indicating queue length
Example Workflow
- Agent is analyzing code (working)
- You type “Now check the tests” and press Enter
- Message is queued (not sent yet, since agent is busy)
- Agent finishes analyzing
- First queued message “Now check the tests” is automatically sent
- Agent responds with test results
- Agent finishes (work-done signal fires)
- Next queued message (if any) is sent
Environment and Configuration
Working Directory
Each session’s working directory is determined at creation:- Worktree sessions: The full path to the worktree directory (e.g.,
/project/.tempest/my-feature) - Root sessions: The project root directory (e.g.,
/project)
cwd set to this directory, so agents see the correct file context.
Shell Selection
Tempest automatically detects the default shell on first use:- Windows: Detects PowerShell 5.1 / PowerShell 7 / Command Prompt
- macOS/Linux: Uses
$SHELLenvironment variable, falls back to/bin/bash
MCP Configuration
If Token Intelligence (Atlas) is enabled, Tempest writes MCP server configuration to agent-specific files:- Claude Code:
.mcp.json - Cursor:
.cursor/mcp.json - Gemini CLI:
.gemini/settings.json - Opencode:
opencode.jsonoropencode.jsonc