# Technical Orientation

> What Orca is, how its three Electron processes (main, preload, renderer) plus the relay server fit together, key entry points, build targets, and how the rest of this reference is organized.

- Repository: stablyai/orca
- GitHub: https://github.com/stablyai/orca
- Human wiki: https://grok-wiki.com/public/wiki/stablyai-orca-47ffb1f68457
- Complete Markdown: https://grok-wiki.com/public/wiki/stablyai-orca-47ffb1f68457/llms-full.txt

## Source Files

- `README.md`
- `package.json`
- `electron.vite.config.ts`
- `src/main/index.ts`
- `src/preload/index.ts`
- `src/renderer/src/App.tsx`
- `src/shared/types.ts`

---

<details>
<summary>Relevant source files</summary>
The following files were used as context for generating this wiki page:

- [README.md](README.md)
- [package.json](package.json)
- [electron.vite.config.ts](electron.vite.config.ts)
- [vite.web.config.ts](vite.web.config.ts)
- [src/main/index.ts](src/main/index.ts)
- [src/main/daemon/daemon-entry.ts](src/main/daemon/daemon-entry.ts)
- [src/main/ipc/register-core-handlers.ts](src/main/ipc/register-core-handlers.ts)
- [src/main/runtime/orca-runtime.ts](src/main/runtime/orca-runtime.ts)
- [src/preload/index.ts](src/preload/index.ts)
- [src/renderer/src/App.tsx](src/renderer/src/App.tsx)
- [src/relay/relay.ts](src/relay/relay.ts)
- [src/shared/types.ts](src/shared/types.ts)
</details>

# Technical Orientation

This page explains what Orca is, how its runtime processes fit together, where the key entry points live, and how the rest of the codebase is organized. It is the first stop for any contributor who needs a mental map before diving into a specific subsystem.

Orca is a cross-platform Electron IDE (macOS, Windows, Linux) built around a single idea: letting developers run multiple AI CLI agents—Claude Code, Codex, Grok, Gemini, and dozens more—in parallel across isolated git worktrees, with native source-control review, GitHub/GitLab/Linear integration, SSH support, and a mobile companion app, all in one window. It is BYOK/BYOC by design; no Orca account or cloud service is required.

---

## Process Architecture

Orca is composed of five distinct runtime contexts. Three are the standard Electron process types; two are purpose-built for persistent terminals and remote execution.

```text
┌────────────────────────────────────────────────────────────┐
│  Electron main process  (src/main/index.ts)                │
│  - App lifecycle, BrowserWindow creation                   │
│  - Service wiring: Store, OrcaRuntimeService, accounts,    │
│    rate limits, agent hooks, automations, keybindings      │
│  - IPC handler registry (registerCoreHandlers)             │
│  - OrcaRuntimeRpcServer  (WebSocket, port 6768/6769)       │
│  - Forks: daemon child process                             │
│                                                            │
│    ┌──────────────────────────────────────────────────┐    │
│    │ Daemon child process (daemon-entry.ts)           │    │
│    │ node-pty host; Unix socket; keeps sessions alive  │    │
│    └──────────────────────────────────────────────────┘    │
└───────────────────┬────────────────────────────────────────┘
                    │  contextBridge (IPC)
┌───────────────────▼────────────────────────────────────────┐
│  Preload script  (src/preload/index.ts)                    │
│  - Exposes window.api.* to renderer via contextBridge      │
│  - Native file drag-and-drop resolution                    │
│  - Runtime environment subscriptions                       │
└───────────────────┬────────────────────────────────────────┘
                    │  window.api.*
┌───────────────────▼────────────────────────────────────────┐
│  Renderer process (src/renderer/src/App.tsx)               │
│  React 19 + Zustand + xterm.js + Monaco + Tailwind         │
│  Sidebar / Terminal / Editor / Source Control / Browser    │
└────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────┐
│  Relay server  (src/relay/relay.ts)                        │
│  Standalone Node.js; deployed to remote SSH host via SCP   │
│  stdin/stdout JSON-RPC to main process; Unix socket recon. │
└────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────┐
│  CLI binary  (src/cli/index.ts  →  out/cli/index.js)       │
│  WebSocket client to OrcaRuntimeRpcServer on main           │
└────────────────────────────────────────────────────────────┘
```

