Brennan BensonandClaude 4bd4f8cf06 feat(native-chat): show each interrupted chat's workspace as its read-only sidebar card (#25652)
* feat(native-chat): show each interrupted chat's workspace as its read-only sidebar card

The resume-on-restart dialog listed workspaces as a bare name and glyph, so users could not
tell their sessions apart. It now renders each workspace with the sidebar's own WorktreeCard
in a new read-only mode, with the offered chats in place of its live agent rows, and nests
child workspaces under a listed parent the way the sidebar does. The dialog is wider and the
chat rows use the sidebar's compact agent row layout.

Co-Authored-By: Claude <noreply@anthropic.com>

* test(native-chat): name the nesting helper for what it returns

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(native-chat): resume dialog cards show no status

The dialog's cards stand in for the chats before the restart, so the sidebar's live status
(Failed, now Interrupted) read as a verdict on chats the dialog offers to resume. A read-only
card shows no status, and in the new card style its PR joins the badges because the status
lane that normally holds it is gone.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(sidebar): a read-only card is inert and shows no live state, whatever its caller passes

A read-only card stayed inert only because each control checked `readOnly` on its own and the
caller left out the handlers that would turn the rest on: passing `onLineageToggle` put a live
child-workspaces toggle on it. It also still painted live state over the resume dialog's chat
rows: the sleep dim, the "Queued for deletion" overlay (which blocked unticking a pre-ticked
chat) and the prompt-cache countdown.

WorktreeCard now reduces a read-only card's props to what it pictures (every handler, selection
and active flag dropped), and the controller resolves `readOnly` once into what the views
already read: card properties without status, ports or live agents (and with the host), no
sleep or delete state, no cache countdown, and one `interactive` flag for its own controls.
A contract test renders a read-only card with every feature and handler on in all three card
styles and fails on any control outside the caller's rows or any live state.

* fix(native-chat): nest and indent the resume dialog's child workspaces as the sidebar does

A child workspace whose parent has older metadata with no host id stayed at the top of the
dialog, though the sidebar nests it: the dialog copied a strict same-host filter, while the
sidebar treats a hostless row as belonging to the host. The nesting rule now lives in one
sidebar lineage helper, getWorktreeLineageAncestorsOnHost, which scopes by host the way the
sidebar's lineage inputs do.

In the legacy card style a nested child was inset for its parent's depth instead of its own,
so it sat one sidebar step too far left (0px instead of 14px), outdented into the parent's
padding. Each child is now inset for its own depth, as a sidebar row is.

A groups-level test renders real sidebar cards from the store, with the child nested under a
hostless parent, and checks every offered chat's checkbox renders and the legacy inset.

* fix(native-chat): the resume dialog places every workspace even if lineage loops

Nesting followed each workspace's parent chain, so two workspaces listed as each other's
ancestors (possible only when two hosts report opposite lineage for the same ids) were placed
under no top-level entry and vanished, while their pre-ticked chats would still be resumed.
The loop is now cut where the walk first comes back, so every workspace renders.

* fix(native-chat): keep "Don't ask again" above the resume dialog's buttons when narrow

Below the small breakpoint the footer stacks bottom-up, so the option moved into it rendered
under Resume and Dismiss all. It now reads top to bottom: the option, then the actions; wider
windows keep the single row.

* test(sidebar): import the card statically in the read-only contract test

Its dynamic import ran in a beforeAll with a 20 s timeout, below the suite's 60 s hook timeout,
and timed out under parallel load, which skipped all six contract tests.

* fix(sidebar): legacy lineage children step in as far without a status lane

Legacy cards outdent their nested child list by 1.125rem to pull it back over the 22px status
lane. A card without that lane (a read-only card in the resume dialog, or the sidebar with the
Status property off) kept the outdent, so a child's title sat 3px right of its parent's instead
of 25px. Without a lane the list now sits at ml-1, which gives the same 25px step (39px at depth
2). Cards with a status lane, the default sidebar, render exactly as before.

* fix(native-chat): nest resume dialog children by the sidebar's own row rule

Round one nested a child under a parent whenever either had no host id, but the sidebar's row
builder looks a parent up on the child's own host, so a row with no host id nests only under a
parent with none either. The dialog showed a parent/child pair nested that the sidebar shows side
by side.

The row builder's parent lookup is now one function, getSidebarLineageParent, and the dialog
walks ancestors with it (getSidebarLineageAncestors) over the same non-archived rows and cycle
set. The chat's workspace is still found on its host, falling back to a row with no host id.
A test checks the four host pairings against the real row builder, and the dialog test renders
each pairing with every chat's checkbox.

* test(sidebar): pin child-workspace indent with and without a status lane

Covers legacy, compact and new card styles with the Status property on and off. With Status on,
the legacy and compact sidebar keep their outdent unchanged; with it off they now step children
in by the same amount; the new card style is identical either way. The file now imports the
card statically, since its 15 s per-test dynamic import timed out under load.

* fix(sidebar): a read-only card's child workspaces step in as the sidebar's do

The legacy outdent on a card's child list cancels its status lane, which in the sidebar is the
unread button plus the row gap: 1.125rem, exactly the outdent, not the 22px the previous fix
assumed. Its ml-1 for a card with no lane put the resume dialog's children 4px deeper per level
than the sidebar's (25px against 21px). With no lane there is now nothing to cancel and no
margin, which gives the sidebar's 21px (35px at depth 2).

