Raw capture โ raw/stablyai-orca.md
url: https://github.com/stablyai/orca title: Orca author: stablyai date_fetched: 2026-08-01 date_published: 2025
Orca is a cross-platform Electron desktop application (macOS, Windows, Linux) that acts as an "AI orchestrator" โ it runs multiple CLI AI coding agents (Claude Code, Codex, OpenCode, Pi, Grok, and 20+ others) in parallel git worktrees, with a mobile companion app (iOS/Android). It's a meta-tool: it doesn't implement AI models but provides the environment, coordination, and persistence layer for running existing CLI agents at scale.
Scale: ~590,000 lines of TypeScript across ~9,500 source files. Version 1.4.163-rc.1 at analysis time. MIT licensed.
Orca uses Electron's standard multi-process model plus a custom daemon:
Main process (src/main/, ~888K lines Sloc): The application core. Manages app lifecycle, window creation, IPC handlers, PTY/provider system, agent hook server, SSH connections, orchestration engine, plugin system, persistent storage, telemetry, updates, and crash recovery. Entry point: src/main/index.ts (3,034 lines).
Renderer process (src/renderer/, ~22K lines): React 19 + Tailwind CSS 4 web UI with shadcn/ui component library, Monaco editor, Tiptap rich text, xterm.js terminals with WebGL rendering, dnd-kit drag-drop, TipTap markdown editor, Mermaid diagrams, KaTeX math, PDF.js. Single-page app loaded via src/renderer/index.html.
Preload layer (src/preload/, ~10K lines): Electron preload scripts bridging main โ renderer via contextBridge/ipcRenderer.
CLI (src/cli/, ~32K lines): Standalone orca CLI binary for scripting and agent-driven control. Handlers for worktree, browser, computer use, emulator, Linear, account management, etc.
Relay (src/relay/, ~48K lines): A long-lived relay process that maintains WebSocket connections for mobile pairing and SSH tunnel maintenance. Contains the relay HTTP client, session broker, E2E encryption, auth coordinator, and demand ledger for metering mobile โ desktop traffic.
Daemon (src/main/daemon/): A forked child process (via child_process.fork) that hosts persistent PTY sessions so they survive renderer crashes and window close. Communicates with main via IPC.
Mobile app (mobile/): React Native companion app (iOS/Android) for monitoring and steering agents from a phone.
Persistent PTY via Daemon: Instead of hosting PTY sessions in the main process (which would die on quit), Orca spawns a forked daemon process that owns the actual node-pty pseudo-terminals. The main process routes data between the daemon and the renderer. On restart, the main process reconnects to surviving daemon PTYs, and the renderer rehydrates terminal state from persistence. This is the single most architecturally significant decision โ it's what makes terminal sessions survive renderer crashes and window close.
Agent Hook Server: A local HTTP server (src/main/agent-hooks/server.ts) that listens on a loopback port for status pings from agent CLI hooks. Each supported agent (Claude Code, Codex, Pi, Grok, Cursor, etc.) has a managed hook installed into its runtime that POSTs state changes (idle โ working โ waiting โ blocked โ done) to this server. The server enriches events with timing, persists last-known state to disk (last-status.json), and forwards to the renderer via IPC. This is Orca's primary mechanism for knowing what agents are doing without parsing terminal output.
Hook installation is per-agent: For Claude Code it's via .claude/hooks/, for Codex via .codex/hooks/, for Pi via its native hook protocol, etc. The agent-hooks/ directory contains agent-specific installers that know each agent's hook contract. For remote/SSH agents, hooks are relayed through the SSH multiplexer back to the local hook server.
Worktree Isolation: Every agent session gets its own git worktree (or folder workspace). The worktree system (src/main/git/worktree.ts, src/main/worktree-create-base.ts) handles creation, base resolution, stale detection, and teardown. Worktrees can be local, WSL, or SSH-remote. Orca tracks per-worktree metadata (display name, first-agent-message rename, creation source) in a JSON store.
OrcaRuntimeService (src/main/runtime/orca-runtime.ts): The central orchestrator singleton. It manages:
- The live graph of worktrees, terminals, browser panes, and emulator panes
- Agent session claim identity (cryptographic session binding)
- PTY handle tracking and synthetic title injection
- Worktree lifecycle (create, clone, delete, rename)
- Orchestration dispatch (coordinator โ worker fan-out)
- File watcher registration and SSH re-arm
- Mobile session tab synchronization
SSH Multiplexer (src/main/ssh/): A custom SSH connection manager built on top of ssh2. Key features:
- Single SSH connection multiplexed across PTY, SFTP, git, file watching, and agent hook channels
- Auto-reconnect with incarnation tracking
- Port forwarding provider
- SSH config file parsing (OpenSSH-compatible)
- WSL-aware SSH (bridges Windows โ WSL SSH)
- Relay deployment: auto-installs Orca runtime on remote hosts
- Cross-platform: native, WSL, and SSH execution hosts
Relay System (src/main/runtime/relay/): Desktop โ mobile synchronization via a relay broker. Uses:
- WebSocket transport with E2E encryption (tweetnacl)
- Session broker for auth and routing
- Demand ledger for metering
- Mobile-specific RPC methods (terminal subscribe, file search, notification replay)
src/main/plugins/ implements a plugin architecture with:
- Plugin discovery from filesystem directories
- Bundled bootstrap plugins shipped with the app
- Marketplace integration for community plugins
- Consent and enablement management
- Kill list service for blocking known-malicious plugins
- Plugin-hosted in a separate child process for isolation
Orca uses a custom JSON store (src/main/persistence.ts) for all settings and metadata. There's no SQLite for core state โ only JSON files on disk. The orchestration system uses a separate SQLite database (src/main/runtime/orchestration/db.ts) for coordinator runs, task dispatch, and message history.
Terminal history is managed by src/main/terminal-history.ts with garbage collection, async deletion, and tombstone retry.
src/main/browser/ wraps Chromium (via Electron's BrowserView/webview) with:
- Agent-controllable browser panes (Design Mode for element picking)
- Offscreen browser backend for headless operation
- Certificate trust management
- Agent Browser Bridge (browser โ agent communication)
src/main/computer/ provides desktop automation via native accessibility APIs (macOS: Accessibility framework, Windows: UIA) for agents that need to operate desktop applications.
Each agent gets its own integration module:
- src/main/claude/ โ Claude Code (hook service, trust presets, session resume, live PTY persistence)
- src/main/codex/ โ Codex (hook service, runtime home management, session resume/migration, real-home vs managed-home)
- src/main/pi/ โ Pi
- src/main/grok/ โ Grok
- src/main/cursor/ โ Cursor
- src/main/copilot/ โ GitHub Copilot
- src/main/opencode/ โ OpenCode
- src/main/droid/ โ Droid
- src/main/gemini/ โ Gemini CLI
- src/main/antigravity/ โ Antigravity
- src/main/kimi/ โ Kimi
- src/main/mimo/ โ MiMo Code
- src/main/devin/ โ Devin
- src/main/hermes/ โ Hermes Agent
- src/main/command-code/ โ Command Code
- src/main/minimax/ โ MiniMax
- src/main/amp/ โ Amp
- src/main/openclaude/ โ OpenClaude
Each follows a similar pattern: account service, runtime auth/selection, hook installation, and session resume.
Orca detects agent state through two channels:
- OSC terminal titles (\x1b]0;...\x07): Parsed from PTY output by src/shared/agent-detection.ts and tracked per-terminal in orca-runtime.ts. This is the fallback for agents without managed hooks.
- Hook server pings: The primary mechanism. Hooks POST JSON payloads directly, which is more reliable and carries structured data (agent type, state, model, session metadata).
The hook server enriches events with receivedAt and stateStartedAt timestamps, persists them to last-status.json, and forwards to the renderer. The two paths are unified in src/shared/agent-hook-listener.ts which normalizes payloads from both sources.
For agents that don't natively emit OSC titles during active work, Orca injects synthetic title frames directly into the PTY data stream via sendSyntheticTitle(). This drives the UI spinner/status indicators. The injection is gated on window visibility to avoid unnecessary work. A shared interval timer (80ms) advances all active spinners, avoiding per-pane timers.
Rather than hosting PTY sessions in the main process, Orca forks a daemon child process that owns node-pty pseudo-terminals. The main process sends commands and receives data via IPC. This means:
- Terminal sessions survive renderer crashes
- Terminal sessions survive window close (hidden to tray)
- Terminal sessions survive main process restart (daemon checkpoint/restore)
The daemon uses node-pty patched (see config/patches/node-pty@1.1.0.patch) for custom behavior.
Instead of opening separate SSH connections for PTY, SFTP, file watching, and git, Orca multiplexes all channels over one SSH connection using ssh2's session/channel APIs. The ssh-channel-multiplexer.ts handles:
- Concurrent channel allocation
- Backpressure management
- Settlement (waiting for channel open confirmation)
- Lane scheduling for fair writer allocation
The Codex integration has the most complex session resume logic in the codebase. Orca intercepts the Codex CLI launch to inject --resume <session-id> when a prior session exists. It handles:
- Session provenance tracking (which CODEX_HOME owns which session)
- Legacy session migration from Orca-managed to system ~/.codex
- Real-home vs. managed-home hook installation
- Project trust pre-marking before PTY spawn
The orchestration coordinator (src/main/runtime/orchestration/coordinator.ts) implements a stale-base detection system. Before dispatching a task to a worker agent, it probes the worktree's git drift (commits behind base). If behind more than 20 commits (DISPATCH_STALE_THRESHOLD), it escalates rather than dispatching. Spec authors can opt out with allow-stale-base: true in the spec text.
Orca has extensive crash recovery mechanisms: - Renderer crash recovery: Automatic reload with exponential-ish backoff, circuit breaker after N consecutive crashes, manual recovery prompt as last resort - GPU crash fallback: Detects GPU process death bursts, prompts user to restart with software rendering, persists fallback marker across launches - Main thread hang watchdog: Detects event loop stalls, writes hang detection marker for next launch to read - Crash breadcrumbs: Coalesced crash breadcrumb store (last 30 events) included in crash reports, with durable (disk-persisted) breadcrumbs for critical transitions - Process-gone classification: Distinguishes expected teardowns (app quit, renderer reload) from unexpected crashes to avoid false crash reports
src/shared/agent-prompt-injection.ts implements bracketed paste mode injection for submitting prompts to agent terminals. This avoids line-by-line typing which would be slow and trigger agent hooks mid-paste. The system builds paste bytes with appropriate delays (AGENT_PROMPT_SUBMIT_DELAY_MS) and handles oversized inputs through chunked iteration.
The CLI supports multiple output formats (--format json, --format text) designed for both human and agent consumption. The src/cli/format.ts module normalizes output across handlers with structured error reporting.
The core value proposition is running N agents in parallel, each in its own worktree. Everything flows from this: PTY persistence, hook-based status tracking, worktree isolation, SSH multiplexing. The architecture sacrifices simplicity for parallelism support.
Enormous engineering effort went into making things survive: daemon-based PTYs, crash breadcrumbs, renderer recovery, GPU fallback, update handoff, agent session resume across restarts. This is the most distinguishing architectural choice โ most Electron apps lose terminal state on crash; Orca treats that as a design constraint to solve.
At 590K lines with 9,500+ files, this is a complex codebase. The main process entry point is 3,000+ lines. Many subsystems have deep coupling: agent hook server โ runtime โ PTY provider โ daemon โ renderer. The per-agent integration modules are individually complex (Codex alone spans multiple modules for accounts, hooks, sessions, trust, usage tracking).
While there are many unit tests (.test.ts files throughout), the orchestration coordinator's core loop (decompose โ dispatch โ monitor โ converge) appears to have limited integration testing. The coordinator depends on live terminals and git operations that are hard to mock realistically.
The app uses a JSON file store for settings, worktree metadata, and workspace session state. This is simple and debuggable but doesn't scale well for concurrent writes or large datasets. The orchestration system uses SQLite separately โ a split that suggests the JSON store was an early choice that became hard to change.
Using Electron gives cross-platform reach and access to Chromium for browser panes, but at significant resource cost. The React Native mobile app is a pragmatic companion rather than a full-featured client โ it monitors and steers, but doesn't run agents.
Traycer is another open-source AI orchestration desktop app. Both wrap multiple coding agents in a unified interface. Key differences: - Traycer uses Yjs for real-time collaboration; Orca uses a custom relay protocol - Traycer's RPC protocol is versioned for independent client/host releases; Orca's IPC is more tightly coupled - Orca has a mobile companion app; Traycer is desktop-only - Orca supports 20+ agents with per-agent hook integration; Traycer's agent list is smaller (17+)
Broomy is the closest comparison โ another MIT-licensed Electron app for running multiple coding agents side-by-side. Orca is significantly larger in scope: SSH remote worktrees, mobile companion, orchestration engine, computer use, plugin system. Broomy is more focused on the side-by-side editing experience.
cmux is a macOS-native terminal built on libghostty, designed for managing multiple AI coding agent sessions. Both address the "parallel agent" use case. cmux is simpler (native, no Electron) with notification rings for attention; Orca is the full platform with orchestration, SSH, mobile, and more.
Fleet Supervisor (sermakarevich) is a Python supervisor for parallel coding agents with pluggable backends and a web UI. Orca's orchestration is more deeply integrated (worktree management, SSH, PTY persistence) but Fleet Supervisor has the advantage of being backend-agnostic and having a built-in MCP question broker.
Grok Build is a pure Rust terminal-based coding agent โ it IS an agent, not an orchestrator of agents. The comparison point is that both are open-source, terminal-first tools. Orca orchestrates existing agents; Grok Build implements its own agent from scratch. Orca supports Grok as one of its 20+ launchable agents.
src/main/
index.ts (3034 lines) โ App entry, lifecycle, service wiring
persistence.ts โ JSON store singleton
runtime/
orca-runtime.ts โ Central orchestrator singleton
orchestration/
coordinator.ts โ Task decomposition and dispatch loop
db.ts โ SQLite-backed orchestration database
types.ts โ Message/Task/Run types
federation-sync.ts โ Cross-worktree dispatch sync
relay/
desktop-relay-service.ts โ Mobile pairing relay
relay-session-broker.ts โ Auth and routing
runtime-rpc.ts โ WebSocket RPC server
agent-hooks/
server.ts โ Local HTTP hook receiver
managed-agent-hook-controls.ts โ Hook enable/disable
first-work-branch-rename.ts โ Auto-rename on first agent message
pty/
(in providers/) โ local-pty-provider.ts, daemon-init.ts
ssh/
ssh-connection.ts โ SSH2 wrapper with multiplexing
ssh-channel-multiplexer.ts โ Multi-channel over single connection
ssh-relay-session.ts โ Remote agent hook relay
ssh-config-parser.ts โ OpenSSH config parser
ssh-relay-deploy.ts โ Auto-deploy Orca runtime to remote
git/
worktree.ts โ Git worktree operations
runner.ts โ Git binary execution wrapper
browser/
agent-browser-bridge.ts โ Agent โ browser communication
browser-manager.ts โ Browser pane lifecycle
claude/ โ Claude Code integration
codex/ โ Codex CLI integration
plugins/ โ Plugin system
terminal-history.ts โ Scrollback persistence
startup/ โ Process startup, GPU, single-instance lock
crash-reporting/ โ Crash recovery and reporting
src/cli/
dispatch.ts โ CLI command router
handlers/ โ Per-command handler modules
format.ts โ Output formatting (JSON, text)
src/renderer/src/ โ React UI
src/shared/ โ Cross-process types, detection, protocols
src/relay/ โ Relay process
mobile/ โ React Native companion app
main/index.ts at 3,034 lines: The entry point has max-lines disabled with explicit rationale, but the sheer number of imports and service wiring suggests a lack of modular decomposition at the top level.
orca-runtime.ts at hundreds of lines: Also has max-lines disabled โ "still owns the mutable live graph, PTY handles, waiters, mobile floor/layout state, and managed-worktree reconciliation."
agent-hooks/server.ts: Similarly max-lines disabled โ "owns the loopback HTTP adapter, the on-disk last-status persistence layer, and the relay ingest path."
Per-agent code duplication: Each agent integration (claude, codex, grok, cursor, etc.) follows similar patterns (account service, hook service, session resume, trust) with duplication rather than shared abstractions.
Two persistence backends: JSON files for core state, SQLite for orchestration โ suggesting organic growth rather than architectural intent.