Neil a907dd2ba2 fix(pty): key buffered pre-attach PTY exits on the incarnation, not a sequence fence (#17010)
* fix(pty): key buffered pre-attach exits on the PTY incarnation, not a clock

A restarted SSH relay renumbers PTYs from pty-1, so a fresh spawn is routinely
handed an id whose previous shell is still emitting a late exit. #16970 stopped
that exit blanking the new tab by dating every buffered record and dropping
anything older than the spawn request. That fence is a clock, so it cannot judge
a stale exit that arrives AFTER the request left — the residual risk #16970
documented.

Thread the incarnation main already puts on the pty:exit payload (and the
pty:spawn reply) through preload to the pre-handler buffer, so a buffered exit
names which lifetime of the id died. An exit disagreeing with the incarnation
now attaching is discarded whenever it arrived.

Only a positive disagreement discards: absence stays "unknown", never a
mismatch, so hosts that predate the field keep #16970's behaviour exactly. The
fence is retained for the two cases with no incarnation to compare — buffered
bytes (pty:data carries none) and unnamed exits.

No wire change: incarnationId was already published on the relay's pty.exit
notification and pty.spawn reply, and already forwarded over the in-process
pty:exit / pty:spawn IPC. Only the preload types and the renderer read it now.

* fix(pty): read the incarnation through the shared guard, not truthiness

A malformed incarnation is evidence of nothing, so it must read as "unknown"
rather than as a value that disagrees with every well-formed one — otherwise a
non-string on the payload would discard the very exits the buffer exists to
deliver. Route both the record and the comparison through the existing
isPtyIncarnationId guard.

* refactor(pty): name the bounded-map helper after what it does

It evicts the oldest entry when the map is full and the id is new; it reserves
nothing. Rename only — no behaviour change.

* fix(pty): key the buffered-exit STORAGE on the incarnation too, not just the check

Review caught a swallowed exit. Keying only the comparison on the incarnation
while the storage stayed one slot per pty id left the two races this buffer
exists for able to cancel each other out:

  1. the freshly spawned shell dies before the pane attaches -> its exit (X) is
     buffered;
  2. the relay flushes the previous owner's exit for the same recycled id (W),
     which OVERWRITES X in the single slot;
  3. the spawn reply names X, so the identity discard drops W -- the only
     record left.

registerExit then finds nothing and the pane binds to a PTY that is dead and
will never be reported dead: a hang instead of the blank tab #16970 fixed.

Store one record per lifetime, capped at 4 per id, so W can never evict X. A
duplicate exit for a lifetime replaces that lifetime's record rather than
crowding out another's; drain still delivers the newest survivor, preserving
the last-write-wins behaviour a single slot always had.

* fix(pty): filter buffered exits by lifetime inside the buffer, not at call sites

Review found the identity was enforced only where connectIpcPty calls the
discard, while preHandlerPtyExit has several other consumers. The severe one is
registerEagerPtyBuffer: both background launchers spawn directly and then drain
whatever is buffered for the returned id, so a relay-recycled id holding the
previous owner's exit tore a freshly launched agent session down seconds after
it started -- no fence, no admitPtyId, no identity check at all.

Move the rule into the buffer: every read goes through
admissiblePreHandlerPtyExits, so a record proven to belong to another lifetime
is unreachable by construction rather than because each caller remembered to
discard first. hasPreHandlerPtyExit/drainPreHandlerPtyExit take the asking
lifetime; registerEagerPtyBuffer and registerExit thread it through, and both
background launchers pass the incarnation their own spawn returned.

A reader that cannot name an incarnation still sees everything, which is the
honest answer -- it holds no evidence to discriminate with. That keeps the
pre-spawn fast path in connectIpcPty behaving exactly as it does today; see the
PR for the consumers this still does not cover.

* chore: drop unrelated formatter churn in reliability-gates.jsonc

Repo-wide oxfmt reindented pre-existing entries in a file this change never
touches. Keep the diff to the PTY incarnation work.
2026-08-28 04:17:36 -07:00
2026-08-28 00:59:21 -07:00
2026-07-11 20:53:20 -07:00
2026-08-28 00:59:21 -07: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
2026-08-28 00:59:21 -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.46 · 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   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 7. If it is full, use group 8.

    WeChat group 7 QR code for the Orca community   WeChat group 8 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.

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.5 GiB
Languages
TypeScript 95.1%
JavaScript 4.1%
Swift 0.2%
CSS 0.2%
HCL 0.1%