Brennan Benson 498818fc63 Native chat: a message stopped before the agent got it reaches the agent with your next send (#27623)
* Carry a person's stopped messages to the agent with their next send

A message a person sent and then stopped before the agent started on it was kept
on screen as "Stopped manually" but never reached the agent. The delivery loop
now derives the stopped messages the agent is still owed, names them on the next
ordinary send's handover row, and each agent receives them in that same write as
framed context (Claude and Pi: framed text and images in the prompt; ACP: leading
blocks; Codex: turn/start additionalContext, or framed input items for images
and steers). Codex withdrawals that may have reached the agent are marked so they
are never carried.

* Let a queued card's hand-off carry stopped history; test the exactly-once outcomes

A card's hand-off records no sender, so carrier eligibility also accepts a
queued card whose body names no other agent. Tests cover every row of the
exactly-once table against the real host, each agent's rendering, the journal
fold, and that nothing a client parses changes.

* Keep a send that carried stopped history out of fingerprint reconciliation

After a host crash, restart reconciliation matches an unsettled send to the
agent's transcript by fingerprint. A carrier's transcript copy leads with its
stopped history, so it could never match and would read as never delivered,
which would also release its history again. Like a send with an attachment,
it now stays unconfirmed.

* Owe a stopped message only on proof it never reached the agent; carry Codex history as input

- Codex: every stopped message rides as leading framed input on turn/start and
  turn/steer (an older Codex silently ignores additionalContext and would read as
  delivered); add a Codex fit check against its 1,048,576-character input limit.
- Flip the marker: a withdrawal is owed only with `neverReachedAgent`, written where
  Orca proves it (host-held Stop, ACP held steer, Claude queue clear, a start the
  Stop ended). Old journals and Codex withdrawals read as not owed.
- A carrier releases its history only for Orca's own pre-write refusals or a marked
  withdrawal; provider refusals and not-signed-in are doubt.
- If the history does not fit, try once without its images, then send alone.
- Re-read the turn scope after selection; owed excludes typed slash commands;
  dropped-history fallbacks log through the host logger.

* Owe stopped messages only where Orca held them; list only the history actually written

- Claude's queue clear (lifecycle and interrupt sweep) and a start ended by
  Stop write plain `cancelled` again, as on main: Claude may already hold a
  swept send, and the child-exit site proved nothing for leftover rows. The
  proof sites are the host-held Stop withdrawal and ACP held steers.
- An adapter that leaves the history out after it fit calls the host's new
  `historyLeftOut` before writing; the host rewrites the pending row without
  `carries`, so those messages stay owed.
- History is chosen oldest first: each message with its images if it fits,
  else without them, else skipped this time without holding back later ones.
- Session History titles and previews skip `<stopped-message>` blocks through
  the existing hidden-block list.

* Build the swept-send test's marked fact with the shared builder

* Keep a person's own words when a rewind rebuilds their message

A rewind rebuilt each kept message from the provider's copy. Codex's copy of a
send that carried stopped history starts with the framed history, so that
bubble showed it. Keep Orca's body for a person's own message, as the live
fold already does; other senders keep the provider's body with their sender.

* Require the logger on the handover context

* Write a plain Claude send as soon as before when no stopped history rides

Wrapping the content build in an async function added microtask ticks before
every Claude write, even with no history, which a turn-timing test caught.
Return the same promise when nothing rides.

* Keep stopped messages and their carriers' coverage through a rewind

A rewind rebuilt history from the provider's items, which hold none of the
host's send facts, so a stopped message the agent never received lost its
bubble and its submission, and a surviving send that carried it lost its
coverage. The rebuild now restates those sends with the submission and
dispatch rows that first recorded them, in both the epoch and the post-clear
paths. A carrier the rewind removed is simply absent, so what it carried is
owed again with the next send.

* Test that a rewind keeps stopped messages owed or covered

Drives the real host, store and journal through a Codex-shaped rewind:
before and after the carrier, after a /clear, across a host restart, for a
stopped message nothing carried, and for a rewind that crashed after its
history committed. Each checks what the desktop and the phone draw and what
the next send carries.

* Owe stopped history again when a carrier provably never reached the agent

A Pi prompt refused for sign-in after its retries, and an ACP prompt line the
encoder refused before writing a byte, now settle with neverReachedAgent. The
owed derivation treats any carrier rejection carrying that proof as refused
before write, so its history rides with the next send instead of being lost.
Pi checks sign-in before it records a prompt from 0.84.0 (Orca's floor).

* Share the Pi adapter test harness with other Pi tests

Moves the scripted connection and setup out of the adapter test, unchanged, so
a stopped-history test can drive the real adapter without growing that file.

* Prepare each send once with the stopped history that fits, in one batch frame

Stopped messages now reach the agent in one frame ahead of the next send: a
header saying they are earlier, stopped history, one tagged element each with
its images numbered in the order sent, then a 'User message:' label. Only a
'<' that would open or close the frame's own tags is escaped.

Each adapter prepares the send once (prepareDispatch): images are read once,
each message's cost is weighed once against that agent's real limits, and the
result is the exact payload plus the ordered ids inside it. The host lists
those ids on the pending row and dispatch writes that same payload, so what a
row says it carried is what the agent got. A message that does not fit goes
without its images, then shortened with a marker; only when not even that fits
does it wait, and the frame says how many were left out. A plain send with
nothing owed is prepared and written exactly as before.

ACP measures every prompt's whole line, text included, and refuses a text-only
message too long for one line before writing it. Titles, previews and copied
first prompts hide the whole frame and its label, however long.

* Keep a stopped or restarted queue paused through a rewind after a /clear

After a /clear the rewind rebuilds in place, so a restated accepted carrier
reads as a turn after the person's Stop (or a restart's pause) and released
the cards it held. Restate those pauses above it, as a new epoch does.

* Restate a rewind's stopped messages in the order they were sent

Owed history follows the restated rows' order, so write them in their old
send order within each anchor rather than the order they were refused.

* Fit the rewind tests to the prepared-dispatch frame

* Cap carried history at 64k characters and degrade only the oldest stopped message

* Owe stopped history again when ACP or Claude refused its carrier before writing it

* Strip a carried-history frame before capping a Grok preview

* Leave a title that opens like a frame but never closes it unchanged

* Drop the image labels Codex writes for carried history images from titles and copied prompts

* Read a stopped message's images one by one so a refused image leaves the readable ones riding

* Settle a Pi prompt still waiting out a sign-in refusal as never reaching Pi when the session ends

* Name the journal rewind module after the rows it builds

* Type Pi's rejection helper with the facts that can reject a message

* Hide everything ahead of a carried-history frame within a bounded lookahead, and cap carried images at 20

* Fit Pi's stopped history beside the line it is written, and settle an encoder-refused prompt as never reaching Pi

Preparation measured the prompt without the streamingBehavior field PiRpcTurns adds, so a nearly full
carrier could exceed the line limit; the encoder then refused it and the write settled as unknown,
covering the carried history forever. Both now measure the frame from the same builder, and an
encoder refusal settles as writeFailed with neverReachedAgent, leaving the history owed.

* Record stopped messages appended to the agent's own log in the journal

A host-only mark on an id no item takes, written before the append and
cleared by a later proven refusal, so an older host reads past it and
clients never see it.

* Derive owed stopped messages from append records as well as ACP and Pi carriers

* Append owed stopped messages to the agent's own log at the next handover

The record is written first and covers them; only a proven refusal owes
them again. A failed or unknown append is logged and never holds the
send. Agents that cannot append keep carrying them in the send.

* Write Claude's stopped messages as shouldQuery:false frames that run no turn

Each message is its content and then Claude's own block-form
"[Request interrupted by user]". The append settles when Claude names
every frame in a result, and its zero-turn commands are claimed by uuid
so they open no turn, show no Working and write no row. The prepared
carrier send and the startup-failure never-reached mark are gone.

* Inject Codex's stopped messages with its own turn_aborted record while idle

One thread/inject_items holds each message and the default-mode
user-role marker. Only "method not found" proves a refusal; any other
error may have recorded them, so they are never injected again. The
prepared carrier send is gone.

* Carry stopped messages for ACP and Pi as plain text, whole messages only

Each rides as its words and Claude's interruption line ahead of the
send's own words, oldest first, while it fits the agent's own limits;
the first that does not fit waits with the rest. The frame, numbering,
labels, shortening and history caps are gone.

* Drop the stopped-history frame stripping from Session History scanners

Nothing writes the frame any more. Claude's and Codex's own interruption
records were already never read as a title or first prompt.

* Keep stopped messages and their append records through a Codex rewind

Only stopped sends are restated, each with the record that covers it, so
a kept message is never injected twice. Carrier coverage on rewind is
gone: Claude and Codex no longer carry, and ACP and Pi never rewind.

* Keep an append record through a Codex rewind only where Codex keeps its pair

A turn can come between a Stop and the send that appends the stopped message (another
agent's mail, a slash command, a busy Codex). A rewind to before that turn kept the
bubble and its append record, while Codex dropped the injected pair, so the message
read as covered when the agent no longer had it.

The reducer now keeps each record's row position. A rewind restates a record only when
that row precedes the rewound turn, and writes it back after the row it followed, so a
later rewind compares the same way; the same-epoch rebuild after a /clear takes back
every record after the floor first. A stopped send is restated with its submission and
rejection rows only: the queued withdrawal never wrote a handover row.

* Check, bound and settle each stopped-message append once

Each session now gives one answer for how its agent takes stopped messages (append,
carry or none), instead of a per-session check beside a router that always offered
the append.

Right before writing, both agents check again that the child, connection and fence are
the same and that no turn runs, by the agent's account or Orca's journal; a failed
check is refused, so the message stays owed. Reading a stopped message's images has its
own 2 s limit and the write and its settlement another 2 s, so a send or Stop queued
behind a stalled append waits about 4 s at most; work abandoned on a timeout never
writes later. A message with nothing left to read is logged as such, not as unknown.

Claude: the append keeps only a uuid observer. Its own lifecycle, echo and result
settle it and stay out of turn tracking, even late; its running, init and idle frames
are left alone. It holds the child from rest only while unsettled, and a child that
ends settles it from what the writes prove, so frames it never took are refused.

Codex: every inject error is unknown. A Codex without the method answers an error Orca
cannot tell from a failed write, so it is never asked again, as before appends existed.
Remote image URLs are left out: Codex refuses them before recording anything.

* Give ACP's carried stopped messages a text block of their own

The carried words were folded into the send's first text block. With an image-only
send its own images came before the interrupted text and read as part of the stopped
request. The prompt is now the carried images, one text block with the carried words,
then the send's own blocks unchanged. Pi keeps text and images apart, so it cannot
interleave them, and stays as it was.

* Hide Codex's own <turn_aborted> record in Session History

Codex writes a user-role <turn_aborted> message for its own Stop. After a first message
holding only an image, that marker became the session's title, its copyable first
prompt and a preview row, in natively interrupted sessions as in appended ones. It is
now hidden like the other harness blocks in titles and previews, and never seeds the
first prompt.

* Give carried stopped-message preparation one time limit, so a stalled image never holds the send or Stop

* Read Codex's stopped images within Orca's attachment limit, not Claude's

* Append only while the agent is idle by its own account, and record nothing while it is busy

* Find a Codex rewind's cut in one place for kept rows and kept append records

* Drop the rewind send-order sort, share the interruption marker, and return untouched files to main

* Test the append end to end through the router, and a late append echo with the next send's words

* Leave out a stopped image whose read stalls, and never read that file again while it is stuck

* Inject Codex's stopped images only into a Codex that resizes injected images, read from its handshake

* Skip and log a kept append record no rebuilt row precedes, instead of anchoring it at the end

* Restate a rewound stopped send's rejection through the one dispatch-row builder

* Keep a stopped image unread until every abandoned read of it settles, not just the first

* Read stopped-history transcripts through the one projection every client now shares

Main removed the rejectedInPlace option: the desktop and the phone now draw a recorded-then-rejected
send the same way, so the tests read one transcript instead of comparing two.

* Deliver stopped messages with the next send: Codex by injection, every other agent inline

Claude no longer writes stopped messages as separate shouldQuery:false appends with
their own frame-claiming, idle gate and settlement. Like ACP agents and Pi, it now gets
them at the front of the person's next words-only send, followed by the
"[Request interrupted by user]" record. Codex keeps thread/inject_items right before the
send, idle only, at most once; a Codex without the method is refused and its sends carry
them instead.

One selection serves both: words only, the newest that fit a 1 MiB encoded bound, in the
order sent, older ones left out and covered. A send with attachments carries nothing, so
history can never push a send past an agent's limits; the per-agent prepare and fit
modules, stopped-image reads and Codex version plumbing go. The injection record is
renamed for what it is. Rewind restatement is split out: a rewind drops stopped
messages with their bubbles, as before, and nothing is injected twice.

* Bound stopped history by one send's size beyond the newest, counting its marker, and keep scanning older messages

* Keep a whole stopped-history delivery within one send, counting either transport's framing

* Budget stopped history by the agent's remaining context beside the send, and carry none when none fits

* Bound stopped history by one send again, not the agent's context: each would have reached the agent unstopped

* Bound stopped history together with the send it rides with

The delivered stopped messages and the send's own words never exceed one send's size, so the agent is never handed more than a send the person could make. If the newest doesn't fit, they all stay owed for a later send.

* Never owe a stopped message too large to deliver beside any send

Such a message could never fit, so it held every older one back for good.

* Owe a stopped message only if it fits beside a one-letter send

The smallest send that carries history has one letter, so the owed bound reserves that, not an empty send.

* Deliver Codex's stopped messages inline, like every other agent

Codex no longer gets stopped messages through thread/inject_items. Its next
turn-opening send carries them at the front, the same text every other agent
gets, and the carrier's own pending row records what it carries. That removes
the injection module, its host-only journal row and reducer handling, the
adapter and router hooks, the unsupported-method fallback flag, and the
<turn_aborted> hiding in Session History that only injected items needed.

A Codex rewind rebuilds kept messages from Codex's copy, which now leads with
the carried words, so a person's own message keeps the words Orca recorded, as
the live fold already does. The per-message size allowance is now the inline
framing itself.

Measured with real Codex 0.159.0 before building: inline acted on "go ahead"
8/8, never on "ignore", and 0/21 on unrelated follow-ups, matching the injected
pair and a real Stop.

* Owe a Codex send's stopped messages again when Codex declines its turn/start

A request Codex answered with an error recorded nothing, so the rejection now
carries the never-reached proof and any stopped messages that send carried are
owed again instead of covered forever. A timeout or transport failure still
proves nothing.
2026-10-14 00:55:02 -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

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 · Android APK · 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   CodeBuddy logo CodeBuddy   Codebuff logo Codebuff   Freebuff logo Freebuff   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: Group 11 is full. Scan to join the Orca community WeChat group 12.

    WeChat group 12 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
2.6 GiB
Languages
TypeScript 96.2%
JavaScript 3.1%
Swift 0.2%
CSS 0.1%