Status is a fixed card property, so every live card has the lane: only a read-only card takes
this branch, and the live sidebar is unchanged. The tests now pin the outdent for live legacy
and compact cards and no margin for a read-only one, instead of an unreachable Status-off state.

* test(sidebar): a read-only card never carries main's multi-selected marker

Main now styles a multi-selected card through data-worktree-card-selected. The contract test
passes isMultiSelected, so it now asserts the marker stays off a read-only card, and drops the
context-menu event constant main removed from that module.

* fix(sidebar): preserve quiet read-only card geometry

* fix(native-chat): match resume cards to sidebar rows

* fix(sidebar): preserve passive SSH identity on read-only cards

* fix(native-chat): keep resume focus and folder host identity

* fix(native-chat): remove resume dialog list border

* fix(sidebar): keep passive SSH pills static

* fix(native-chat): align resume card vertical spacing

* fix(native-chat): preserve cache-only card header spacing

* fix(native-chat): lay the resume dialog out as a checkbox-column list

Every row of the resume list (Select all, workspace, chat) now keeps its
checkbox in one left column; nesting indents only the content after it,
and a divider separates every row. A workspace checkbox is tri-state over
its own chats and those of the workspaces nested under it; Select all
heads the list with an "N of M selected" count. Failures a retry cannot
fix stay out of both. Up/Down move between the list's checkboxes.

The dialog no longer renders the sidebar's WorktreeCard, so the read-only
card mode and the sidebar changes that only served it are reverted to
main. The sidebar lineage helpers stay: the dialog still nests child
workspaces by the sidebar's own rule.

* fix(native-chat): name SSH hosts by their saved label in the resume dialog

The workspace row's host chip spelled an SSH host with its raw target id
(e.g. ssh-1728291234567-abc12d) because it never got the sidebar's host
labels. It now takes them from useSidebarHostScopeOptions, as the delete
dialog does, so the chip reads "devbox" like the sidebar.

Also translates the dialog's five new strings in es, fr, ja, ko and zh.

* fix(native-chat): group the resume list in bands and let a project select its chats

The resume list now follows the common grouped-list pattern: each
workspace heads its chats with a full-width tinted band (lighter for a
nested child, at its own indent), chats are split by plain hairlines, and
groups meet without gaps or rounded row corners.

The project row gets a checkbox in the same left column, tri-state over
every eligible chat in the project (nested workspaces included, failures
a retry cannot fix left out) with an "x of y" count, on a band a step
stronger than a workspace's.

The list takes arrow keys, so it is now a named group (role="group").

* fix(native-chat): no project row for workspaces the resume list cannot place

Workspaces the store cannot place in a repo were grouped under a header
with an empty name, so the new project checkbox was announced as "Select
all chats in ". Main and the earlier heads showed that header as a bare
folder glyph with no name, and there is no id to fall back to. Those
workspaces now get no project row; their own rows and Select all still
cover their chats.

* fix(native-chat): lay the resume list out as nested workspace boxes

Brennan chose the nested-box layout without row dividers. A project is a
tinted band; each workspace is a bordered, rounded box one step in from
its project, holding its header band and its chats, and a child
workspace's box sits inside its parent's, after the parent's chats, at
the parent's chat indent. The boxes are drawn in the content area only,
so every checkbox stays in the one left column outside them. Rows carry
no dividers; the box border is the only line.

* fix(native-chat): show the resume list as a tree

Brennan chose the Resume Tree. The list is now a tree: machine, then
project, then workspace (a child workspace is a node inside its parent,
after the parent's chats), then the chats. Every row keeps its checkbox
in one left column, then an 18px indent per level, a disclosure arrow
(an empty slot on a leaf), the icon and label, and its count. Levels read
apart by icon and weight; there are no boxes, bands or row dividers, only
the divider under Select all.

The machine level shows only when the machine is not obvious (a remote
host, or chats on more than one), named with the sidebar's host labels
and an SSH chip; it replaces the per-workspace host chip. Chats are
grouped per machine first, so one workspace id on two hosts stays two
nodes.

Every node is tri-state over the eligible chats under it, through the
existing per-chat onToggle. Nodes start expanded; collapsing is local to
this opening and keeps the selection. The list is a role="tree" of
leveled treeitems: Up/Down move between checkboxes, Left collapses and
Right expands the focused node.

* refactor(native-chat): read each resume chat through one key helper

Every per-chat read in the resume tree (its tick, its toggle, its
failure, and each group's coverage) now goes through chatState, so a
later change of chat key stays in one function. Tests pin the machine
level's host rules: a runtime host gets a machine node but no SSH chip.

* fix(native-chat): make the resume tree's keys work from its Tab stop and after a click

Tab lands on the tree itself, where the arrow keys did nothing. Down and
Home now enter at the first checkbox, Up and End at the last; Home and End
also jump to the ends from a row.

Clicking an arrow with the mouse left focus on the arrow, where no tree
key works. After a collapse or expand click, focus now moves to that
row's checkbox, or to the tree when the checkbox is disabled.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-07 23:06:45 -07:00
2026-10-08 01:07:05 +00: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 0.0.52 · 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: Scan to join the Orca community WeChat group 11.

    WeChat group 11 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
1.8 GiB
Languages
TypeScript 95.4%
JavaScript 3.9%
Swift 0.2%
HCL 0.1%
CSS 0.1%