Commit Graph

101 Commits

Author SHA1 Message Date
Brennan Benson 84e9ee964b
Persist Source Control view mode (#2153)
Co-authored-by: Orca <help@stably.ai>
2026-05-17 22:26:49 -07:00
Jinjing e957b86197
Add configurable Open In applications (#2110)
* feat: add configurable Open In menu

Implements configurable Open In applications in worktree context menus with persisted settings, preload/API wiring, and renderer controls/tests.\n\nDesign doc: docs/configurable-open-in-menu.md

* fix: address review findings
2026-05-16 15:34:40 -07:00
Jinjing 087f1aa9bf
fix(worktree): preflight delete before terminal teardown (#2103)
Implement delete preflight checks before PTY teardown across git/runtime/ipc flows.

Design reference: docs/worktree-delete-preflight.md
2026-05-16 13:52:59 -07:00
Neil 675b1b0cb6
Fix Windows agent hook Unicode prompts (#2100) 2026-05-16 13:32:23 -07:00
Diego Lorente del Castillo 2ad01ead7d
feat(file-explorer): show gitignored files with dimmed italic decoration (#1941)
* feat(file-explorer): show gitignored files with dimmed italic decoration

Surfaces `.gitignore`d files in the right-sidebar file explorer with an
italicised, dimmed filename and a CircleSlash icon in the same trailing
slot used by the git status letter. A tracked change always wins — the
ignored decoration only applies when no other git status is present.

Gated behind a new `showGitIgnoredFiles` global setting (default on) so
heavy SSH workspaces can keep the smaller payload by skipping
`--ignored=matching` on `git status`.

`ignoredPaths` lives as a peer field on GitStatusResult rather than an
extension of GitFileStatus/GitStagingArea, so Source Control's
staging-area grouping is untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(file-explorer): trim redundant comments from gitignored decoration

Removes duplicated "Why:" explanations that ended up restating the same
backward-compat rationale across five files (relay, ssh provider, runtime
git commands, RPC handler, renderer git client) plus a few comments that
narrated the mechanism the code already shows.

Net: -39 lines of comment across 10 files; no behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(file-explorer): drop remaining comments from gitignored decoration

The code reads well without them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* review: harden gitignored file decorations

- clear ignored decoration cache when ignored status is disabled or omitted
- keep ignored decoration state scoped across worktree and runtime cleanup
- add coverage for local, SSH, runtime, relay, and Explorer precedence

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-05-15 18:58:08 -07:00
Jinjing df44d8aff1
chore: ignore ephemeral docs (#2004) 2026-05-15 18:09:21 -07:00
Neil e7f3bb6034
Add Grok agent support 2026-05-15 13:52:39 -07:00
Jinwoo Hong 6c4bcf7ea6
feat(ssh): make remote workspaces first-class (#1876)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 12:32:07 -07:00
Prateek Rungta e42c78107c
Mobile: replace presence-lock banner with loud overlay + collapsible chip (#1899)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
2026-05-15 11:47:13 -07:00
Jinjing b8d6698950
fix: make right sidebar header draggable (#1950) 2026-05-15 11:44:52 -07:00
Jinjing cc0272e5c4
chore: remove open editor design doc (#1938) 2026-05-15 11:11:13 -07:00
Jinjing 35e13a04b1
Add worktree Open in editor button (#1929)
* Add worktree open-in editor button

Implements the Open in menu flow from docs/open-in-worktree-button.md, including shell IPC validation and sidebar menu integration.

* Move worktree open action into menu

Updates the design to remove the card button and show VS Code under a single Open in context-menu item.

* Shorten worktree file manager labels
2026-05-15 11:05:21 -07:00
Jinjing 39b8c5026a
docs: add Korean README (#1905) 2026-05-15 00:20:13 -07:00
Neil 2c7da06b2a
Revert "Scaffold iOS companion control architecture" (#1858) 2026-05-14 13:02:27 -07:00
Ramzi cf6867aa6b
Scaffold iOS companion control architecture (#1252) 2026-05-14 12:47:26 -07:00
Jinwoo Hong 5b24ae4198
Fix Claude scoped Keychain auth (#1735)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 10:48:46 -07:00
Neil a2ae62fccd
Rename mobile README showcase asset
Rename the mobile companion showcase files to ensure GitHub renders the updated background asset.
2026-05-13 18:36:09 -07:00
Neil 58e5e5dc19
Polish mobile README showcase
Update the mobile companion README copy, download text, translations, and showcase media.
2026-05-13 18:28:36 -07:00
Neil c713c81eb3
Rename showcase tile to Native Search
Rename Keyboard Native to Native Search in README showcase and translations.
2026-05-13 18:16:57 -07:00
Neil 915e177783
Add Linear and mobile README showcase
Add Linear to the README feature showcase, add mobile companion download links, and update translated READMEs.
2026-05-13 18:12:54 -07:00
Neil e68468d403
Update usage tracking showcase title
Rename the showcase tile to Account Switcher & Usage Tracking and update translated README labels.
2026-05-13 15:37:25 -07:00
Neil 39f0779da7
Improve README feature showcase
Add a responsive GIF-first feature showcase to README files and update translations.
2026-05-13 15:18:55 -07:00
Jinjing c8d97f3b98
fix: include gitignored files in quick open (#1762) 2026-05-13 14:29:30 -07:00
Jinjing 6782823a90 docs: add agent statuses section to READMEs
Co-authored-by: Orca <help@stably.ai>
2026-05-12 01:18:27 -07:00
Jinjing 6616aa1577
chore: remove local-only design doc from repo (#1689)
docs/manual-repo-reorder.md is a planning doc that should not have
been checked in; .gitignore now broadly excludes docs/*.md.

Co-authored-by: Orca <help@stably.ai>
2026-05-10 23:18:30 -07:00
Jinjing 648f207281
feat(checks-panel): auto-refresh on entering Checks tab (#1688)
Force a freshness check each time the user enters the Checks tab
(open sidebar, switch to Checks tab, or switch active worktree/branch)
so stale PR metadata, cached-null "no PR" results, stale checks, and
stale comments are surfaced immediately rather than waiting for the
cache TTL.

- Extracts entry-refresh logic into `checks-entry-refresh.ts` with a
  30 s grace window to suppress rapid show/hide duplicate fetches.
- Adds a `shouldEntryRefresh` effect in `ChecksPanel` keyed by
  `activeWorktreeId::repo.path::branch`; resets on panel hide so
  close-and-reopen re-evaluates freshness.
- Fixes a stale-closure bug in `handleRefresh`: `fetchPRChecks` is now
  called directly with the freshly resolved `headSha` after PR refresh
  instead of reusing the pre-refresh closure's captured sha.
- Adds 11 unit tests in `checks-entry-refresh.test.ts`.
- Design doc: `docs/refresh-on-checks-tab.md`.

Co-authored-by: Orca <help@stably.ai>
2026-05-10 23:16:41 -07:00
Jinjing cbf99a1c98
feat(sidebar): allow manual drag-and-drop reordering of repos (#1686)
* feat(sidebar): allow manual drag-and-drop reordering of repos

Users can now drag repo headers in the sidebar to reorder them. The
custom order is persisted to disk and survives restarts. Includes
design doc at docs/manual-repo-reorder.md.

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

* fix: scope post-drag click swallow to dragged repo header

Avoid silently eating unrelated clicks if one races between pointerup and
the failsafe teardown.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-10 23:07:28 -07:00
Jinjing 908bc18234
feat(sidebar-filter): replace dropdown with searchable popover for repo filtering (#1684)
Replaces the DropdownMenu-based repo filter with a Command/Popover combo that
supports live search, All/None bulk actions, and a Clear all footer. Scales
to large repo sets without scroll friction. Design doc added at
docs/sidebar-filter-redesign.md.

Co-authored-by: Orca <help@stably.ai>
2026-05-10 21:47:15 -07:00
Jinjing b501a6faa0
fix(github-drawer): eliminate reopen flash via useSyncExternalStore (#1680)
Replace the setState-driven data flow with useSyncExternalStore so the
drawer reads cached work-item details synchronously on first render.
Warm reopens now paint the cached content immediately with zero blank
flash. Adds a pub/sub layer (subscribeWorkItemDetailsCache /
notifyWorkItemDetailsCache) to all cache-write paths so React is
notified on every touch or invalidation. Includes design doc at
docs/gh-work-item-drawer-cache-flash.md.

Co-authored-by: Orca <help@stably.ai>
2026-05-10 19:53:05 -07:00
Jinjing ace7db218d
perf(github-drawer): cache work-item details + collapse issue fetch (#1655)
Reopening a GitHub issue/PR drawer paid full IPC + `gh` startup latency on
every open. Two changes here:

1. Module-level SWR cache in GitHubItemDialog.tsx keyed by
   (repoPath, issueSourcePreference, type, number). Reopening within 30s
   paints cached data instantly; older entries paint stale-then-refresh.
   Concurrent opens dedupe on a shared in-flight promise. Mutation
   handlers invalidate by (repo, type, number); a cache-generation
   counter prevents in-flight refetches from resurrecting stale data
   after a mid-flight invalidation.

2. Collapsed GraphQL query for issue details replaces 3 serial `gh`
   subprocesses (REST issue + REST comments + GraphQL participants) with
   one round-trip. Falls back to the legacy fan-out on any GraphQL error
   so historical contract is preserved.

Cross-window invalidation rides a new `gh:workItemMutated` IPC broadcast
that skips the originating sender (the source already updated its cache
optimistically — re-broadcasting would race the optimistic write).
`addIssueComment` now takes a `type` so the broadcast scopes correctly
when a PR shares its number with an issue.

Co-authored-by: Orca <help@stably.ai>
2026-05-09 23:46:30 -07:00
Neil 4e8be92c84
Revert "fix(skills): remove broken doc references in orca-cli SKILL.md" (#1638) 2026-05-09 18:03:59 -07:00
xiaolai f22d046160
fix(skills): remove broken doc references in orca-cli SKILL.md (#973)
* fix(skills): remove broken doc references in orca-cli SKILL.md

Three files listed under ## References do not exist in the repository:
docs/orca-cli-focused-v1-status.md, docs/orca-cli-v1-spec.md, and
docs/orca-runtime-layer-design.md. Agents following the skill would hit
dead links when trying to resolve ambiguous CLI behavior. Replace the
stale list with a general pointer to the docs/ directory.

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

* docs: remove stale Orca CLI doc index

---------

Co-authored-by: claude[bot] <claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-05-09 17:58:49 -07:00
Neil 5eb5043344
Move STYLEGUIDE.md into docs/ (#1625)
Co-authored-by: Orca <help@stably.ai>
2026-05-09 01:08:35 -07:00
Cristian Lopez 83b3369ea5
fix: Support Codex pet sidekick animations (#1533)
* Support Codex pet sidekick animations

* Refine Codex pet defaults and drop unused failed animation state

Always default spritesheetPath to spritesheet.webp when a manifest
omits it, even when explicit frame/animation metadata is present, so
non-Codex bundles still benefit from the standard sheet name.

Drop the 'failed' animation entirely — Orca has no failure state, so
mapping interrupted completions to 'failed' would conflate user
cancellation with agent failure. Codex spritesheets can still expose
a 'failed' row as an asset contract, but it's never selected at runtime.

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

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-05-07 23:50:20 -07:00
Jinwoo Hong e83d92eede
Mobile: server-authoritative phone-fit state machine + race fixes + UX cleanup (#1518)
Co-authored-by: Orca <help@stably.ai>
2026-05-06 21:54:23 -07:00
Jinwoo Hong 087c00b02e
Mobile: stabilise connection + terminal-fit fixes + share one RpcClient per host (#1481)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 18:58:13 -07:00
Brennan Benson 6f2e31afad
feat(telemetry): PR 4 — wire 7 core events to call sites (#1433)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:57:51 -07:00
Jinwoo Hong 705be9e312
feat(status-bar): consolidate memory + sessions into Resource Usage segment (#1415)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:38:18 -07:00
Jinjing 5ce9c3b481
feat(tasks): remember tasks page resume state across sessions (#1442)
Persist transient Tasks page position (GitHub mode, active preset/query,
Linear preset/query) in PersistedUIState so reopening Tasks restores the
user's working context instead of falling back to defaults. Source, repo
selection, team selection, and active project keep using their existing
settings paths.

Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:19:50 -07:00
Neil 479f5c488d chore: move Autohand Code listing after Auggie in READMEs and agent catalog
Co-authored-by: Orca <help@stably.ai>
2026-05-05 00:27:36 -07:00
Igor Costa 38b77afb8d
Add Autohand Code agent support (#1382) 2026-05-05 00:25:37 -07:00
Jinwoo Hong d1b26e2eb7
Mobile improvements: scrollback hydration, keyboard layout, and worktree-creation polish (#1423)
Co-authored-by: Orca <help@stably.ai>
2026-05-04 23:24:22 -07:00
Jinjing 56b69f8d8f
docs: remove stale design docs (#1425)
Co-authored-by: Orca <help@stably.ai>
2026-05-04 23:05:05 -07:00
Neil 9f1ccf44d0
fix(readme): correct Kimi CLI link and swap Anthropic favicon for Claude glyph (#1405)
Co-authored-by: Orca <help@stably.ai>
2026-05-04 13:21:56 -07:00
Neil e7619b7334
fix(readme): replace Droid favicon with local black-bg SVG (#1404)
Co-authored-by: Orca <help@stably.ai>
2026-05-04 13:11:24 -07:00
Jinwoo Hong fc578f5ea9
feat(mobile): Expo companion app [beta] (#1245)
Co-authored-by: Orca <help@stably.ai>
2026-05-04 13:08:27 -07:00
Jinjing 375a3e6351
feat(sidebar): path-aware filter in SSH remote file browser (#1384)
Typing a path like `Documents/orca-internal` in the browse filter now resolves the path on the remote instead of producing "No matches". Supports `~`, absolute, and relative paths with live preview and Enter to navigate.

Co-authored-by: Orca <help@stably.ai>
2026-05-04 00:01:04 -07:00
Jinjing fd6abb5808
fix(cmd-j): rank empty-query worktrees by focus recency (#1383)
* fix(cmd-j): rank empty-query worktrees by focus recency

Persist a per-worktree focus-recency timestamp and use it as the primary
ordering signal for Cmd+J's empty-query Worktrees section, so SSH and
other quiet worktrees surface based on user focus rather than background
activity. See docs/cmd-j-empty-query-ordering.md.

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

* fix(tests): guard lastVisitedAtByWorktreeId and mock markWorktreeVisited

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-03 22:55:11 -07:00
Jinwoo Hong a638215729
fix(pty): release ptmx fd on natural exit + defuse SIGHUP-to-recycled-pid (#1327)
* fix(pty): release ptmx fd on natural exit + defuse SIGHUP-to-recycled-pid

Daemons accumulated ptmx fds over time because node-pty's UnixTerminal
only releases the master fd when destroy() runs. On the natural-exit
path (the common case — user closes a tab, shell runs `exit`) nothing
ever calls destroy(), so the fd leaks until GC. On macOS this
eventually hits kern.tty.ptmx_max=511 and all new terminals fail to
spawn.

Fix: release the fd synchronously on every teardown path (natural
exit, explicit kill, stale SSH spawn, daemon shutdown) and close the
concurrent SIGHUP-to-recycled-pid hazard inside node-pty's
UnixTerminal.destroy().

- src/main/daemon/pty-subprocess.ts: synchronous POSIX proc.kill
  neutralization inside proc.onExit; dead guards on forceKill/signal
  so they never target a reaped-and-possibly-recycled pid
- src/main/daemon/session.ts: new disposeSubprocess() for already-
  exited sessions (fd release only, no SIGKILL) — avoids sending
  SIGKILL to a recycled pid during daemon shutdown
- src/main/daemon/terminal-host.ts: dispose loop routes on isAlive —
  live sessions get forceKillAndDisposeSubprocess (SIGKILL + fd
  release), exited sessions get disposeSubprocess (fd release only)
- src/main/providers/local-pty-provider.ts: same POSIX kill
  neutralization at top of onExit for the legacy local path
- src/relay/pty-handler.ts: same neutralization in wireAndStore;
  disposed flag guards all public entry points; dispose() uses
  SIGKILL (not SIGTERM) before destroy since the relay is exiting;
  killTimer fallback + immediate-shutdown + stale-spawn cleanup all
  call disposeManagedPty + ptys.delete so wedged children (D-state,
  bad NFS) can't leak map entries against the 50-PTY cap

Windows is exempt everywhere — WindowsTerminal.destroy IS a kill()
call internally (closes the ConPTY agent), so neutralizing would
turn destroy into a no-op and leak the agent.

See docs/fix-pty-fd-leak.md for the full design.

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

* fix(pty): patch node-pty native off-by-one leaking /dev/ptmx per spawn

node-pty 1.1.0's pty_posix_spawn on macOS walks low_fds[0..2] in an
allocation loop that breaks at the first fd >= STDERR_FILENO, then
cleans up via `for (; count > 0; count--) close(low_fds[count])`. In
the typical case (break at count=0) the cleanup body never runs and
low_fds[0] — a /dev/ptmx handle — leaks per spawn. Fixed upstream in
microsoft/node-pty af053f2 (PR #882), not in any 1.1.0 release.

Backport the 3-line cleanup-loop fix as a pnpm patch. E2E validated
against a dev daemon: 200 spawn/kill cycles kept the daemon's ptmx
fd count flat at baseline; prior runs reproduced linear 1-per-spawn
growth. Also documents the native root cause as a status addendum in
docs/fix-pty-fd-leak.md — the JS-side destroy() discipline previously
landed is still load-bearing for the SIGHUP-to-recycled-pid hazard and
for synchronous fd release on daemon shutdown.

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

* fix(pty): capture stable kill spy ref in pty.test.ts

destroyPtyProcess reassigns proc.kill = () => {} on POSIX to defuse
the SIGHUP-to-recycled-pid hazard (see docs/fix-pty-fd-leak.md). After
that reassignment, proc.kill.mock is undefined and the assertions
crashed in CI. Capture a stable reference to the vi.fn() before it
gets reassigned.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-02 23:12:14 -07:00
Jinwoo Hong 827b84d27a
fix(runtime): add single-instance lock + owned-metadata clear (#1312) (#1326)
* fix(runtime): add single-instance lock + owned-metadata clear to prevent orca-runtime.json corruption

Closes #1312.

Every AppImage/.app relaunch was booting a fresh Electron main that clobbered
`<userData>/orca-runtime.json` and `agent-hooks/endpoint.env`. When the newest
instance quit, metadata pointed at a dead pid and `orca status` reported
`stale_bootstrap` even though the original Orca was still running. SIGKILL'd
predecessors also left orphaned `o-<pid>-*.sock` files in userData.

Three surgical changes:

1. `app.requestSingleInstanceLock()` in a new
   `src/main/startup/single-instance-lock.ts` helper, wired into
   `src/main/index.ts` after `configureDevUserDataPath(is.dev)` so dev and
   packaged runs lock in separate namespaces. Losing instances focus the
   primary's window via `second-instance` and quit without touching userData.

2. `clearRuntimeMetadataIfOwned(userData, pid, runtimeId)` in
   `runtime-metadata.ts` — compares both pid AND runtimeId against the
   current file before clearing, so the auto-updater handoff window never
   erases the replacement process's fresh bootstrap. Called from a rewritten
   `will-quit` handler that folds `runtimeRpc.stop()` + owned-clear into the
   same `Promise.allSettled([disconnectDaemon, …]).then(app.quit)` chain
   (inside the `!daemonDisconnectDone` guard so the second-pass re-entry
   can't re-invoke stop+clear).

3. `sweepOrphanedRuntimeSockets()` in `runtime-rpc.ts` runs at the top of
   `start()` on POSIX, using `process.kill(pid, 0)` to probe liveness and
   remove `o-<dead-pid>-*.sock` orphans left by SIGKILL/OOM-kill.

Tests (37 new/updated):
- `single-instance-lock.test.ts` (3): lock-failed does not register listener;
  lock-acquired registers exactly one; callback dispatches correctly.
- `runtime-metadata.test.ts` (+4): clearRuntimeMetadataIfOwned matched /
  pid-mismatch / runtimeId-mismatch / no-file branches.
- `runtime-socket-sweep.test.ts` (4): own-pid-skip / alive-retain /
  dead-sweep / regex-miss separated via synthetic ownPid=1; two
  regex-invariant tests assert the sweep regex matches the real
  `createRuntimeTransportMetadata` output (including the 'rt' fallback).

Design doc: `docs/fix-missing-single-instance-lock.md`.

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

* fix(runtime): focus hidden windows on second-instance event

focus() alone is a silent no-op when the primary window is hidden
(close-to-tray on macOS via Cmd+W, or on a different macOS Space) or
behind other apps on Windows. Call show() before focus() so a second
launch attempt reliably surfaces the existing window regardless of
state.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-02 23:05:14 -07:00