* docs(spec): manual network address entry for mobile pairing
* docs(plan): manual network address entry for mobile pairing
* docs(plan): fix two test-spec issues in Task 1
* feat(mobile-pairing): add parseManualNetworkAddress validator
* docs(plan): fix buildComboboxEntries filter rule
* feat(mobile-pairing): buildComboboxEntries for network interface combobox
* feat(mobile-pairing): combobox with manual address entry
* docs(spec): align buildComboboxEntries behavior with corrected plan
* fix(mobile-pairing): use text-destructive token for inline error
* fix(mobile-pairing): route Use row through translate() with i18next interpolation
* refactor(mobile-pairing): extract NetworkInterfaceCombobox shared by MobileHero and Settings section
The Popover + Command + manual-entry UX lived only in the Settings →
Mobile → Network Interface section. The mobile pairing screen
("Step 2 of 2 — Pair this computer") had its own copy of the same
Select-based dropdown that did not support manual address entry. A
user trying to pair with a Tailscale MagicDNS hostname from the
pairing screen could not enter it.
Extract the typeable combobox into a shared
`NetworkInterfaceCombobox` component. Both surfaces now render the
same Popover + Command with manual address entry, the `Use "..."`
row, the inline validation error, and the `(custom)` trigger label.
Settings keeps its own Generate QR button, Refresh + Tooltip, and
Tailnet accordion around the combobox. The pairing screen keeps its
existing layout (label + combobox + refresh icon).
Net deletion: ~160 lines. Net behavior gain: manual address entry is
now reachable from both surfaces, not only Settings.
* style(ui): give CommandInput a visible background so the search box is not lost
The Popover content above the CommandList renders the cmdk CommandInput
with only a thin bottom border. Against a white popover background it
visually disappears, especially in the mobile pairing screen where the
popover sits inside a dark phone mockup. Add a subtle `bg-muted/30` +
`py-1` so the input row is unambiguous, without changing the input's
shape or behavior.
* fix(mobile-pairing): drop cmdk CommandItem, use plain buttons inside Popover
In `pnpm dev` HMR cycle the cmdk CommandItem `onSelect` dispatch was
unreliable — clicking the item fired the synthetic event but the parent
React state never received it, so the trigger label never updated after
the user picked a manual address or a refreshed interface.
Replace the `Command` + `CommandItem` primitives inside
NetworkInterfaceCombobox with a native `<input>` + `<button>` list
wrapped by Radix `Popover`. The list now responds to the user's first
click without any intermediate effect that could be skipped in dev mode.
The combobox keeps the same props contract, the same placeholder, the
same inline validation, and the same `Use "<address>"` row at the
bottom of the list.
Update MobileNetworkInterfaceSection.test.tsx selectors from
`role=option` (cmdk's) to `role=button` so the integration test still
asserts the right element. All 479 feature tests still pass.
* debug(mobile-pairing): log handleSelect* invocations to confirm click path
* fix(mobile-pairing): commit on pointerdown to beat Radix Popover close race
In dev mode Radix Popover's close-on-pointerdown handler occasionally
fires before React's synthetic click dispatch reaches the option button,
so the parent's selectedAddress never updates after the user picks a
manual address. Bind the commit handler to pointerdown (synchronous,
before any pointer-up / click synthesis) and call event.preventDefault()
to avoid text-selection side effects. Keep onClick as a fallback so
keyboard / touch / programmatic-dispatch paths still work.
* fix(mobile-pairing): keep manually-typed addresses across network refresh
`selectRefreshedNetworkAddress` used to fall back to the first OS
interface whenever `currentAddress` wasn't in the OS-enumerated
list — so a user who typed a Tailscale MagicDNS name saw their
selection snap back to LAN every time `loadNetworkInterfaces`
returned. Treat manual entries as sticky by passing an
`isManual` flag from the caller; `selectRefreshedNetworkAddress`
now keeps the address when the caller says the user typed it.
`MobilePage` tracks `addressIsManual` alongside
`selectedAddress`: `handleAddressChange` flips it on when the
picked address is not in the OS list, and `loadNetworkInterfaces`
passes it through so refresh keeps the choice.
* chore(mobile-pairing): remove debug logs and sync new-combobox-listbox i18n key
* fix(mobile-pairing): address CodeRabbit review on manual-address lifecycle
Three real bugs from review, plus a regression test:
1. NetworkInterfaceCombobox in MobileHero was disabled when
`networkInterfaces.length === 0`, which locked users out of the
only path to type a manual address during a transient empty
discovery. Pass `disabled={false}` and let the combobox's
own empty-state copy explain the situation.
2. `selectRefreshedNetworkAddress` returned `undefined` whenever
`interfaces.length === 0`, even if the user had a manual
address and `currentAddressIsManual` was true. Keep the manual
address so a recovering discovery doesn't clobber it.
3. `loadNetworkInterfaces` could rewrite `selectedAddress` (e.g.
when a refresh swaps to a freshly-discovered tailnet) but never
updated `addressIsManual`, so the next refresh could revert
the user back to LAN. Re-derive `addressIsManual` from the
new address after every refresh.
Adds a regression test in
`mobile-network-interface-selection.test.ts` exercising the
empty-refresh + manual path.
* style(mobile-pairing): trim disabled-false comment to two lines
* refactor(mobile-pairing): replace typeable combobox with select + custom-address dialog
The Settings/MobileHero network selector used a Popover+search-input hybrid
that looked uneven and hid its validation error behind the open popover.
Replace it with a plain Select of discovered interfaces plus an
'Add custom address…' footer row that opens a small dialog for entering a
Tailscale hostname or static IP. Drops the 'MagicDNS' jargon for plainer
copy, keeps the '(custom)' trigger label, and routes all strings through
translate() with real es/ja/ko/zh translations. Removes the now-dead
buildComboboxEntries helper. Also adds the missing scrollbar-sleek class
the old list omitted (was failing pnpm lint).
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: ppw-stack <ppw-stack@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
|
||
|---|---|---|
| .github | ||
| .husky | ||
| .visual-evidence/sidebar-nav | ||
| Casks | ||
| config | ||
| docs | ||
| mobile | ||
| native | ||
| notes | ||
| previews | ||
| resources | ||
| skills | ||
| src | ||
| tests | ||
| tools | ||
| .gitattributes | ||
| .gitignore | ||
| .npmrc | ||
| .oxfmtrc.json | ||
| .oxlintrc.json | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| LICENSE | ||
| README.md | ||
| components.json | ||
| electron.vite.config.ts | ||
| orca.yaml | ||
| package.json | ||
| pnpm-lock.yaml | ||
| tsconfig.json | ||
| vite.web.config.ts | ||
README.md
Orca
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
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.17
Community & Support
-
Discord: Join the community on Discord.
-
Twitter / X: Follow @orca_build for updates and announcements.
-
WeChat: Scan the QR code to join the community.
-
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.
License
Orca is free and open source under the MIT License.








