* feat(orchestration): deliver worker results to a structured chat coordinator
Resolve a Run's handle-less session coordinator and a session:<id> mailbox to
the live session, wake an evicted session for the delivery, redrive a session's
own mail on its idle edge, route a terminal view's pointer through its PTY, and
accept session:<id> (or a bare Orca session id) as a recipient.
* test(orchestration): pin coordinator delivery through the real session host, wake, idempotence and session addresses
* test(orchestration): type the coordinator mail fixture's attach params
* fix(orchestration): refuse session recipients with the caller codes, and treat a worker without its identity as undeliverable
* test(orchestration): pin a chat's terminal view reading the chat's coordinator mail
* test(orchestration): read coordinator mail fixtures through checked guards instead of assertions
* fix(orchestration): name a structured session's CLI by $ORCA_CLI_COMMAND in its pointer turn
* fix(orchestration): render the pointer's CLI invocation for the shell the session runs in
* fix(orchestration): address a session recipient where its check reads, so a structured worker gets its mail
* test(orchestration): pin the runtime's own idle-edge redrive wiring; say a released session is not running, not ended
* fix(orchestration): point mail that has not been pointed, not mail nobody has acked, naming the ack a held batch needs
* feat(orchestration): hand a /clear-replaced chat's Runs and unread mail to the session that replaced it
* feat(orchestration): adopt a /clear predecessor's Runs at the clear's commit, the edge its replacement's own status misses
* fix(orchestration): log a wake that could not resume a session, instead of retaining silently
* test(orchestration): give coordinator mail waits a budget that holds under a loaded parallel run
* refactor(orchestration): narrow a retained pointer's dispatch state by type guard instead of a cast
* fix(orchestration): give back a pointer whose admitted turn never ran
A pending send stamped its rows delivered and dropped its operation row, so a
provider that died before echoing left the last result pointed at nobody. The
lane now awaits the admitted turn's settlement: accepted consumes the claim,
anything else returns the rows and drops this send's operation row, so the
re-point on the next edge is a new send rather than a replay of unknown.
* fix(native-chat): keep a committed /clear from failing on its replacement observer
The observer runs after the clear's durable commit; a throwing adoption turned a
committed clear into a failed RPC. It is now best-effort and logged, like the
status feed's observer, and the successor's idle edges re-derive the adoption.
* test(orchestration): pin /clear adoption across a chain of clears and a predecessor's check
A session cleared twice before any edge hands both predecessors' Runs and mail
to the end of the chain. A predecessor still live in the clear's tail reads
none of the re-addressed mail: a session's direct mailbox is consume-on-read
and holds no replayable batch.
* test(orchestration): type the pending-settlement host test's send input without an assertion
* fix(orchestration): keep a chat's orchestration address across /clear by deriving its lineage
A chat's orchestration address is now the first session of its /clear lineage. Every session of the
lineage resolves to that one actor when it acts and when it is reached, and delivery goes to the
lineage's live session. Nothing is rewritten at a clear, so the predecessor-adoption path is gone:
the commit-edge observer, the idle-edge rebind, and the unread-mail re-address. That path could
unbind the successor's own Run and orphan all but one Run of a chain.
The idle edge now opens the orchestration database through its lazy getter and logs when it cannot,
instead of reading a field that stays null until the first orchestration call after a restart.
* fix(orchestration): give back a structured pointer claim an earlier process left open
A pointer the host admits as pending stamps its batch delivered, and only an in-memory settlement
waiter gives it back if no turn ran. A process that died in that window left the batch stamped with
nothing to release it, so the last result on that mailbox was never pointed again. When the
database opens, every surviving pointer operation row is from an earlier process: its stamped batch
is found by the row's fingerprint, released, and the row dropped, before the restored-mailbox scan
points it again. A row whose batch was never stamped keeps its id for the retry.
* test(orchestration): pin that a cleared chat's sends carry its conversation's address
* fix(orchestration): open the orchestration database at an idle edge only when it already exists
A profile with no orchestration database has no mail to redrive, so a structured chat's idle edge no
longer creates one, and says nothing. An existing database is still opened lazily there.
* fix(orchestration): read a chat-coordinated Run's session through the actor's generation
A handle-less Run names its coordinator session only by an actor that still counts at the Run's
current generation, the same rule every other binding read uses; an actor an older binary's rebind
or unbind left behind no longer routes the Run's mail. A test pins that a cleared chat's run-create
and run-use write its conversation's root actor at the Run's current generation.
* refactor(orchestration): address a session's conversation by its bare root Orca session id
Carries the Orca session id rename into coordinator delivery. A session's orchestration
identity holds its conversation's bare Orca session id, the /clear lineage root's, and
its mail address is derived from it by formatOrcaSessionAddress; a Run a cleared chat
creates or uses stores that bare root id. A session recipient carries the parsed id and
its address as distinct types, a handle-less coordinator's session is read through
currentRunCoordinatorOrcaSessionId, and session ids read from records or PTY bindings
are checked with isOrcaSessionId before they become an identity. The session address
prefix comes from the one exported constant.
* refactor(orchestration): canonicalize a cleared session through the one id hook and the party resolver
- canonicalOrcaSessionId now walks a session's /clear lineage to its root; the
parallel session identity and lost-worker rule are deleted, so the caller
resolver, recipient routing, reach and idle-edge mailboxes all resolve a
session through resolveOrcaSessionParty.
- A Dispatch row's assignee_orca_session_id goes through the same hook.
- The terminal-view delivery lane is gone with the terminal handoff: no PTY is
bound to a session, so a chat's mail is always a session turn.
- Pins a send to a Run-less chat's session address after a restart, when the
send must start the agent-session host before routing reads its record.
* fix(orchestration): point a structured session with the PTY lane's exact text
A chat or structured worker is now told what a terminal agent is told: the pointer is
formatMessagePointer with the CLI name the PTY lane resolves for a local terminal (orca, or
orca-dev in a dev build), with no shell-specific invocation and no ack lesson. The lane still
excludes the batch a reader holds unacknowledged and points newer mail; that stays host-side,
and the reader's own check replays the held batch and names its ack as it does for a terminal.
* fix(orchestration): deliver a cleared structured worker's mail to its live successor
A terminal keeps its handle across /clear; a structured worker's successor now does the same.
Mail at the worker's handle, its dispatch mailbox, and a Run it coordinates resolved to the
session minted for the worker, which /clear replaced. Each now walks the /clear lineage forward
to the live session, which the caller resolver already treats as the worker.
* test(orchestration): compare a chat's pointer turn to the PTY lane's text for this build's CLI name
* refactor(orchestration): resolve the local CLI name once, for the PTY lane and the structured lane alike
* fix(orchestration): let a /clear-ed chat restate its address, placed by the host's lineage
The CLI entry compared a restated --from/--terminal with the injected session id as a
plain string, so a cleared chat restating the address it had before the clear (its lineage
root, the address it keeps) was refused. Only the host's session records know the lineage,
so a session address that is not this session's own spelling is now sent as the caller
param, where the host's canonical-id check accepts it or refuses it before any effect.
Plain restatements are still dropped and any other name is still refused at the entry.
* test(orchestration): read the coordinator journal through the async snapshot, and wait for the held turn's handover
Main made journalSnapshot async and delivers an accepted send once the host hands it over, so the fixture awaits the snapshot and waits for the provider's turn before echoing it.
* refactor(orchestration): point a chat whose agent is not running through the plain send
Main's host no longer has hold/release: an accepted send starts the agent itself. The
pointer lane's wake step called host.hold, which no longer exists, so it is deleted
from the pointer host, the delivery lane and their tests. An idle or evicted chat gets
its pointer through the same send a user message takes; the claim is still consumed
only on accepted and given back otherwise.
* fix(orchestration): leave a chat whose provider died stopped instead of respawning it for mail
A pointer whose provider died before echoing it is given back. The death's own status
edge then redrove the mail, and since a send starts the agent, a provider that died on
every turn was restarted about once a second for as long as the mail was unread. The
pointer lane now reads, on every attempt, whether the session's latest send never ran
because its provider exited or could not start, and holds the mail until a later send
runs. Every trigger passes through that gate: a parked retry, the idle edge's re-derive
and new mail. A rejection for any other reason still points at the next idle edge.
* fix(orchestration): hold mail after a start the person must fix, placing every failure kind
A start refused for a reason only the person can fix (not signed in, history too large,
a managed-account problem) or one the host stopped because it never came is held like a
failed start: the mail waits for the person's next message, which also retries the start.
An account switch still in progress is transient, so it stays ungated and the first edge
after the switch settles points the mail. One exhaustive record places every rejection
kind, so a new kind does not compile until it is placed.
* fix(orchestration): retry a structured pointer under its own id instead of gating on the failure reason
A pointer send that failed was given back and re-sent under a fresh operation id,
so every status edge after a provider death was a new send that started the provider
again. A reason-string gate held some of those deaths, but missed a Codex crash with
turn/start in flight (it settles unknown with the connection's error), latched all later
mail after one transient death, and did not keep a user's Stop.
A retry now reuses the mailbox's operation id, which the host answers by replaying the
recorded verdict without reaching the provider. The id is re-minted only for new mail,
after a later send ran, for a row an earlier process left, or once an account switch
settles. Rows are stamped only on accepted, so the admitted-stage claim, its give-back
and the restart claim-release scan are gone.
* test(orchestration): pin that a Stop keeps a pointer unsent before the next status edge, too
* fix(orchestration): point a structured chat's mail by the same rule as a terminal's
The chat lane pointed newer mail past a batch its reader had checked and not
acknowledged, while the terminal lane skips a mailbox until that batch is acked. A chat
now waits for the ack the same way a terminal does, and the lookup that let the chat lane
filter the held batch out is removed.
* fix(orchestration): refuse a session address that gate-list or task-list --run would drop
The CLI entry lets a `session:` address that is not the session's own spelling through
for the host to place, but gate-list and task-list send no caller when --run names the
Run, so `--from session:<other>` was silently ignored. With --run they now refuse it
(consumer_fenced) before any request, the same as a conflicting terminal handle.
* fix(orchestration): keep a failed mail redrive from skipping a chat's first-turn workspace rename
A structured session's status callback redrives its mail before the first-turn workspace
auto-rename, outside any try, so a database error there threw past the rename. The redrive
now logs its failure and returns.
* chore: take main's pnpm-lock.yaml the merge of origin/main left stale
* fix(orchestration): give a stamp or park decision its own variant so the send branch narrows
* fix(orchestration): re-mint a held structured pointer from facts that cannot strand it
A pointer row whose id had no submission in the journal was always resent under that id,
before any re-mint test ran. After a rewind rebuilt the journal, or a send refused before it
was recorded aged past the host's 24h admission window, the mail was held forever: neither
the person's next turn nor a restart pointed it again.
The re-mint tests now run first. "The agent has run since" is any accepted send submitted
after the row was minted; "an earlier process minted it" is a row whose id this lane did not
send, not a wall-clock comparison a clock step could fool; and a row the host never recorded
is re-minted once it is too old for the host to admit. The account-switch exception is gone:
nothing tells the lane when a switch ends, and each outside edge during one added another
pointer and failure to the chat. A parked pointer now retains as turn-unsettled.
* fix(orchestration): let the host check a session caller that gate-list or task-list --run names
5f753af0a7 refused any `--from session:<x>` beside --run that was not the session's own
spelling, which also refused a /clear-ed chat restating its lineage root, an address the host
accepts everywhere else. The CLI now sends that address with --run, and the host's declared
caller check accepts the root and refuses anyone else (consumer_fenced) before any effect.
* fix(orchestration): date a pointer on the journal's clock so a backward clock step cannot re-mint it every edge
Orca
中文 · 日本語 · 한국어 · 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
Features
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
Codex
Grok
Cursor
GitHub Copilot
Muse
DeepSeek Harness
ZCode
OpenCode
MiMo Code
Amp
OpenClaude
Antigravity
Pi
oh-my-pi
Hermes Agent
Devin
Goose
Auggie
Autohand Code
Charm
Cline
CodeBuddy
Codebuff
Freebuff
Command Code
Continue
Droid
Kilocode
Kimi
Kiro
Mistral Vibe
Qwen Code
Rovo Dev
+ any CLI agent
Install
Desktop — macOS, Windows, Linux
- Download from onOrca.dev
- Or grab a build directly: macOS Apple Silicon · macOS Intel · Windows (.exe) · Linux AppImage · All builds
- Running
orca serveon a headless Linux server? See the headless Linux server guide.
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.
- iOS: Download on the App Store
- Android: Download APK 0.0.50 · Install guide
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.
-
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.
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.