---

## Main Process (`src/main/index.ts`)

The main process is the app's composition root. Its single `app.whenReady()` block:

1. Reads or initializes the SQLite-backed `Store` (settings, repos, worktrees).
2. Instantiates every service: `OrcaRuntimeService`, `CodexAccountService`, `ClaudeAccountService`, `RateLimitService`, `AutomationService`, `KeybindingService`, crash-reporting, telemetry, stats.
3. Starts the agent hook server and the persistent-terminal daemon (via `startFirstWindowStartupServices`).
4. Creates the single `BrowserWindow` (`createMainWindow`) and registers all IPC handlers with `registerCoreHandlers`.
5. Starts `OrcaRuntimeRpcServer`—a WebSocket server (default port 6768, dev port 6769) that exposes the runtime to the CLI and mobile app.

A `--serve` flag enables a headless mode (`orca serve`) where the window is never created and the runtime is exposed over WebSocket only, making it usable as a background server for the Orca CLI.

Sources: [src/main/index.ts:1-120](), [src/main/index.ts:480-560]()

### Services Wired at Startup

| Service | Source module | Role |
|---|---|---|
| `Store` | `src/main/persistence.ts` | SQLite-backed settings, repos, worktrees |
| `OrcaRuntimeService` | `src/main/runtime/orca-runtime.ts` | Live tab/pane graph, PTY handles, worktree management |
| `OrcaRuntimeRpcServer` | `src/main/runtime/runtime-rpc.ts` | WebSocket RPC for CLI and mobile |
| `CodexAccountService` | `src/main/codex-accounts/service.ts` | Codex auth + managed home |
| `ClaudeAccountService` | `src/main/claude-accounts/service.ts` | Claude auth |
| `RateLimitService` | `src/main/rate-limits/service.ts` | Per-agent rate-limit polling |
| `AutomationService` | `src/main/automations/service.ts` | Automation rule execution |
| `KeybindingService` | `src/main/keybindings/keybinding-service.ts` | File-backed keybinding overrides |
| `AgentHookServer` | `src/main/agent-hooks/server.ts` | Loopback receiver for hook callbacks |
| `CrashReportStore` | `src/main/crash-reporting/crash-report-store.ts` | Process-gone diagnostics |

### IPC Handler Registration

`registerCoreHandlers` (`src/main/ipc/register-core-handlers.ts`) wires every `ipcMain.handle` and `ipcMain.on` call in one place, covering: app identity, repos, worktrees, PTY, filesystem, filesystem watcher, GitHub, GitLab, hosted review, Linear, Azure DevOps, Bitbucket, Gitea, feedback, crash reporting, export, stats, memory, rate limits, runtime, runtime environments, notifications, notebook, onboarding, developer and computer-use permissions, browser, speech, SSH, workspace cleanup/space/ports, settings, keybindings, account management (Codex, Claude, Grok, Gemini, Copilot, Cursor, OpenCode, Droid, Hermes, and more), and telemetry.

Sources: [src/main/ipc/register-core-handlers.ts:1-50]()

### Daemon Child Process

`src/main/daemon/daemon-entry.ts` is compiled as a separate Rollup entry (`daemon-entry` in `electron.vite.config.ts`) and placed outside the ASAR archive (`externalizeDeps`) so `child_process.fork()` can execute it from disk. It hosts `node-pty` for persistent terminal sessions: PTYs stay alive when the renderer reloads, crashes, or the window is temporarily hidden. The main process connects to it over a Unix socket (`--socket`) with a token (`--token`) for authentication.

Sources: [electron.vite.config.ts:46-65](), [src/main/daemon/daemon-entry.ts:1-50]()

---

