* test(repro): demonstrate #10142 tab X close bypasses running-process confirmation
Unit repro: closeTerminalTab (the X-button/middle-click entry) never consults inspectRuntimeTerminalProcess and drops a tab with a live child.
E2E repro: Cmd+W shows 'Stop running command?' for a tab running sleep 300; cancelling then clicking the tab X closes it silently.
Co-authored-by: Orca <help@stably.ai>
* fix(terminal): confirm running-process close on every tab close path (#10142)
The tab-strip X button, middle-click and the tab context menu closed a
terminal with a live child process without asking, while Cmd+W raised
"Stop running command?" for the same tab. The probe lived only in
TerminalPane's pane-level close handler; every mouse entry point reaches
closeTerminalTab(), which guarded pinned tabs and nothing else.
Move the decision into closeTerminalTab, above the web-runtime branch so
paired/remote host-backed tabs are covered too, and give the last-pane
keyboard close back to it instead of probing twice:
- running-terminal-close-guard.ts probes every live PTY of the tab and
fails open on a rejected probe or a stale remote handle, matching what
Cmd+W already did. No live PTY ids => fully synchronous close, so idle,
parked and hibernated tabs keep today's behavior.
- shouldConfirmRunningTerminalClose keeps lifecycle echoes, bulk closes,
CLI/RPC closes and the post-confirmation re-entry off the modal path.
- A standalone confirm store drives RunningTerminalCloseDialog, which
reuses the existing CloseTerminalDialog (no new user-visible strings).
The request carries the tab label because a tab-strip close can target
a tab the user is not looking at, and dedupes by tab id.
- TerminalPane.handleRequestClosePane now delegates the last pane to
closeTerminalTab. Its transport ptyId is nullable by design, so the old
path silently skipped the prompt mid-reattach; the pane keeps its own
probe only for closing one pane of a split.
- Agent panes win the dialog copy when a split has both an agent and a
plain command busy, instead of depending on PTY spawn order.
- Tab-group closeItem ran leaveWorktreeIfEmpty synchronously after a close
that can now defer; it moves to onClosed and still honors skipEmptyCheck.
Co-authored-by: Orca <help@stably.ai>
* fix(terminal): close the running-process confirmation gaps on every path (#10142)
Follow-up hardening on the tab-close confirmation, from review of the first
pass:
- A pinned tab with `confirmClosePinnedTab` off never got the running-process
prompt on any path, including Cmd+W, which is a regression against the old
pane-level behavior: the pinned branch short-circuited on pinned-ness alone
and re-entered with `force`, which the running guard excludes. The pin prompt
now supersedes only when it will actually appear; with the setting off the
close falls through to the running guard.
- The probe chain had no `.catch`, so a throw in the decision (a copy-kind
lookup on a tab id makePaneKey rejects, a store subscriber) left the tab
silently unclosed with no user feedback. It now fails open, as the pane path
it replaced did.
- A wedged remote inspect RPC could leave the X button looking dead for its
full 15s timeout. The probe is now bounded; every close path shares the
bound, so keyboard and mouse still behave identically.
- The agent-vs-command copy had two resolvers on exactly the keyboard/mouse
seam this issue is about. terminal-close-copy-kind.ts is now the single
policy; TerminalPane and the tab-strip guard both call it.
- The running queue is async while the pinned queue is synchronous, so both
could be pending at once and stack two modal overlays. The running dialog now
waits for a visible pinned confirmation.
- Deduping a repeat close request dropped the second caller's callbacks; it now
folds them in, so both closes resolve from one prompt. Ticking "don't ask
again" also drains queued prompts instead of showing one the user just opted
out of, and a queued prompt no longer inherits the previous tab's tick.
closeTerminalTab drops its private pinned predicate for the shared
isUnifiedTabPinned, whose only consumer the previous commit had removed.
* test(e2e): wait for `sleep` to own the terminal before closing it (#10142)
The running-process close specs polled `hasChildProcesses` to decide the tab
was busy, but macOS starts the shell under `login`, so an initialising terminal
already reports a child before `sleep 300` runs. Both specs could therefore
press close against a shell that never started the command: the probe correctly
saw an idle terminal and closed without asking, and the adjudicated repro failed
against a correct fix.
Wait for `foregroundProcess === 'sleep'` instead. Assertions are unchanged, and
the repro still fails at the pre-fix baseline (a92d8e0b0d).
* fix(terminal): ask instead of closing when the close probe times out (#10142)
Round-1 review follow-ups.
- The 4s probe bound closed the tab outright, but `inspectRuntimeTerminalProcess`
gives remote runtimes a 15s RPC timeout: any probe taking 4-15s silently killed
a running remote command that Cmd+W used to prompt about, and the pane path now
delegates its last-pane close to this guard. An unanswered probe is unknown, not
idle, so the timeout raises the confirmation with every pty treated as a
candidate. Failing open still applies to an *answered* probe (rejection, stale
remote handle), which is the pre-existing pane behavior.
- The split-pane Cmd+W probe had no bound at all; it now shares the same one, so
the two paths give the same answer to the same question.
- The renamed regression spec dropped its repro scaffolding: the hardcoded
/tmp screenshot directory (also a cross-platform path violation) and the
title/docblock that still described the bug as open.
* fix(terminal): adopt the double-activation guard and layout pty lookup from #10167 (#10142)
Cross-referenced against @innocarpe's #10167, which solved the same issue.
Two things it got right that this branch did not:
- Queue actions now hold off for 350ms after a queued request replaces the
visible one, matching the sibling pinned-tab confirmation. Without it the
second click of a double-click aimed at one tab lands on the next tab's
prompt and kills a running process the user never saw asked about — the
exact bug class this PR exists to close.
- The pty lookup unions the layout bindings with ptyIdsByTabId. A mounting
pane is bound into the layout before the liveness map catches up, and the
store's own teardown collector unions both for that reason, so reading only
the map let a close slip through that window with no prompt.
Also replaces the render-time ref write that failed React Doctor's
"Ref mutated during render" rule: the queued-request checkbox reset now goes
through CloseTerminalDialog's existing subject-change reset instead of
remounting via key, which keeps the exit animation on one element.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
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.36
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 7.
-
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.
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.










