Commit Graph
4479 Commits
Author SHA1 Message Date
Brennan BensonandOrca 6213f43016 Wake hibernated agent panes on reveal instead of leaving an inert ghost (#7145)
Co-authored-by: Orca <help@stably.ai>
2026-07-03 14:27:36 -07:00
332490e919 Fix stale GitHub repo avatars after owner changes (#6507)
* Fix stale GitHub repo avatars after owner changes

* Simplify avatar-refresh effect deps (repo covers its fields)

Co-authored-by: Orca <help@stably.ai>

* Preserve known fork identity when live upstream lookup is inconclusive

Co-authored-by: Orca <help@stably.ai>

* Remove dead avatar-icon wrapper; drop no-op update fallbacks

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 14:20:30 -07:00
5124b0d0ad fix(serve): install orca CLI in headless serve so orca claude-teams resolves (takeover of #5766) (#7267)
* fix(serve): install the orca CLI in headless serve mode

In headless serve mode the orca CLI command (~/.local/bin/orca on Linux,
/usr/local/bin/orca on macOS) is never created, so the in-app Claude Team
launcher (orca claude-teams) opened by 'Start new agent' fails with
command-not-found. CliInstaller.install() is only invoked from renderer/desktop
flows (onboarding, Settings 'Install CLI', feature tips) via the cli:install IPC;
headless serve has no renderer. Run the existing idempotent installer on the
serve startup path, best-effort so a failure never blocks serve startup.

Fixes #5763.

* fix(serve): install a bare `orca` dispatcher on Linux for Claude Team

On Linux CliInstaller installs the CLI as `orca-ide` (to avoid shadowing GNOME
Orca's /usr/bin/orca), not bare `orca`. But the Claude Team launcher (`orca
claude-teams`), composed client-side by both the desktop renderer and the
mobile app and written verbatim to the host PTY, invokes bare `orca` — which
is unresolved in the initial managed terminal (no agent-teams shim on PATH
yet). The serve-mode CLI install therefore fixed macOS but not Linux.

Add a bare-`orca` dispatcher in the serve branch (host-side, Linux only) that
execs the bundled CLI wrapper. ~/.local/bin is hardcoded ahead of /usr/bin on
the managed-terminal PATH, so it resolves. Plain file (not a managed symlink)
so CliInstaller.removeLegacyLinuxCommandIfManaged leaves it untouched.

* Restore ai-vault files to origin/main (drop stale pre-0.52 oxfmt merge artifact)

Co-authored-by: Orca <help@stably.ai>

* Harden serve CLI install: AppImage-safe dispatcher, no-prompt macOS, skip Windows, conflict guard

- Gate CliInstaller.install() to macOS+Linux; Windows would only mutate the
  persistent user-registry PATH without helping the current serve's terminals.
- Inject a non-prompting privilegedRunner so headless macOS never pops an
  osascript admin dialog when /usr/local/bin isn't writable (skips instead).
- Linux dispatcher: exec the stable $APPIMAGE via buildAppImageCliWrapper when
  running from an AppImage (resourcesPath is an ephemeral FUSE mount); skip when
  the bundled orca-ide launcher is absent; never clobber a user-owned ~/.local/bin/orca.
- Single-quote the exec target; add coverage for all new branches.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Daniel Rudaev <daniel@d1dx.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 14:12:33 -07:00
cede986d38 fix(browser): restore programmatic focus for CDP text insertion (#7041)
* fix(browser): restore programmatic focus for CDP text insertion

* test(browser): cover the DOM focus replay error path

* fix(browser): serialize DOM.focus replay against pipelined Input.insertText

* refactor(browser): consolidate pending-focus invalidation into one guard

Collapse the three per-handler deletes (Page.bringToFront, Page.captureScreenshot,
catch-all) of the pending DOM.focus replay into a single guarded delete keyed on
'not DOM.focus and not Input.insertText'. States the invariant in one place and
removes the trap where a future early-returning handler forgets to clear the
stale focus. Also clear the map on client teardown and shorten the field comment.

Co-authored-by: Orca <help@stably.ai>

* test(browser): annotate mock webContents return type for portable declaration emit

Co-authored-by: Orca <help@stably.ai>

* fix(browser): drop pending focus replay when the client disconnects mid-flight

Co-authored-by: Orca <help@stably.ai>

* fix(browser): re-check active client after DOM.focus replay round-trip

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 14:12:18 -07:00
3614cbc40c Add default browser action for terminal links (#6129)
* Add terminal link browser context action

* Polish terminal link default-browser action

- Route Open in Default Browser through the shared openHttpLink funnel
  (forceSystemBrowser) so loopback dev-server links get the same
  worktree-label rewrite as shift+click's system-browser path.
- Translate the new menu label in es/ja/ko/zh (was en-only).
- Extract TerminalQuickCommandMenuItem to keep TerminalContextMenu under
  the max-lines lint after adding the link item.
- Hit-test the link only when the menu actually opens (skip on Windows
  right-click copy/paste path).
- Add scheme-safety unit tests (file:/javascript:/smb:/vscode: rejected)
  and a menu-item render/callback test; fix TerminalContextMenu.test
  props for the new required fields.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 14:09:52 -07:00
42de074152 fix(browser): keep isolated profile storage on its partition (#6958)
* fix(browser): keep isolated profile storage on its partition

* fix(browser): keep cloned isolated tabs on their resolved partition

* fix(browser): thread resolved partition through UI profile switches

Keep the isolated-storage invariant universal: UI-initiated profile
switch/create now persist the resolved partition alongside the profile
id, matching the runtime path, so a tab stays on its partition even if
the renderer profile mirror is later stale (issue #6923).

Co-authored-by: Orca <help@stably.ai>

* fix(browser): persist resolved partition through session restore

Add sessionPartition to the workspace-session zod schema so the resolved
partition survives persist->load; without it zod strips the field and a
restored isolated tab whose profile mirror is stale at startup falls back
to the shared default partition, reopening the storage leak (#6923).

Fold the webview teardown branches (parent drift or partition mismatch)
into one and re-resolve the viewport container once, matching the
pre-refactor null-guard behavior.

Split the sleeping-agent parse tests into their own file to keep both
under the 800-line cap.

Co-authored-by: Orca <help@stably.ai>

* fix(browser): keep CLI-created tabs inheriting the default profile

browserTabCreate without an explicit profile was sending sessionProfileId:
null, which the renderer store treats as 'no inheritance' (its guard is
!== undefined). That forced CLI-created tabs onto the shared default
partition even when the user had configured a default browser session
profile, silently changing behavior a #6923 fix should not touch.

Leave sessionProfileId/sessionPartition undefined when no profile is named
so the renderer applies default-profile inheritance; thread the resolved
partition only when a profile is explicitly chosen.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 13:58:40 -07:00
Brennan BensonandOrca 133ebcee5d Update stale mobile Android download links to 0.0.21 (#7262)
Co-authored-by: Orca <help@stably.ai>
2026-07-03 13:42:02 -07:00
97c30c5ccc fix: drop stale repos fetches so deleted projects don't reappear (#7020) (#7024)
* fix: drop stale repos fetches so deleted projects don't reappear

Deleting a project group with "Remove contained projects" could leave the
removed projects as stale, unusable sidebar rows until an app restart (#7020).
`repos:changed` fires once per removal and the renderer starts an unsequenced
repos fetch per event; an earlier fetch that read pre-removal state could
resolve last and overwrite the newer result, reintroducing the deleted repos.

Guard fetchRepos and fetchReposForAllHosts with a monotonic token so a fetch
drops its own result once a newer repos fetch has superseded it — only the
latest fetch, which reads the final persisted state, applies. Add a regression
test that a stale fetch resolving after a newer one can't resurrect a removed
repo.

* test: isolate stale-fetch race in a dedicated file; scope guard to fetchRepos

Move the #7020 regression test out of repos.test.ts into a focused
repos-stale-fetch.test.ts and add a reject-path case (a superseding fetch
that later rejects must still block the older stale fetch). Scope the
monotonic guard to fetchRepos only: the original shared-counter guard on
fetchReposForAllHosts let an unrelated fetchRepos bump the counter and
abort an in-flight all-host load, dropping every host's repos.

Co-authored-by: Orca <help@stably.ai>

* chore: restore origin/main cdp-ws-proxy.test.ts (drop merge artifact)

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 13:40:17 -07:00
2c0be62df6 Fix empty nested import folder fallback (#6719)
* fix: allow empty nested import as folder

* Track open-as-folder recovery action and localize its strings

Completes the empty-nested-import fallback: adds the open_as_folder action to the existing add_repo_nested_import_action funnel (integer counts only, no paths) so adoption of the recovery path is measurable, and lands the five-locale catalog entries the new UI strings require.

Co-authored-by: Orca <help@stably.ai>

* Pin runtime-kind mock return to the literal union in nested import flow test

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 13:38:20 -07:00
Brennan BensonandOrca 700b492b1b Fix main typecheck: pin Buffer<ArrayBuffer> in cdp-ws-proxy mid-print test (#7263)
Co-authored-by: Orca <help@stably.ai>
2026-07-03 13:30:55 -07:00
Parker Rex 02dfb4b334 Fix Discord icon and CreateWorktree label spacing (#6505)
* Fix landing create worktree label

* Update Discord help menu icon
2026-07-03 13:12:14 -07:00
273fee79fa Fix CDP Page.printToPDF support (#7044)
* Fix CDP printToPDF proxy

* Harden CDP PDF stream handling

* Fix PDF margin units

* refactor(cdp): extract printToPDF param mapping + stream store into cdp-print-to-pdf

Move the CDP Page.printToPDF option translation and the ReturnAsStream handle
store out of cdp-ws-proxy into a focused cdp-print-to-pdf module, mirroring the
existing cdp-screenshot sibling. Keeps the over-budget proxy from growing
further and gives the PDF logic direct unit coverage.

No behavior change: all existing proxy tests pass unmodified.

Co-authored-by: Orca <help@stably.ai>

* fix(cdp): drop print result if client disconnected during printToPDF

A ReturnAsStream print that resolved after the requesting client
disconnected (or was replaced) registered its buffer in pdfStreams after
the disconnect's clear() already ran, orphaning a potentially large PDF
until the 5-minute TTL. Re-check isActiveClient after the await, mirroring
navigateWithLifecycle/reloadWithLifecycle.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <foxtrot-eng@stably.ai>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 13:06:43 -07:00
9aeaf0728f Fix git worktree list fallback for older Git (#7235)
* fix git worktree list fallback for localized errors

* Polish worktree -z fallback: clarify comment, add localized + negative tests

Co-authored-by: Orca <help@stably.ai>

* Extend -z fallback to relay/SSH worktree path; tighten comments; add relay tests

Co-authored-by: Orca <help@stably.ai>

* Isolate regex-fallback path in relay test

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: yuqili03 <yuqili03@deeproute.ai>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 12:56:38 -07:00
2153ef9456 Accept any hostname (and optional :port) in manual network address entry (#7223)
* Allow arbitrary hostnames in manual network address entry

parseManualNetworkAddress only accepted an IPv4 address or a Tailscale
MagicDNS (*.ts.net) hostname, so users behind a dynamic residential IP
who rely on a DDNS domain or self-hosted relay had no way to enter it
in the desktop UI short of bypassing validation via DevTools/IPC.

The main process already resolves any host: resolvePairingEndpoint
and parsePairingAddressOverride in src/main/runtime/runtime-rpc.ts
accept an arbitrary hostname and an optional host:port. This change
brings the renderer-side validation in line with what pairing already
supports: any RFC 1123 hostname (a superset that still covers
*.ts.net), optionally suffixed with :port (1-65535). IPv4 validation
is unchanged, including still rejecting malformed dotted-numeric input
instead of silently treating it as an all-digit hostname.

Updates the custom-address dialog copy in NetworkInterfacePicker.tsx
to describe the wider grammar.

* Polish manual-address takeover: fix bare-numeric guard, sync 5 locales, lint

- Require a dot in the IPv4-typo guard so a bare numeric label (`123`)
  validates as a legal RFC 1123 hostname, matching the code's own comment
  and the main-process resolver; add coverage.
- Update en.json + es/ja/ko/zh placeholder/hint to the broadened grammar
  (translate() reads en.json before the TSX fallback, so the copy change
  was previously inert; the other locales described the old ts.net-only rule).
- Replace indexOf(...)!==-1 with includes() to satisfy oxlint.

Co-authored-by: Orca <help@stably.ai>

* Keep validator a strict subset of the backend resolver

Review surfaced two ways the renderer could accept an address the main
process handles differently:
- All-numeric hosts (bare `123` and dotted `256.0.0.1`) are now rejected.
  The WHATWG URL host parser downstream reinterprets a numeric host as IPv4
  (`123` -> `0.0.0.123`), so accepting one would validate an address the
  pairing resolver silently dials as a different host.
- Ports with leading zeros are rejected. `^[0-9]+$` let an arbitrarily long
  zero-padded string past the range check and inflate the returned address
  beyond the hostname length cap that the old whole-string check enforced.

Co-authored-by: Orca <help@stably.ai>

* Reject any numeric final label, not just fully-numeric hosts

WHATWG URL host parsing treats a host whose last label is numeric
(`foo.123`, `foo.0x1`) as an IPv4 signal, so the pairing resolver would
fail to parse it and silently dial a fallback host. Widen the ambiguous-IP
guard to a single last-label check that subsumes the earlier all-numeric
case, keeping the renderer a strict subset of what the backend resolves
correctly. Normal hostnames whose last label merely contains digits
(`host2.example.com`) are unaffected.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 12:52:55 -07:00
492306f223 fix(sidebar): keep independent same-host checkouts of one repo as separate projects (#7237)
* fix(sidebar): keep independent same-host checkouts of one repo as separate projects

Re-regression of #5374: PR #6320 removed the per-host-surface separation
added by #5375, so independent local clones of the same repo (shared origin
=> same github:owner/repo identity) collapse into one sidebar project again.

Restore the surface-key separation in worktree-list-groups.ts, scoped by
ProjectHostSetup.setupMethod: 'provisioned' (ephemeral-VM runtime copies)
still nest under the project header (preserving #6320), while real user
checkouts (legacy-repo / imported-existing-folder / cloned) each get their
own header when duplicated on one host surface.

Revert the two tests #6320 inverted and add coverage for a provisioned copy
nesting alongside a same-host user checkout.

* test(cmd-j): update palette grouping tests for same-host checkout split

The Cmd+J palette shares getProjectGroupingForRepo (via
getProjectHeaderRevealTarget) with the sidebar, so restoring same-host
checkout separation also splits independent `cloned` checkouts into
per-setup palette entries. Update the multi-setup test to assert the split
and add coverage that a `provisioned` runtime copy still nests under one
project key.

* test(sidebar): cover split + provisioned-nest on one host together

Guard the intersection of #5374 and #6320: when a project has two real
same-host user checkouts AND a provisioned copy, the real checkouts each get
their own per-setup header while the provisioned copy stays under the plain
project key (never a path-scoped ::setup: header). Locks the two features'
combined behavior so a future change can't silently regress either half.

* refactor(sidebar): reuse shared Windows-path helper, single-pass surface count

Take-over polish of #7237:
- Use shared isWindowsAbsolutePathLike instead of an inline drive-letter
  regex, deduplicating the pattern and also bucketing UNC \\server\share
  paths as a Windows surface instead of falling through to default.
- Collapse buildProjectGroupingIndex's two passes over projectHostSetups into
  one, computing each surface key once and flagging ambiguous projects from
  the aggregated counts.
- Tighten why-comments to AGENTS.md's two-line rule.

No behavior change to the fix; all 123 sidebar/palette grouping tests pass.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 12:44:34 -07:00
37c8ff4935 fix: block resuming host-stored AI Vault sessions into SSH workspaces (#7130)
* fix: block resuming host-stored AI Vault sessions into SSH workspaces

AI Vault scans session history from this machine's disk only (host home
dirs plus local WSL homes), but since #6685 resume actions accepted any
SSH workspace as a target. Resuming a host-stored session there queues
cd '<local cwd>' && <agent> --resume <id> into a remote shell where
neither the cwd nor the session file exists, so it always fails.

Gate resume targets on where the session file lives: local targets stay
unrestricted, SSH targets now require a WSL-stored session (the
SSH-to-local-WSL setup #6685 was built for). Applies to the sidebar
resume buttons, direct resume, and pane drag-and-drop, with a toast
explaining the host mismatch. Catalog sync also picked up two
pre-existing drifts (missing failedUnnestWorkspace fallback, two
unreferenced SSH-timeout keys).

* i18n: translate host-session SSH-resume block message (es/ja/ko/zh)

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-03 12:44:31 -07:00
1fd9547501 fix(agent-completion): stop PermissionRequest hooks from firing false completion notifications (#6316)
* test(agent-completion): cover done after waiting pause

Co-authored-by: Orca <help@stably.ai>

* test(agent-completion): assert attention fires alongside done-after-waiting

Wire dispatchAttention into the done-after-waiting regression test so it
verifies both halves of the #5698 fix: the mid-turn permission pause
surfaces as attention exactly once, and the later genuine 'done' still
completes exactly once. Matches sibling tests that assert on both paths.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: brennanb2025 <brennankbenson@gmail.com>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-07-03 12:44:28 -07:00
Neil c8e571f40c fix(sidebar): prevent hovercard text selection drags (#7228) 2026-07-03 03:07:17 -07:00
Brennan Benson 653f349b5f Fix terminal theme selection persistence (#7227)
Fixes #7166.
2026-07-03 02:55:27 -07:00
Neil ce680071a2 Place terminal URL tooltip at pane corner (#7221) 2026-07-03 02:15:24 -07:00
Neil a84f737cf7 fix(terminals): restore pane detach tab placement (#7215)
* fix(tabs): restore deferred tab activation so dragging a terminal tab doesn't switch panes mid-gesture

PR #5927 shipped terminal-pane drag (reorder tabs, move a tab into another
pane, edge-split into a new column). It deliberately DEFERRED tab activation
to pointer-up and suppressed it during a drag, so pressing a tab to drag it
never switched the active tab or stole terminal focus mid-gesture.

PR #6395 (d32d62a395) deleted tab-strip-pointer-activation.ts and made
SortableTab/EditorFileTab/BrowserTab activate eagerly on pointerdown — fixing
click-to-switch-after-reorder but regressing the drag: grabbing a tab now
flips the active tab + focused pane and yanks xterm keyboard focus before the
drag is even recognized (aggravated by PR #6210 raising the dnd-kit threshold
5px->12px). The move itself still lands, but the gesture feels broken.

Restore the deferred-activation hook, but gate it on measured pointer
DISPLACEMENT instead of the drag-active context ref the old hook used — that
ref clears asynchronously relative to the drop's pointerup, which is exactly
what made #6395's click-after-reorder misfire. Displacement mirrors dnd-kit's
own activation threshold: a release within TAB_DRAG_ACTIVATION_DISTANCE_PX is
a click (activate); crossing it is a drag (suppress). Because each press
measures its own gesture, a click after a reorder always activates.

- Recreate src/renderer/src/components/tab-bar/tab-strip-pointer-activation.ts
  (displacement-gated) + unit tests, incl. an explicit #6395 regression case.
- Rewire onPointerDown in SortableTab, EditorFileTab, BrowserTab to use it.
- BrowserTab.test.tsx shallow-renders via mocked React hooks; add useRef/
  useCallback stubs so the new hook works under that harness.

Verified end-to-end in a dev build via CDP: pressing a tab no longer
activates/steals focus on pointerdown; a click still activates on release;
dragging a tab into another pane still moves it; clicking tabs after a drag
still switches (the #6395 guard in tests/e2e/tabs.spec.ts stays green because
it uses zero-displacement clicks). 233 unit tests pass; oxlint + renderer
typecheck clean.

* fix: restore pane detach tab placement
2026-07-03 01:45:15 -07:00
Neil 7c9059c4d4 Restore desktop terminal URL modifier clicks
Restore desktop terminal URL and OSC link activation to require Cmd/Ctrl while preserving mobile tap routing.
2026-07-03 01:32:22 -07:00
Dvitash 0ff2c09002 Fix typed OMP remote title flicker (#6954) 2026-07-03 00:26:37 -07:00
Neil f1bcb77392 fix: parse Claude Fable current-week usage
Claude Code 2.1.199 renders the Fable plan bucket as Current week (Fable), while Orca only parsed a standalone Fable heading. Accept weekly-style Fable headings as the distinct Fable weekly meter while keeping broader Fable-weekly copy as a section boundary to avoid false positives.

Validation:
- pnpm exec vitest run --config config/vitest.config.ts src/main/rate-limits/claude-pty.test.ts src/main/rate-limits/claude-fetcher.test.ts src/main/rate-limits/service.test.ts src/renderer/src/components/status-bar/tooltip.test.ts src/renderer/src/components/status-bar/inline-usage-bars.test.tsx
- pnpm run typecheck
- pnpm exec oxlint src/main/rate-limits/claude-pty.ts src/main/rate-limits/claude-pty.test.ts src/main/rate-limits/claude-fetcher.ts src/main/rate-limits/claude-fetcher.test.ts src/main/rate-limits/service.ts src/main/rate-limits/service.test.ts src/renderer/src/components/status-bar/tooltip.test.ts src/renderer/src/components/status-bar/inline-usage-bars.test.tsx
- git diff --check HEAD~1..HEAD
- live local Claude fetcher returned fableWeekly: 62
2026-07-03 00:16:19 -07:00
Jinwoo HongandOrca 10e8f86899 Coalesce PTY input write bursts (#7205)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 23:43:35 -07:00
Mark Xian 2848c5daf4 Fix rename inputs committing on CJK IME Enter confirmation (#6980)
Fixes #6980.
2026-07-02 23:37:12 -07:00
Rod Boev 09fc57e113 fix(browser): keep CDP reload from closing Orca browser tabs
Fix the per-tab CDP proxy reload path so raw Page.reload keeps the Orca browser tab alive. Lifecycle priming is bounded and root reloads use the same safer webContents reload behavior as Orca's own browser reload path.
2026-07-02 23:24:24 -07:00
NeilandOrca fa94065a81 Recover exported terminal handles from live PTYs (#7162)
* Recover exported terminal handles from live PTYs

* Guard terminal-handle adoption: first-wins, no collisions

Discovery adoption of ORCA_TERMINAL_HANDLE is now skipped when the pty
already has a handle bound this session (re-keying would strand waiters
registered under the old handle) or when the reported handle is already
bound to a different pty (provider-reported values are not trusted to be
collision-free). Also adds the relay why-comment and PtyProcessSummary
type alias from review feedback.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-02 23:06:32 -07:00
Brennan BensonandOrca d65c938529 Keep runtime mirror sized with desktop terminal resizes (#7192)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 22:42:49 -07:00
Neil 0fd2d67c69 Allow manual sorting of Project Groups (#7191) 2026-07-02 22:23:18 -07:00
Neil b523c5311f fix: show Claude Fable usage in account switcher
Show Fable usage in inactive Claude account switcher previews by supplementing OAuth usage with scoped Claude CLI /usage data, with macOS scoped Keychain safety checks and compact preview layout coverage.

Validation:
- pnpm exec vitest run --config config/vitest.config.ts src/main/rate-limits/claude-fetcher.test.ts src/main/rate-limits/service.test.ts src/renderer/src/components/status-bar/inline-usage-bars.test.tsx src/renderer/src/components/status-bar/tooltip.test.ts
- pnpm run typecheck
- pnpm exec oxlint src/main/rate-limits/claude-fetcher.ts src/main/rate-limits/claude-fetcher.test.ts src/main/rate-limits/service.ts src/main/rate-limits/service.test.ts src/renderer/src/components/status-bar/StatusBar.tsx src/renderer/src/components/status-bar/inline-usage-bars.test.tsx
- git diff --check HEAD~1..HEAD
2026-07-02 22:18:12 -07:00
NeilandOrca 4caea00f16 Skip the synchronous cold-restore replay for live daemon sessions in doSpawn (#7105)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 22:04:05 -07:00
Neil 185b768609 Add rich Markdown spellcheck setting (#7103) 2026-07-02 21:59:41 -07:00
NeilandOrca 4c4cbf2d76 Fix Vim alternate-screen terminal redraw recovery (#7142)
* Fix Vim alternate-screen terminal redraw recovery

* Decide alternate-screen atlas recovery from parsed buffer state

Replace the raw-chunk scan for alternate-screen enter sequences with the
xterm parser's own verdict: in-place rewrite chunks check
buffer.active.type (plus a parse-time buffer-switch count) inside the
write callback, where the buffer is authoritative. Covers enter/exit
sequences split across PTY chunk boundaries and full enter-exit cycles
coalesced into one write, and deletes the hand-rolled CSI parser.

Adds regression tests from a real captured vim session (including a
CSI sequence split at a 1024-byte PTY read boundary) and a contract
pin against the real @xterm/headless parser.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-02 21:59:17 -07:00
Jinwoo HongandOrca 827d2bb6aa Refine TUI wheel scroll feel (#7179)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 21:27:16 -07:00
Brennan BensonandOrca 3e4ace0562 Fix Codex pane output tearing after app occlusion (#7173)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 21:00:03 -07:00
Brennan BensonandNeil 0ea354d454 Keep terminals responsive under agent output load (#7139)
Co-authored-by: Neil <neil@stably.ai>
2026-07-02 20:39:49 -07:00
Brennan Benson 087ad66aa2 Revert "Ship serve-sim camera dylib as data and materialize it at runtime" (#7172) 2026-07-02 18:46:00 -07:00
Brennan BensonandOrca f44cb3059b Ship serve-sim camera dylib as data and materialize it at runtime (#7168)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 18:24:23 -07:00
Brennan BensonandOrca c06507ee30 Open terminal file links on mobile (#7134)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 18:17:47 -07:00
dbd53ebb63 fix(emulator): recycle iOS simulators that wedge-boot without a display framebuffer (#7065)
* fix(emulator): recycle iOS simulators that wedge-boot without a display framebuffer

CoreSimulator can report a device Booted while its display IO ports never
came up (HID alive, no com.apple.framebuffer.display port), so
ensureSimulatorBooted passes and serve-sim --detach dies with 'No
framebuffer display descriptor found'. Reconnecting hits the same Booted
early-return, so the pane could never recover without a manual
simctl shutdown/boot.

startSession now recognizes that helper failure signature, recycles the
device once (shutdown + boot), and retries; if the display still fails to
come up it surfaces an actionable erase/recreate message instead of the
raw helper log dump.

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

* review: harden simulator framebuffer recovery

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-02 18:13:33 -07:00
Brennan BensonandOrca 11ca4955ae Run the repo's Custom GitHub Issue Command when starting a workspace from an issue (#6827)
Co-authored-by: Orca <help@stably.ai>
2026-07-02 18:09:14 -07:00
Jinwoo Hong 78d3a37b90 Revert WebGL context retention (#7169) 2026-07-02 17:55:37 -07:00
Neil 8e8a08ac7c fix: supplement Claude Fable usage from CLI (#7167) 2026-07-02 17:45:15 -07:00
Brennan BensonandNeil 99bc693cd5 Fix Codex config paths in managed runtime home (#7157)
* Fix mirrored Codex relative config paths

Orca mirrors ~/.codex/config.toml into a managed CODEX_HOME before launching Codex. Relative path-valued Codex settings were then resolved from the runtime home instead of the user's real Codex home, which made config loading fail in Orca while the same CLI worked in a normal terminal. Rewrite known relative path settings to absolute paths rooted at the system Codex home while preserving runtime-owned trust sections.

* Dedupe Codex TOML line scanner and include path rewrite in CLI tsconfig

* Harden Codex config path rewrite and cover managed account homes

- Track multiline arrays in the shared TOML line scanner so array lines
  are never mistaken for table headers or path keys
- Escape control characters and reject lone-surrogate unicode escapes so
  the rewritten runtime config always stays valid TOML
- Extend the rewrite allowlist with profiles.* file settings and
  debug.config_lockfile.* (both can abort Codex config loading)
- Rewrite relative paths when mirroring the canonical config into
  managed account homes (codex login CODEX_HOMEs), anchoring WSL
  accounts to the Linux-side ~/.codex with posix join semantics

---------

Co-authored-by: Neil <neil@stably.ai>
2026-07-02 17:01:41 -07:00
gatsby74 5da41d4ed6 [codex] Add file explorer open in terminal
Add an Open in Terminal action for file-explorer directories and preserve terminal startup cwd through restore/session paths.
2026-07-02 16:47:38 -07:00
Eren Çakar 801effa68e fix(claude): use Git Bash-safe hook fast path
Fixes #7116.

Use a forward-slash bare .cmd path for Claude/OpenClaude Windows hooks when the managed script path is Git-Bash-safe, avoiding the per-hook PowerShell startup overhead in the common case. Unsafe paths with spaces or shell metacharacters continue to use the encoded PowerShell launcher from #6078.

Keep Codex on its cmd.exe-safe fast path and leave the other agent integrations on the hardened encoded launcher.

Co-authored-by: Eren Çakar <hey@erencakar.com>
2026-07-02 15:42:01 -07:00
Jinwoo Hong 2ce9314acb Improve Windows terminal performance: retain WebGL contexts, warm first ConPTY (#7085) 2026-07-02 18:41:23 -04:00
Brennan Benson e44daf37a3 Match main terminal mirror character widths to the renderer (#7148) 2026-07-02 14:50:15 -07:00
Brandon Barker e6ca3087c5 perf(ssh): resolve node path concurrently with remote install state (#6952)
Run independent SSH relay bootstrap probes concurrently when the connection can safely support overlapping execs. Preserve the old sequential path for system SSH without reusable ControlMaster and for remotes that reject concurrent session channels.
2026-07-02 13:55:36 -07:00