* refactor(mobile): export the mobile web manifest read schema
The generation store re-parses the manifest it cached, and it must read it back
with the same loose reader the fetch accepted it under: parsing strictly after
accepting loosely would turn a host's added field into a forced redownload on
every launch.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* feat(mobile): add the per-host mobile web generation store
Turns a verified bundle into an atomically activated, host-scoped generation
directory under the OS cache, and reads it back. No RPC, no UI, no flag: the
native view is later handed the directory read-only and never writes to it.
The single directory under `generations/` is the activation, so there is no
activation file to edit: a commit deletes every other generation before the
rename, an interrupted one leaves zero generations for the runbook's redownload
rule, and two directories or an unreadable manifest drop the host tree instead
of guessing. `tmp/` is never an activation candidate and every one of them goes
at launch. `hosts.json` carries recency only, so losing it costs eviction order
rather than a generation.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): never evict the host a commit just activated
`now()` is a wall clock. With four hosts cached, one backward jump made the
fifth commit's own entry the oldest, so it evicted the host it had just
activated and handed back an ActiveGeneration whose directory was gone.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* Revert "fix(mobile): never evict the host a commit just activated"
This reverts commit a082ac1777. That commit carried all six round-1 fixes under
a subject naming only one of them; the six land again below, one per commit.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* refactor(mobile): drop the generation store's unused eviction entry point
`evictHostsBeyond` had no caller: commit enforces the four-host ceiling itself,
and a launch-time sweep for a shrunk limit can be added when something shrinks
it. The two `createDirectory` calls went with it, since the port already creates
intermediates, plus a line on what the Android rename fallback leaves behind.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): never evict the host a commit just activated
`now()` is a wall clock. With four hosts cached, one backward jump made the
fifth commit's own entry the oldest, so it evicted the host it had just
activated and handed back an ActiveGeneration whose directory was gone.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): fold case when refusing an asset named like the manifest
APFS and NTFS are case-insensitive by default, so `Manifest.JSON` landed on the
store's own `manifest.json` and the activation read back as the asset's bytes.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): keep a completed activation when the recency index cannot be written
`hosts.json` is written after the rename, so a disk that filled between the two
turned a generation already on disk into a thrown commit. The index carries
recency, not truth, and the next activation rewrites it whole.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): refuse to commit a staged handle whose tree is gone
Commit deleted every other generation before it looked at the staged tree, so
committing an aborted or swept handle destroyed the live generation and only
then threw. The check moves ahead of the first delete.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* test(mobile): close four surviving generation-store mutants
Sweeping only the first host's tmp, staging over residue, dropping the serial
queue, and dropping the stale-index pruning all passed the suite. The stage
race needed two differing asset lists under one build id to be visible at all:
with identical ones an interleaved pair ends on the same bytes as a serial one.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): activate only a build-id entry that holds a manifest
An entry under `generations/` matching the staged build id was taken as the
activation on its name alone, so an empty directory of that name — what a
crash between the rename and the post-rename check leaves on Android under
API 26 — or a plain file made the commit drop the verified staged tree and
return a generation that cannot be read back.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): never delete a cache because a manifest read failed
The adapter mapped every `file.text()` throw to null and the reader treated
null as corruption, so one iOS data-protection or I/O blip deleted the only
verified generation a host had. Missing stays null and still drops the tree;
a failed read now throws, and the reader returns no activation without
touching disk, leaving the caller to redownload.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* refactor(mobile): drop the generation store's unreachable build-id guard
`MobileWebBundleManifestReadSchema` already pins `buildId` to the sha256
pattern, so no manifest reaching the store can fail the second check.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* test(mobile): pin that eviction ignores a non-host directory
Dropping the host-key filter in `listHostDirectories` passed the whole suite;
the ceiling would then count and evict anything else under the OS cache
directory.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): keep a mid-download host out of the cache ceiling
A host holding only a staging tree was counted against the four-host limit
and, having no index entry, sorted first for eviction, so four cached hosts
plus one download meant the next activation deleted the tree that download
was about to commit. The ceiling now counts hosts with a generation; sweeping
still walks every host directory.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): record recency when a commit finds the build already active
The same-build early return skipped the index write, so a host that
redownloaded the bundle it already had stayed the least recently activated
and was the first evicted. No eviction pass on that path: the host count is
unchanged.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
* fix(mobile): honour only staged handles the store itself issued
`StagedGeneration` is structurally typed, so any object of that shape made
`commitGeneration` rename over, and `abortStagedGeneration` delete, a
directory of the caller's choosing. Handles are tracked in a per-store
`WeakSet` and anything else is refused before a filesystem call.
Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
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
OpenCode
MiMo Code
Amp
OpenClaude
Antigravity
Pi
oh-my-pi
Hermes Agent
Devin
Goose
Auggie
Autohand Code
Charm
Cline
Codebuff
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 or join TestFlight
- Android: Download APK 0.0.48 · 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 8. Group 8 may be full; if so, scan the Group 9 QR code instead.
-
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.












