* feat(orchestration): agent mail to a busy chat waits in the chat's own queue
A mail notice for a busy structured chat used to wait in the orchestration lane's
own invisible "until the chat is free" gate. It now goes through the queue a
person's message uses: sendAgentTurn(..., { delivery: 'queue', source }) makes
the host hold it as a draft card the person sees and can Steer or delete, and
the queue sends it when the turn ends.
- The lane's busy gate (turnRunning / awaitingHuman) is gone; the queue's own
hold decides. Its parking now only waits for its own send or card to settle.
- A queued card's hand-off (sent under a fresh id) is matched by
queuedMessageId, so it stamps the mail once and never sends a second notice.
- A card from before an Orca restart is still the lane's: no second card.
- A card the person deleted counts as handled for that batch; newer mail
notifies again. No stored flag: read off the card and delivered_at.
- `orchestration check` waits for the lane to withdraw a card whose mail it
read, so a stale notice is never sent; more mail replaces the card.
- Each card records who queued it in queued_messages.source_json (versioned,
schema-validated): the person, or Orca for agents, with every distinct
sender as an orchestration party plus host id, and the mailbox, dispatch,
run and message ids. The restart pause holds only the person's cards.
- sendAgentTurn answers with a snapshot, not the journal's live submission.
* test(orchestration): type the mail fixture as a pointer batch message
* fix(orchestration): the queue judges an agent's mail notice as it sends it
A mail notice queued in a busy chat could go out stale or twice: it was
kept true from outside the queue, by orchestration check withdrawing it,
which missed other readers, raced an attempt in flight, lost the card
when /clear carried it (a second notice), and moved it to the back when
new mail replaced it. An agent's card behind a person's paused card never
sent after a restart, so an unattended coordinator stalled.
- The drain asks the card's sender, in its own serialized step, whether
it still stands: send, restate (count and senders of the mail owed
now, written onto the card in the hand-off's transaction), or withdraw
as the host. A failing judge sends as written. Send-now restates but
never withdraws. Orchestration registers the judge on the host.
- check no longer touches any queue (back to main); onMailRead,
notifyOrchestrationMailRead and the lane's withdrawals are gone.
- One unsettled card per agent message, enforced at insert; new mail is
counted when the card sends, never replaces or moves it.
- The lane finds its card by what it is (a notice for the mailbox in the
session the mailbox reaches now); a decline is a withdrawal a person's
operation stamped. /clear moves agent cards as the host. Pointer rows
last only while a direct send is in flight and end with the session.
- Pauses (restart, Stop, /clear) hold only a person's cards, and a held
card never traps an agent's card behind it, keyed on the message kind.
- The source is named for the message (agent-session-message-source),
one payload shape per message kind, no relative host id.
* fix(orchestration): Orca's mail notice waits in the queue out of sight
The notice card read as something the person typed and came and went on
its own, the transient-state message the queue should not show. It is
hidden until B can label who sent it.
- The host leaves mail-notice cards out of the published queue, so the
list, its count, Steer/Delete/Edit, steer-newest and the paused header
never see them, on every client. Keyed on the message kind: D6's task
card will be shown, labelled, in B. They still count toward the queue
limit (temporary, until B).
- A refusal no longer returns a hidden card for the person to act on:
the host withdraws it, and the lane points again only after a turn ran
since, the rule it already had for a refused notice.
- Send-now no longer restates a card: no one can reach a hidden one.
- The stored sender drops the pane key, a mailbox credential.
- The gate covers an abandoned worker: a mailbox that reaches no session
withdraws its notice (tested).
* fix(orchestration): a hidden mail notice never waits on the person
Hiding the notice left three paths where it waited on someone who
cannot see it.
- A failed hand-off write put a send_failed hold on it, which only a
person's Send or Delete clears: that mailbox's notices stopped for
good. The host now withdraws a hidden card instead and hands its
mailbox back to the lane through the ordinary redrive, since an idle
chat gets no other edge. A write that keeps failing is retried once
per edge.
- A person's Stop while the agent started on the notice put it back to
waiting, where no pause holds it, so it was sent again at once. The
host now withdraws it; the lane points again after a turn ran or when
newer mail makes it a different notice, as on main. A restart still
puts it back.
- A notice queued before the person's message went first. One order
rule now: the person's cards go in order and never past one waiting
on them; a card they cannot see never delays one they can, and goes
only when none of theirs may.
The drain moves to its own module (structured-agent-session-queued-
drain.ts). Comments that still described the notice as visible are
corrected.
* fix(orchestration): an accepted notice hand-off stamps its mail; a judge that cannot look decides nothing
- When the agent opened its mail in the notice's own turn (the normal
flow), an open batch left nothing owed, so the lane never marked the
mail the accepted hand-off carried as delivered, unlike an accepted
direct send. The lane now stamps exactly the ids a handed-off notice
carried whenever undelivered mail remains, owed or not. A later
conversation is no longer told again about mail already opened.
- At quit the host registry is cleared before teardown, so the drain's
judge could not resolve the mailbox and withdrew the notice. A judge
that cannot read its inputs now defers: the card waits for a step
that can look. A mailbox that resolves to another session or none is
still withdrawn.
- The judge, the owed-batch selection and the notice body move to
structured-mail-notice.ts. A failing hand-back of a dropped card is
logged.
* refactor(orchestration): a chat receives the agent's mail itself, queued like a person's message
A structured chat used to get a derived "You have N orchestration messages,
run check" notice, which could go stale while it waited in the chat's queue,
so the queue judged, restated or withdrew it as it sent. It now gets the mail
itself as the turn, through sendAgentTurn with delivery 'queue', the path a
person's message takes.
- One turn per mailbox batch: the mailbox's unread mail at delivery, in mail
order, each message led by "[message from <sender>]", its type, subject,
body, payload and reply hint (what check prints). Mail arriving while that
card is still in the queue waits for the next card; a card is never edited.
- An idle chat takes it at once; a busy one queues it as an ordinary card the
person sees and can Steer or delete. Mail is marked read when the chat
accepts the turn, so check does not return it again; a deleted card leaves
its mail unread for check, and it is not pushed again.
- The card stores who it is from (source_json): every distinct sender, and
each message's id, run and sender. Kind 'mail-notice' becomes 'mail'.
- Removed: the send-time judge (QueuedAgentCardVerdict), structured-mail-
notice, structured-pointer-notice-cards, queued-message-restatement, the
hidden-card rules, the agent-card exemptions from the restart, Stop and
/clear pauses, the dropped-card hand-back, and the drain split. An agent's
card now follows the same pauses as a person's.
- Terminal agents are unchanged: they keep the typed pointer and check.
* fix(orchestration): a chat's check skips mail already queued to it; restarts hold only the person's cards
- When a structured chat runs `orchestration check` (consuming, --peek or
--wait), mail an agent's card in that chat's own queue still carries
(any card not deleted) is left out: it is on its way as a turn, so the
agent does not read it twice. Derived from the queued rows at read time;
a deleted card no longer carries it, so it comes back. Terminal callers
and every other read are unchanged. New batches pass the exclusion to
getOrCreateMailboxDelivery; peeks filter it.
- A restart's queue pause now holds only the person's cards: an unattended
coordinator's agent card sends after an app restart without waiting for a
Resume, since the mailbox is the record and reading is marked. Stop and
/clear still hold agent cards. One rule, in queuePauseHolding. An agent
card queued behind the person's held card still waits behind it: the
queue never reorders.
- The duplicated direct-mailbox snapshot routing in check-run and
check-worker becomes one helper, which keeps check-worker under its line
limit.
* fix(orchestration): the mailbox is the only record of read mail; a chat's check takes its waiting cards
A card held an exclusive claim on its mail that nothing reconciled with the
mailbox: queueing it stamped the mail delivered, and a chat's check hid every
card that was not deleted. So a chat's own check --wait in one turn could not
see a result its waiting card held, a hand-off that ended in doubt or came back
"Not sent" stranded its mail, a check racing the card's build read the mail
twice, and a card left behind by run-use still sent and marked it read.
What a card or send holds is now derived each time from the chat's queue and
its sends: an accepted send marks its mail read; a waiting card or an
unanswered send holds its mail; everything else unread is pushed again or
returned by check. A card the person deleted is recorded as not to be pushed,
at the delete. The lane withdraws returned, partly read and moved cards. A
chat's consuming check withdraws the waiting cards holding what it reads, one
at a time with the lane. The sender is stored on the sent submission too
(host-only), so read state survives the card row's prune. A refusal before
anything started ends its operation; a restart pause is raised only by the
person's cards; an unreadable agent source stays an agent's.
* refactor(orchestration): a chat gets the pointer a terminal agent gets, sent through the chat's own queue
A structured chat now receives exactly what a terminal agent is typed: "You have N orchestration
messages ... run `orca orchestration check`" (formatMessagePointer, same CLI name). It goes
through the shared sendAgentTurn with delivery 'queue', the composer's queue-if-active: an idle
chat gets it at once, a busy chat's queue holds it as a normal card and sends it when the turn
ends. The lane's idle gate is gone; the send decides, as for the person's message.
The lane queues no second pointer while one of its cards still waits, read from the queued rows;
mail arriving meanwhile, or after the card is sent, is pointed again as the terminal lane points
new unread mail. A queued pointer counts as delivered, as an accepted one does. `check` and mail
read state are main's: only `check` reads mail.
The card records who it is from (queued_messages.source_json, kind 'agent', message
'mail-notice', with its senders) for the next PR to render. A restart's pause is raised by and
holds only the person's cards; Stop and /clear still hold an agent's.
Removed from the earlier designs: the message-as-turn batching, the check exclusion and taking,
the derived claims, lock and reconciliation, the sender on submissions, and their tests.
* fix(orchestration): a chat's pointer follows a card that leaves its queue unsent
The lane holds new mail while a pointer card waits, and retried it only on the chat's next
status change. A card that leaves the queue without a turn after it (the person deletes it
while Stop holds it, or its hand-off comes back) made none, so that mail sat unpointed until
something unrelated happened. The shared queue wiring now tells its host when an agent's card
stops waiting, read only when the queue changed, and the runtime redrives that chat's parked
mail. The runtime forwards the new host dep like the others.
Tests: that case end to end, and /clear carrying an agent card keeps who it is from. Agent card
bodies in tests are the pointer text; the restart pause's header says why an agent card may send.
* refactor(orchestration): no special handling for agent notices in the chat queue
A structured chat's orchestration notice is now sent through the chat's own send
like any message: an idle chat takes it as a turn, a busy chat's queue holds it
and sends it at turn end, under the same Stop, restart and /clear pauses as the
person's cards. Native chat no longer branches on who a card is from; the card
only records it.
- Restore main's queue pause logic (no restart exemption for agent cards).
- Remove the queue watch that redrove mail when an agent card left the queue,
and the host's queued-row read the lane used for it.
- The lane reads nothing of the chat's queue. It sends no second notice while
mail it already pointed at is unread, read off the mailbox alone.
* fix(orchestration): point new mail like a terminal, even while earlier pointed mail is unread
Drops the native-chat-only rule that held back a notice while the agent had not yet read mail it
was already pointed at. Also fixes main's stop-note test, which still built a provider handle in
the shape #24991 replaced.
* test(native-chat): keep the queued-message rig fixture under the line limit
* fix(test): drop main's duplicate codexProviderHandle import (same line as #25713)
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.52 · 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 11.
-
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.