## Preload Script (`src/preload/index.ts`)

The preload is the security boundary. It runs in a privileged context with access to both Node.js and the DOM, and uses Electron's `contextBridge` to expose a typed `window.api` object to the renderer. The renderer has no direct access to Node.js or Electron internals.

Key responsibilities:
- **`window.api.*`** — hundreds of typed async/sync wrappers around `ipcRenderer.invoke` and `ipcRenderer.send`, organized by domain: `app`, `repos`, `worktrees`, `pty`, `gh`, `gl`, `linear`, `ssh`, `settings`, `keybindings`, `runtime`, `speech`, `automations`, `crashReports`, and more.
- **Native file drop** — `dragover` and `drop` listeners use `webUtils.getPathForFile` (Electron 28+ API, unavailable in the renderer's isolated world) to resolve `File` objects to real filesystem paths, then classify the drop target by walking `composedPath()` for `data-native-file-drop-target` markers.
- **Notification sound** — a cached `HTMLAudioElement` for notification sounds, deduplicated per playing duration to match VS Code's `AccessibilitySignalService` pattern.
- **Runtime environment subscriptions** — imported helper `subscribeRuntimeEnvironmentFromPreload` manages polling/push subscriptions for runtime environment state.

Sources: [src/preload/index.ts:1-70](), [src/preload/index.ts:145-230]()

---

## Renderer Process (`src/renderer/src/App.tsx`)

The renderer is a React 19 single-page application bundled by Vite with Tailwind CSS v4. All state is managed via Zustand (`useAppStore`). The root `App` component:

- Drives the three-column layout: left sidebar (worktrees/repos), main content area (terminal panes, editor, browser), right sidebar (source control, file search, PR checks, explorer).
- Handles startup hydration: fetches settings → repos → worktrees → persisted UI → session → keybindings → SSH reconnect → terminal reconnect, with carefully ordered async steps and a recovery path that avoids writing corrupted state to disk on failure.
- Subscribes to IPC push events via `useIpcEvents()` (agent status, PTY data, settings changes, SSH state, GitHub PR refresh, etc.).
- Manages the global keyboard shortcut dispatcher: `keybindingMatchesAction` resolves shortcut actions against the user's `KeybindingOverrides`.
- Lazy-loads heavy page components: `Landing`, `TaskPage`, `AutomationsPage`, `Settings`, `SkillsPage`, `OnboardingFlow`, `QuickOpen`, `WorktreeJumpPalette`, and others.

The renderer also includes a **web build variant** (`vite.web.config.ts`) that compiles the same React application for browser hosting—used when the relay server or `orca serve` exposes a web client for mobile pairing. Output goes to `out/web/`.

Sources: [src/renderer/src/App.tsx:1-100](), [src/renderer/src/App.tsx:350-500](), [vite.web.config.ts:1-32]()

---

## Relay Server (`src/relay/relay.ts`)

The relay is a **standalone Node.js script** (not Electron) deployed to remote SSH hosts. Its lifecycle:

1. The Electron main process SCPs the compiled relay bundle to the remote host and launches it over an SSH `exec` channel.
2. Relay reads/writes framed JSON-RPC over `stdin`/`stdout`.
3. On client disconnect it opens a Unix domain socket (`relay.sock`) and enters a configurable grace period (default: `DEFAULT_SSH_RELAY_GRACE_PERIOD_SECONDS`), keeping all PTYs alive.
4. A subsequent connection passes `--connect`, which bridges the new SSH channel to the existing socket.

The relay registers handlers for: PTY (`PtyHandler`), filesystem (`FsHandler`), git (`GitHandler`), preflight (`PreflightHandler`), external automations (`ExternalAutomationsHandler`), port scanning (`PortScanHandler`), agent exec (`AgentExecHandler`), and workspace session (`WorkspaceSessionHandler`). It also runs a `RelayAgentHookServer` so remote agent hook callbacks route back to the Orca desktop.

Sources: [src/relay/relay.ts:1-80]()

---

## CLI (`src/cli/`)

The `orca` CLI binary (`out/cli/index.js`, also registered as `bin.orca` in `package.json`) is a pure TypeScript/Node.js program compiled separately from the Electron build. It connects to the running Orca desktop app's `OrcaRuntimeRpcServer` WebSocket to control worktrees, terminals, and agents programmatically. Key modules:

| File | Role |
|---|---|
| `src/cli/index.ts` | Entry point, command dispatch |
| `src/cli/args.ts` | Argument parsing |
| `src/cli/runtime-client.ts` | WebSocket client for RPC |
| `src/cli/handlers/` | Per-command implementations |

Sources: [package.json:6-8]()

---

## Build System

Orca uses **electron-vite** (`electron.vite.config.ts`) as the primary bundler for the three Electron contexts, plus a standalone Vite config for the web renderer. Rollup inputs are declared explicitly.

### Build Targets

| npm script | Output | Description |
|---|---|---|
| `build:electron-vite` | `out/main/`, `out/preload/`, `out/renderer/` | All three Electron process bundles |
| `build:relay` | `out/relay/` | Relay server (plain Node.js) |
| `build:cli` | `out/cli/` | CLI binary |
| `build:web` | `out/web/` | Web renderer for mobile/browser pairing |
| `build` | all of the above | Full production build (runs typecheck first) |
| `build:release` | all of the above | Release build (skips typecheck, runs native verification) |

### Main-Process Rollup Entries

The main process defines five separate entry points in `electron.vite.config.ts`:

| Entry key | Source | Purpose |
|---|---|---|
| `index` | `src/main/index.ts` | Main app entry |
| `daemon-entry` | `src/main/daemon/daemon-entry.ts` | Persistent PTY host (ASAR-unpacked) |
| `computer-sidecar` | `src/main/computer/sidecar-entry.ts` | Computer-use sidecar |
| `stt-worker` | `src/main/speech/stt-worker.ts` | Speech-to-text worker |
| `agent-hooks/managed-agent-hook-controls` | `src/main/agent-hooks/managed-agent-hook-controls.ts` | Hook control module for CLI |

Sources: [electron.vite.config.ts:43-70]()

### Compile-Time Telemetry Gate

`electron.vite.config.ts` substitutes three build constants at compile time (`ORCA_BUILD_IDENTITY`, `ORCA_POSTHOG_WRITE_KEY`, `ORCA_DIAGNOSTICS_TOKEN_URL`). CI injects real values via GitHub Actions secrets; every other build resolves them to `null`, making `IS_OFFICIAL_BUILD` false and short-circuiting all telemetry transport. There is no runtime environment variable fallback.

Sources: [electron.vite.config.ts:14-40]()

---

## Key Source Directories

```
src/
├── cli/           CLI binary (standalone Node.js, WebSocket RPC client)
├── main/          Electron main process
│   ├── agent-hooks/   Hook install/server for agent status callbacks
│   ├── daemon/        Persistent PTY daemon (forked child process)
│   ├── ipc/           All ipcMain handler registrations by domain
│   ├── runtime/       OrcaRuntimeService: live tab/pane/PTY graph
│   ├── startup/       Process configuration, path hydration, single-instance lock
│   ├── telemetry/     PostHog transport, consent, cohort classifier
│   ├── window/        BrowserWindow creation and attachment helpers
│   └── ...            Per-integration dirs: github/, gitlab/, linear/, ssh/, claude/, codex/, ...
├── preload/       Electron preload (contextBridge → window.api.*)
├── relay/         Remote SSH relay server (standalone Node.js)
├── renderer/      React UI
│   └── src/
│       ├── App.tsx        Root component, startup hydration, global shortcuts
│       ├── store/         Zustand store slices
│       ├── components/    All UI components (Sidebar, Terminal, RightSidebar, …)
│       ├── hooks/         React hooks (IPC subscriptions, shortcuts, scroll, …)
│       ├── lib/           Pure utilities (theme, keyboard, telemetry, session, …)
│       ├── runtime/       Runtime graph sync (mobile/web session publishing)
│       └── assets/        CSS design tokens, fonts
├── shared/        Types and pure logic shared across all contexts
│   ├── types.ts           Core domain types (Repo, Worktree, GlobalSettings, …)
│   ├── agent-detection.ts Agent status inference from OSC terminal titles
│   ├── keybindings.ts     KeybindingActionId, override types, matcher
│   └── ...                ssh-types, runtime-types, automations-types, …
└── types/         Ambient .d.ts shims (env.d.ts, vite/client, build-constants)
```

### `src/shared/` — The Cross-Context Contract

`src/shared/` is imported by main, preload, renderer, CLI, and relay alike. It must never import from Electron or Node-only modules. `src/shared/types.ts` defines the canonical domain types (`Repo`, `Worktree`, `GlobalSettings`, `TabGroupLayoutNode`, etc.). Per the project convention, all project-owned types live in `.ts` files, not `.d.ts`, so `skipLibCheck` does not silently swallow type errors.

Sources: [src/shared/types.ts:1-80]()

---

## Data Flow: IPC from Renderer to Main

```mermaid
sequenceDiagram
    participant R as Renderer (React)
    participant P as Preload (contextBridge)
    participant M as Main Process
    participant S as Service / Native

    R->>P: window.api.pty.spawn(opts)
    P->>M: ipcRenderer.invoke('pty:spawn', opts)
    M->>S: LocalPtyProvider or DaemonPtyProvider
    S-->>M: { id, snapshot, ... }
    M-->>P: resolve
    P-->>R: Promise<{ id, ... }>
    M->>P: ipcRenderer.send / webContents.send('pty:data', {id, data})
    P->>R: onData callback (window.api.pty.onData)
```

Push events travel in the reverse direction: the main process calls `mainWindow.webContents.send(channel, payload)`, and the preload registers `ipcRenderer.on(channel, listener)` listeners that fan out to renderer callbacks registered via `window.api.<domain>.on*` subscriptions.

---

## Runtime Topology at a Glance

`OrcaRuntimeService` (`src/main/runtime/orca-runtime.ts`) is the central state machine for the live session. It owns:
- The window tab/pane graph (`syncWindowGraph`) used to publish the layout to mobile and the CLI.
- All active PTY handles, keyed by pane key.
- Worktree creation, removal, and lineage.
- Commit-message agent orchestration.
- Account service integration for launch-time auth preparation (Claude, Codex).

The `OrcaRuntimeRpcServer` wraps the service and exposes it over WebSocket using the `RuntimeRpcEnvelope` framing defined in `src/shared/runtime-rpc-envelope.ts`. The CLI and the mobile app both use this channel.

Sources: [src/main/runtime/orca-runtime.ts:1-55]()

---

## Wiki Structure

The remaining pages in this wiki cover individual subsystems in depth. The natural reading order after this orientation is:

- **Terminal & PTY** — `node-pty`, daemon persistence, relay PTY, xterm.js renderer integration
- **Worktrees & Repos** — git worktree lifecycle, sparse checkout, lineage tracking
- **Agent Hooks** — hook installation, loopback server, relay agent-hook server, status inference
- **SSH & Relay** — relay deployment, reconnect protocol, port forwarding
- **Source Control** — git staging, diff annotation, PR/MR review workflows
- **GitHub / GitLab / Linear Integration** — IPC handler design, caching, mutation broadcasts
- **Runtime RPC & CLI** — WebSocket envelope, CLI command dispatch, `orca serve` mode
- **Settings & Persistence** — SQLite Store, session JSON, UI state
- **Telemetry & Observability** — consent, PostHog gate, OpenTelemetry tracing lane, crash reporting
- **Design System** — CSS tokens, shadcn primitives, Tailwind v4 usage

Every subsystem corresponds to a directory under `src/main/`, `src/relay/`, or `src/renderer/src/components/` with the same domain name.
