Brennan Benson c53ed030b2 fix(terminal): one intentional-stop register, and per-run spawn and input facts (#22989)
* fix(terminal): one intentional-stop register and per-run spawn and input facts

Main now keeps one register of PTY stops it made on purpose, with an owner
count and a kind: reversible (sleep, hibernation) or replaced (a restart
handing the pane to a new process). It replaces four separate markers, and
every exit path reads it, so a hibernated or restarted pane keeps its tab and
binding through the exit instead of being retired and grafted back.

Main also records two facts per process run, keyed by incarnation: whether the
run was a fresh spawn (from the spawn-commit origin, which now counts a cold
restore as a reattach) and when a client first sent it input a person
produced. Renderer keystroke, paste, drop and quick-command writes carry a
userInput flag; terminal.send, stream input and dispatched agent prompts are
recorded by the runtime, excluding terminal query replies.

* test(terminal): a stopped process's synthetic and late provider exits keep its pane

One process can reach the runtime's exit handler twice: main's synthetic exit
when the kill reply overtakes the stream, then the provider's own exit, which
certifies the death. Both must read the same stop, a later process on the
same id must not, and the stop is forgotten when the duplicate-exit window
closes.

* test(terminal): a runtime worktree sleep keeps its tabs and wake bindings

* fix(terminal): keep every overlapping stop kind on one exit

A sleep and a restart that stop the same process now each keep their
label: the exit carries both renderer flags, and a runtime kill during
the sleep still records its SSH stop as reversible. A later stop of an
already-stopped process joins its entry, so a failed repeat cannot erase
the stop that landed.

The cold-restore rule moves into the run facts, so the binding span keeps
labelling a cold restore as a spawn.

* test(terminal): IME and Hangul commits reach the PTY as user input

Drives a real xterm through the pane's input handling: a macOS
input-source substitution, an iPadOS Hangul syllable, and a composition
the route delivers after a pane switch each reach onData flagged as user
input, which is what tags the write main records.

* test(terminal): state why the IME provenance test's canvas stub is safe

* fix(terminal): a new process ends an unpinned stop, and focus reports are not input

- A landed stop that no exit pinned to an incarnation now ends when a new
  process commits on the same id, so that process's exit is not read as
  the stop. Both spawn-commit funnels report through one runtime method.
- A spawn commit with no incarnation starts its run facts clean, since it
  cannot be told from a new process.
- Stream input that is only focus reports no longer counts as user input;
  the desktop renderer already excludes them through xterm's own signal.
- The IME provenance test uses typed fakes: the pane input and composition
  route installers now take only the fields they read.

* chore: restore pnpm-lock.yaml to the base revision

* fix(terminal): typing in the dashboard preview is a run's user input

The dashboard popout's terminal preview writes to the PTY through its own
runtime path, which recorded no input, so a pane typed into only from the
preview read as untyped. It now records before the write, after the
mobile-driver check. One classifier, shared with terminal.send, decides
which provenance-free bytes nobody typed: a whole terminal reply or only
focus reports, which also covers the focus-in a desktop renderer sends
when it reattaches a remote pane.

* test(terminal): the IME provenance test removes the navigator stubs it adds

happy-dom serves navigator.userAgent from the prototype, so the test found no
own descriptor to restore and left the iPad user agent in place. The pane-switch
case then ran as a Mac pane only because it followed the Hangul case. Deleting
the own-property stub restores the default platform for every case.

* fix(terminal): every PTY write names its input kind, and one record point reads it

A run's first input was recorded by opposite defaults: the renderer's
pty:write recorded nothing unless a writer opted in, terminal.send recorded
everything that was not a reply, and main's own controller writes recorded
nothing. Each unclassified producer silently took its transport's default, so
the worktree-create draft counted from the renderer and not from main, and
mailbox pointers never counted.

Every host write entry point now takes a required kind: driving, launch or
query-reply. That covers the runtime controller's write and settled write,
the terminal writer, sendTerminal, sendTerminalAgentPrompt, pty:write and
pty:writeAccepted, the renderer transport and the runtime input helpers. The
fact is recorded once, just before the provider write, in the controller
funnel and the pty:write funnel: only driving bytes count, and a payload that
is only a reply or focus reports never does. The per-producer records are
gone.

Launch writes (create-time drafts and follow-ups, the agent launch prompt,
restored and cold-restore startup commands, the SSH background launch) do not
count. Mailbox pointers, dispatch, plugins and agent-team sends do. The
runtime mixins are unchecked by the compiler, and the pane session is an any
bag, so two source scans fail on any write there that leaves out its kind.

* fix(terminal): type the pane session's transport so the compiler checks every write's kind

The pane-connection session is an `any` bag, so a transport write there that
left out its input kind compiled, and only a text scan over the renderer
caught it. Declaring `transport: PtyTransport` on the session puts those writes
under the compiler, so the scan is gone. One hidden-delivery guard now narrows
a null PTY id itself instead of relying on an untyped predicate.

The main-process scan over `@ts-nocheck` runtime files missed five files whose
directive sits on the second line, below a lint directive, and missed a write
through a local alias of the PTY controller. It now finds both.

* fix(terminal): record a runtime spawn's run facts only after its binding save succeeds

The runtime spawn funnel reported the commit before its host-session binding save, so a spawn discarded for a failed save still recorded run facts and cleared a landed stop. Report it after the save, and separately on the adopted return, which makes no save. Also align tests and fixtures with main: the removed stop-owner map, required write input kinds, SQLite-backed stores and async binding saves.

* test(terminal): pin where the renderer spawn funnel records its commit

The merge moved the renderer funnel's spawn-commit report into the publish step, after the binding save, but no test covered it: deleting the call or moving it back before the save left every suite green. Cover both: a committed spawn records its run facts and supersedes an unpinned landed stop, and a spawn discarded for a failed binding save records nothing and leaves the stop.

* fix(terminal): record a runtime spawn's commit only once its registration succeeds

The runtime funnel reported each commit before registering the process, so a spawn that exited during start still recorded run facts and could end a landed stop, while the renderer funnel reports only after registration. Report after registration on both the ordinary and the adopted branch, so only a committed, registered run has facts and an unknown run keeps reading as not fresh.

* test(terminal): pin that a runtime adoption supersedes a landed stop no exit pinned

* fix(terminal): read an unconfirmed explicit stop's reversibility from the intentional-stop registry
2026-09-27 23:13:24 -07:00
2026-09-26 20:50:46 +00:00
2026-05-04 20:42:03 -07:00
2026-03-16 22:27:51 -07:00
2026-03-28 10:19:14 -07:00

Orca Orca

GitHub stars Total downloads across all releases License: MIT Join the Orca Discord Follow Orca on X Supported platforms: macOS, Windows, and Linux

中文 · 日本語 · 한국어 · Español · Français · Português

The AI Orchestrator for 100x builders.
Run Codex, ClaudeCode, OpenCode or Pi side-by-side — each in its own worktree, tracked in one place.

Download Orca

Orca desktop app running agents in parallel worktrees, with the Orca mobile companion app in the corner

Features

Mobile Companion

Monitor and steer your agents from your phone — get notified when an agent finishes and send follow-ups from anywhere.

iOS App Store · TestFlight · Android APK 0.0.50 · Docs →

Orca desktop with the mobile companion app

Parallel Worktrees

Fan one prompt across five agents, each in its own isolated git worktree — compare the results and merge the winner.

Docs →

Parallel worktree orchestration

Terminal Splits

Ghostty-class terminals with WebGL rendering, infinite splits, and scrollback that survives restarts.

Docs →

Terminal splits

Design Mode

Click any UI element in a real Chromium window to send its HTML, CSS, and a cropped screenshot straight into your agent's prompt.

Docs →

Embedded browser and Design Mode

GitHub & Linear, Native

Browse PRs, issues, and project boards in-app — open a worktree from any task and review without a context switch.

Docs →

GitHub and Linear task workflows in Orca

SSH Worktrees

Run agents on a beefy remote box with full file editing, git, and terminals — auto-reconnect and port forwarding included.

Docs →

Remote worktrees over SSH

Annotate AI Diffs

Drop comments on any diff line and ship them back to the agent — review, edit, and commit without leaving Orca.

Docs →

Annotate AI-generated diffs

Drag Files to Agents

VS Code's editor with autosave everywhere — drag files or images straight into an agent prompt.

Docs →

Drag files and images into an agent prompt

Orca CLI

Agents drive Orca too — script every workflow with orca worktree create, snapshot, click, and fill.

Docs →

Script Orca from the CLI

Also in the box:

  • Quick open — Search across worktrees, files, agents, commands, and repo context without leaving your flow.
  • Account switcher & usage tracking — See Claude and Codex usage and rate-limit resets, and hot-swap accounts without re-logging in.
  • Rich repo previews — Preview Markdown, images, PDFs, and repo docs in the workspace.
  • Computer Use — Let agents operate desktop apps and visible UI when a workflow needs real interaction.
  • Notifications and unread state — Know when an agent finishes or needs attention, then mark threads unread to come back later.
  • And many, many more — we ship daily, so this list is perpetually behind. The changelog is the real feature list.

Supported Agents

Works with any CLI agent — if it runs in a terminal, it runs in Orca.

Claude Code logo Claude Code   Codex logo Codex   Grok logo Grok   Cursor logo Cursor   GitHub Copilot logo GitHub Copilot   Muse logo Muse   DeepSeek Harness logo DeepSeek Harness   ZCode logo ZCode   OpenCode logo OpenCode   MiMo Code logo MiMo Code   Amp logo Amp   OpenClaude logo OpenClaude   Antigravity logo Antigravity   Pi logo Pi   oh-my-pi logo oh-my-pi   Hermes Agent logo Hermes Agent   Devin logo Devin   Goose logo Goose   Auggie logo Auggie   Autohand Code logo Autohand Code   Charm logo Charm   Cline logo Cline   Codebuff logo Codebuff   Command Code logo Command Code   Continue logo Continue   Droid logo Droid   Kilocode logo Kilocode   Kimi logo Kimi   Kiro logo Kiro   Mistral Vibe logo Mistral Vibe   Qwen Code logo Qwen Code   Rovo Dev logo Rovo Dev   + any CLI agent


Install

Desktop — macOS, Windows, Linux

Or via a package manager:

# macOS (Homebrew)
brew install --cask stablyai/orca/orca

# Arch Linux (AUR) — or stably-orca-git to build from source
yay -S stably-orca-bin

Mobile Companion — iOS, Android

Pair with your desktop app to monitor and steer your agents from your phone.


Community & Support

  • Discord: Join the community on Discord.

  • Twitter / X: Follow @orca_build for updates and announcements.

  • WeChat: Scan to join the Orca community WeChat group 10.

    WeChat group 10 QR code for the Orca community
  • Feedback & Ideas: We ship fast. Missing something? Request a new feature.

  • Privacy: See the privacy & telemetry docs for what anonymous usage data Orca collects and how to opt out.

  • Show Support: Star this repo to follow along with our daily ships.


Developing

Want to contribute or run locally? See our CONTRIBUTING.md guide.

The relay that pairs the mobile app with a desktop host is also in this repository under cloud/, with a separate pnpm workspace and setup guide.

Orca contributors

GitHub star history chart for stablyai/orca

Signed Builds

Windows code signing sponored/provided by SignPath.io, certificate by SignPath Foundation.

License

Orca is free and open source under the MIT License.

S
Description
Orca is the ADE for working with a fleet of parallel agents. Run any coding agent with your own subscription. Available on desktop, mobile and remote runtime.
Readme MIT
1.7 GiB
Languages
TypeScript 95.2%
JavaScript 4%
Swift 0.2%
HCL 0.2%
CSS 0.1%