* Add keyboard shortcut to toggle the Quick Commands menu
- New `tab.openQuickCommandsMenu` keybinding action (no default binding)
- TabBarQuickCommandsMenu listens for the binding and toggles open/closed
- Scoped to the active tab group naturally since the component only mounts when its group is focused
* Show keyboard shortcut in Quick Commands menu trigger tooltip
* Add tests
* expand tests
* Expand keyboard toggle to call handleOpenChange and skip repeated keys
- Replace `setMenuOpen` toggle with `handleOpenChange(!menuOpen)` so closing
via keyboard runs the same reset logic (query, focus frame, value override)
- Guard against key-repeat events to prevent rapid toggling on held key
- Wrap `handleOpenChange` in `useCallback` so it's stable enough to include
in the `useEffect` dependency array without causing spurious re-registrations
- Update tests to reflect that re-running the effect between presses is
required for the close path, and add a repeat-event test
* Add docstring to withShortcutHint func
* review: harden quick commands menu shortcut
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
Keep the synthetic floating workspace local while a remote runtime is active, including terminal/browser creation, activation, close, and remote snapshot handling.
Maintainer follow-ups:
- require worktreeId for runtime-session terminal create payloads
- add renderer-backed terminal create reply sender regression coverage
- merge current main and keep the WSL readDir breadcrumb test aligned with main's Windows-only handler coverage
A deterministic per-load renderer fault (bad GPU driver, corrupt chunk,
AV interference) crashes on every load. Orca auto-reloads recoverable
renderer deaths after 250ms, so without a limit it reloads every
~0.25-1.3s forever — the Windows clusters F0BDRAZN55L (launch-failed
exit 18, bootstrap loop ~1.3s) and F0BDPCL93UM (ACCESS_VIOLATION on
Win10 1909, ~0.8s loop). shouldRecoverRendererAfterProcessGone only
gated integrity-failure/launch-failed, never 'crashed'/'killed'.
Add a rolling-window circuit breaker (3 recoveries / 60s) consulted at
the reload point in createMainWindow. When it opens, Orca stops
auto-reloading, records a renderer_recovery_circuit_breaker_open
breadcrumb, and shows a native Reload/Quit prompt (the renderer is dead,
so a main-process dialog is the only available surface). The window is
NOT reset on did-finish-load: a crash loop renders on every cycle before
dying, so stale attempts must age out by time instead.
Covered by renderer-recovery-circuit-breaker.test.ts (pure helper) and a
createMainWindow.test.ts integration test that drives the loop and
asserts reloads stop after the limit.
Co-authored-by: Neil <neil@stably.ai>
* chore(lint): upgrade oxlint to 1.71 and enable 7 new rules
Upgrade oxlint 1.67.0 -> 1.71.0 (1.72 was blocked by the repo's 3-day
minimum-release-age supply-chain guard; nothing here needs it). The
bump is a no-op on the existing config.
Enable 3 error rules (backlog autofixed to zero in this commit) and
4 warn rules (surface signal without gating CI):
error (autofixed, behavior-preserving):
- unicorn/prefer-node-protocol (~1531 sites: bare builtin -> node:)
- typescript/no-import-type-side-effects (~36: all-inline-type -> import type)
- unicorn/no-array-reverse (19: copy-then-reverse -> toReversed)
warn (real signal, current fires are test-only/correct):
- unicorn/no-array-fill-with-reference-type (aliasing footgun guard)
- typescript/no-unsafe-function-type (bans bare Function type)
- unicorn/prefer-array-flat-map (map().flat() -> flatMap())
- unicorn/prefer-regexp-test (.match() in bool ctx -> .test())
mobile/.oxlintrc.json extends root, so it inherits all 7; the autofix
ran from root and covered mobile/ too.
Verification (all green): oxlint 0 errors (root+mobile+aux configs),
oxfmt clean, typecheck (node+cli+web), vitest 22795 passed / 0 failed,
builds (electron-vite + web + cli) succeed. node: rewrites confirmed to
skip embedded SSH/CLI string payloads (AST-only); all toReversed sites
verified to operate on fresh copies or write-once locals.
* chore(lint): bump mobile oxlint to 1.71 so inherited rules parse
mobile/ is a standalone pnpm project pinning its own oxlint@1.67, which
lacks unicorn/no-array-fill-with-reference-type (needs >=1.70). Since
mobile/.oxlintrc.json extends the root config, mobile CI's 'cd mobile &&
oxlint' failed to parse the new rule. Bump mobile to match root (1.71).
Verified in mobile/: oxlint 0 errors, oxfmt --check clean, tsc --noEmit
pass, vitest 978 passed / 0 failed.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Orca <help@stably.ai>
* Support background and focused terminal presentation modes
* Add `presentation` field ('background' | 'focused') to terminal
creation to control focus behavior.
* Prevent terminal creation from stealing UI focus by default.
* Return discoverability warnings when default terminal presentation
fails, unless explicit background mode is selected.
* Update orchestration SKILL.md to clarify review-only worker
completion rules and named owner handoffs.
* Prevent background terminal sessions from auto-activating
Ensure that terminal tabs created with 'background' presentation (such
as background agent sessions or locally backed renderer transports) do
not automatically activate or get selected as the active tab on remote
or mobile sessions.
- Add a selectIfNoActiveTab option to control auto-activation on mobile
- Set presentation to 'background' for remote runtime transports and
agent background sessions
- Skip tab auto-selection when the presentation is background
* Keep background terminal create payloads focused
* Fix browser pane stuck in HTML fullscreen (#6442)
Guest content in a browser pane could enter HTML fullscreen but not
exit it: requestFullscreen() resized the host BrowserWindow into native
fullscreen, and exitFullscreen() had nothing to restore, leaving the
pane stuck.
Set the webview's disableHtmlFullscreenWindowResize preference so HTML
fullscreen is contained to the <webview> element. Exit then works and
fullscreenchange fires as guests expect.
* Apply browser guest fullscreen policy consistently
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
* feat: copy a file from the explorer to the OS clipboard
Add a "Copy" action to the file explorer context menu that puts the
actual file on the system clipboard, so pasting in Finder/Explorer/a
file manager drops the file itself instead of its path as text.
- macOS: write a public.file-url buffer; Finder synthesizes the legacy
file types it needs for paste.
- Windows: Set-Clipboard -LiteralPath populates the CF_HDROP file drop
list that Explorer pastes as a file.
- Linux: best-effort, picked by desktop — text/uri-list on KDE,
x-special/gnome-copied-files on GNOME-family — via wl-copy or xclip.
- Local files only; the action is hidden for remote/SSH files and the
web client, where no OS clipboard reference is possible.
The platform logic never throws: failures resolve to a structured
result and the renderer surfaces an error toast.
* Review copy-file clipboard safety
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
* fix(window): remove double title bar on Linux
On Linux the BrowserWindow titleBarStyle fell through to undefined, so
the native WM title bar stayed and stacked on top of Orca's own
renderer-drawn titlebar — two title bars. macOS (hiddenInset) and
Windows (hidden) already suppress the native one.
Drop the native frame on Linux (frame: false) and extend the renderer's
Windows-only custom-titlebar branches (logo/menu anchor, app-name
hiding, window-controls spacer + CSS vars, and the WindowControls
min/max/close cluster) to Linux via a shared `hasCustomTitleBar` flag,
so Linux gets one title bar with working window controls — matching the
Windows custom-titlebar path.
Fixes#5724
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* review: harden Linux custom titlebar gating
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
* feat: rename worktree folder to match branch on first work
When the first agent message auto-renames a freshly created creature branch to a
short, work-derived name, also align the on-disk worktree folder and the sidebar
display name with it. Re-key every worktree-scoped slice of state — renderer
store maps plus the persisted main-process state — through the resulting id
change so the live worktree survives the rename instead of being treated as a
deletion (its tabs, terminals, browser panes, and git status all follow).
The rename is best-effort and local-only: a skip or failure (remote runtime,
Windows lock, destination taken) leaves the folder as-is and never undoes the
branch/display rename that already landed.
Squashed from the original PR #4743 commits, rebased onto upstream/main to drop
accumulated merge commits and i18n formatting churn so the branch carries only
the feature diff:
- Rename worktree folder to match branch on first work
- migrate renamed worktree session ids
- keep the live worktree alive through a folder rename
- address PR review feedback
* Address PR review feedback (#4743)
- orca-runtime: emit in-process worktreesChanged client event on folder rename, mirroring notifyBranchRenamed so onClientEvent listeners aren't left stale
- worktrees: re-key rightSidebarExplorerViewByWorktree and activeWorkspaceKey through a worktree-identity rename (both were worktree-scoped but missed by buildWorktreeRenameState)
- branch-name-from-work: treat prefix-only model output as an empty slug so the caller skips the rename instead of producing a doubled prefix
- worktree-folder-rename-target: document why posix.dirname is safe (Windows filtered out earlier)
- tests for each of the above
* Extract branch rename test helpers to a separate harness file
Move git responders, mock builders, and test event fixtures out of
first-work-branch-rename.test.ts into a new test harness file. This
reduces file length and removes the max-lines ESLint disable directive,
complying with project style guidelines.
* Wrap entire OnboardingFlow in TooltipProvider
Enable the use of tooltips anywhere within the onboarding flow, rather
than restricting them to the step indicators.
---------
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
* fix(browser): set up session policies for default browser partition
The default browser partition (persist:orca-browser) was created in the
registry constructor but never got session policies — permission handlers,
download handlers, WebAuthn handlers, etc. — because:
1. hydrateFromPersisted() explicitly skips the default partition
2. createProfile() never targets the default partition
3. restorePersistedUserAgent() only restored the user agent, not policies
This meant sites in the default browser partition that requested
clipboard-sanitized-write (or any other permission) were denied by
Electron's default behavior, since no handler was registered.
Fix: call setupSessionPolicies(ORCA_BROWSER_PARTITION) in
restorePersistedUserAgent(), which is the startup path that runs after
app is ready. The configuredPartitions guard makes this idempotent.
Also adds a test verifying the default partition gets its session
policies on restore.
Co-authored-by: Orca <help@stably.ai>
* fix(browser): preserve clipboard permissions for browser session
Co-authored-by: Orca <help@stably.ai>
* Initialize browser sessions at app startup
- Move cookie replay and persisted session setup out of renderer IPC wiring
- Install default browser partition policies once per process before webviews load
- Cover startup ordering, retry behavior, permission denial, downloads, and WebAuthn policies
---------
Co-authored-by: Prethish-Complyance <prethish@complyance.io>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Keep open browser webviews mounted while hidden so switching tabs preserves in-page state. Remove the parked-webview lifecycle for open tabs and keep the automation session hardening from the original PR.