Git can execute inside a WSL distro against a raw Linux worktree path while Node, on the Windows side, reads the same files back through Win32. `path.join( '/home/me/repo/feature', 'src/file.ts')` on win32 produces the drive-relative `\home\me\repo\feature\src\file.ts`, which resolves against whatever the current drive happens to be and almost always ENOENTs. The same mis-spelling hits the drvfs form, where `/mnt/c/repo` should read as `C:\repo`. Two consequences, both on the Node side only (git already works, because it gets the Linux path as its cwd and resolves it inside the distro): - getDiff's unstaged working-tree read missed, `readWorkingTreeFile` mapped ENOENT to `exists: false`, and an existing file rendered as DELETED in the diff view. - `readWorktreeDiffStamp` could not find `.git`, so the stamp was null, the settled diff cache neither hit nor stored, and every diff respawned `git show` - two `wsl.exe` spawns the cache exists specifically to avoid. Both now spell the worktree directory for the reading host first, via a new `resolveWorktreeHostPath` wrapper around the resolver that landed in #17804. The wrapper exists because `resolveGitMetadataPath` trims: a gitfile payload carries a trailing newline, but a directory name may legally begin or end with whitespace on POSIX, so the wrapper keeps the caller's spelling whenever the resolver only trimmed it. The stamp's opaque `value` still embeds the caller's original `worktreePath`, so settled-cache identity is byte-identical and no cache key moves. `readWorktreeDiffStamp` was already `Promise<WorktreeDiffStamp | null>` with one caller that treats null as a cache miss, so no new nullability enters the type system and the resolver's never-null-for-a-non-empty-pointer contract is untouched. The only unspellable input is an empty worktree path, handled locally as "not provably unchanged" in the stamp and as a read *failure* (not a proven deletion) in file-diff. What changes for users | Platform | Delta | |---|---| | macOS | No change. An absolute POSIX path is returned verbatim, including one whose directory name carries leading or trailing whitespace. | | Linux | No change. Same reason. | | Native Windows (no WSL) | No change. A `C:\...` or `\\server\share\...` path is already absolute for win32 and passes through verbatim. | | Windows + WSL, UNC worktree path (`\\wsl.localhost\Ubuntu\...`) | No change. Already absolute for win32; passes through verbatim. This is today's common case. | | Windows + WSL, drvfs worktree path (`/mnt/c/repo`) | Fixed. Reads as `C:\repo` instead of the drive-relative `\mnt\c\repo`. Needs no distro name. | | Windows + WSL, Linux worktree path with a named distro (`/home/me/repo`) | Fixed. Reads as `\\wsl.localhost\Ubuntu\home\me\repo`. The deleted-file misrender goes away and the diff cache starts hitting. | | Windows, POSIX path, no distro and not a drvfs mount | No change. Passes through verbatim, same ENOENT, same existing fallback. | | SSH | No change. `runtime-git-diff-commands.ts` and the `git:diff` IPC both route to `provider.getDiff` for a connection, so this local code is never reached. | | Relay / remote | No change. No RPC param, wire field, stream opcode, or published content is touched; the relay host runs the same local code and gets the same fix. | | Folder workspace (non-git) | No change. `.git` is absent either way, `resolveGitDir` returns the same fallback, and the stamp stays null exactly as today. | | GitLab / other providers | Not applicable. No provider-specific or review code is touched. | What this does NOT do - It does not fix `resolveGitDir` itself. For a drvfs repo whose worktree Orca already spells `C:\repo\feature`, the gitfile payload `gitdir: /mnt/c/repo/.git/ worktrees/feature` is still mis-resolved by `path.resolve` to `C:\mnt\c\repo\.git\...`, so the stamp still returns null in that shape. Separate change, separate PR; this one neither fixes nor regresses it. - It does not touch submodule path resolution. `resolveSubmoduleWorktreePath` is the path-escape guard and has a near-identical twin in the relay; changing it without escape tests on both is out of scope. - It does not change `readHeadComponent`'s `commondir` resolution. The relative `../..` git actually writes takes the identical `path.resolve` branch, and an absolute POSIX `commondir` under a WSL UNC `gitDir` already resolves correctly because the UNC root is `\\wsl.localhost\<distro>\`. - It does not reorder drvfs-before-UNC inside the shared resolver. That changes the identity of returned strings and needs a real Windows+WSL box. - It does not add any Git command, option, or version dependency. Costs and residual risk - One extra pure function call per diff read. No I/O added or removed on the unaffected paths. - Translation still trims. `resolveWorktreeHostPath` preserves whitespace only when no translation happened; a guest directory named `/home/me/repo ` loses its trailing space on a Windows reader. Reachable only on win32, where such a name is not addressable anyway, and the previous behavior for that shape was a drive-relative miss. - A relative worktree path (no caller passes one) is now resolved against the process cwd instead of joined relative to it. Same file in every case except a relative name that itself ends in whitespace. - `UNSPELLABLE_WORKING_TREE_READ`'s `exists`/`failed` fields are correct but not observable today: the stamp is null for the same input, so nothing can be cached and `reusable` cannot be read back. They are there so the branch stays right if `loadDiff` ever gains a second caller. The test pins the observable part - that no read lands on a cwd-relative path. - Every test here mocks `node:fs/promises` and spoofs `process.platform`. They prove which path string reaches `stat`/`readFile`, which is the right assertion, but none of this has executed against a real 9p mount on a Windows+WSL box and this repo's CI has no such runner. - Honest framing of the trigger: I could not demonstrate a mainline path that hands `getDiff` an untranslated POSIX worktree path on Windows today - `translateWslOutputPaths` UNC-translates worktree paths whenever a distro is known, `getWslHome` returns the UNC spelling, and `resolveWslRepoWorktreeBasePath` normalizes a configured Linux base. The drvfs case is the most plausible live one. Treat this as defense-in-depth that is a strict no-op on every configuration above except the two marked Fixed. Verification - `npx vitest run src/main/git src/shared/git-metadata-path.test.ts` -> 196 files / 2241 tests passed, 2 files and 5 tests skipped. One failure, `git-admission-storm-measurement.test.ts > reports bounded-concurrency before and after measurements` (ENOENT scandir on its own temp state dir), is pre-existing and environmental: it fails identically in isolation and spawns real git children without touching any changed module. - `npx vitest run src/main/git/status-diff-settled-cache.test.ts` -> 21/21 (16 pre-existing, 5 new). `npx vitest run src/shared/git-metadata-path.test.ts` -> 25/25 (19 pre-existing, 6 new cases across 3 new tests). - `npx oxfmt --write` then `npx oxlint` on all five changed files -> clean. Mutation checks - all eight production substitutions were reverted one at a time and the suite re-run. Each fails at least one test, and no new test survives its own mutation: | Reverted | Failing test | |---|---| | file-diff working-tree read -> `worktreePath` | reads the working tree through the host spelling instead of reporting a deletion; invalidates when the working tree file is edited under the host spelling | | stamp working-tree component -> `worktreePath` | invalidates when the working tree file is edited under the host spelling | | stamp `.gitmodules` stat -> `worktreePath` | invalidates when .gitmodules appears under the host spelling | | stamp `resolveGitDir` -> `worktreePath` | stamps through the host spelling so the second read does not respawn git | | `options` threading at the `readWorktreeDiffStamp` call | stamps through the host spelling...; invalidates when .gitmodules appears... | | wrapper's untrimmed preservation -> return the resolver's value | keeps whitespace that belongs to the directory name (both cases) | | `UNSPELLABLE_WORKING_TREE_READ` -> a cwd-relative `readWorkingTreeFile` | reads nothing relative to the cwd when the worktree path has no host spelling | | stamp's null early return -> `hostWorktreePath ?? worktreePath` | reads nothing relative to the cwd when the worktree path has no host spelling | The settled-cache tests seed the fake filesystem through the platform-bound `path` module rather than `path.win32`, so they assert real behavior on a POSIX CI host as well as on Windows and are not gated on the host platform. Co-authored-by: Neil <79079362+brennanb2025@users.noreply.github.com>
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.47 · Install guide
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. If it is full, use group 8.
-
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.












