* Fix Korean IME composition by deferring live terminal preedit The mobile terminal capture field previously sent and cleared every TextInput change, which can break Hangul composition on Android keyboards. Introduce a small commit model and extracted live-input hook so composed text is flushed deliberately while ASCII remains immediate. Constraint: React Native TextInput has no portable composition event for this path; the fix uses a bounded commit delay for likely IME text. Rejected: Native-module IME integration | unnecessary for the confirmed JS dispatch/clear failure and higher maintenance risk. Confidence: high Scope-risk: moderate Directive: Keep terminal.send payload shape and buffered command input unchanged; do not claim physical Samsung Keyboard QA without device evidence. Tested: cd mobile && pnpm exec vitest run src/terminal/terminal-live-text-commit.test.ts src/terminal/terminal-live-input.test.ts src/terminal/terminal-text-input-normalization.test.ts src/terminal/terminal-keyboard-type.test.ts --reporter=verbose Tested: cd mobile && pnpm exec tsc --noEmit Tested: cd mobile && pnpm exec oxlint src/terminal/terminal-live-text-commit.ts src/terminal/terminal-live-text-commit.test.ts src/terminal/use-terminal-live-input-commit.ts app/h/[hostId]/session/[worktreeId].tsx Not-tested: Physical Galaxy Fold7/Samsung Keyboard and Android emulator/Gboard QA were unavailable; device probes recorded no attached Android device. * Preserve pending Korean IME text before mobile accessory controls Accessory keys share the same pending live-input commit gate as TextInput keypress and submit paths, so control bytes cannot race ahead of composed Hangul. Constraint: React Native mobile input does not expose portable composition events for Samsung/Gboard IME paths. Rejected: Let accessory buttons keep sending directly | Direct sends can drop pending Hangul before Tab/Esc/Enter/Backspace reaches the PTY. Confidence: high Scope-risk: narrow Directive: Keep all terminal control-byte paths behind the pending live-input flush/local-edit decision before sending to the PTY. Tested: pnpm --dir mobile test; pnpm --dir mobile lint; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile exec oxfmt --check src/terminal/terminal-live-text-commit.ts src/terminal/terminal-live-text-commit.test.ts src/terminal/use-terminal-live-input-commit.ts src/terminal/use-terminal-live-accessory-input-commit.ts app/h/[hostId]/session/[worktreeId].tsx; git diff --cached --check Not-tested: Physical Galaxy Fold7 Samsung keyboard manual QA is still external-device only. * Prevent stale IME timer flushes after mobile terminal teardown Pending live-input timers now clear on hook unmount, and accessory Delete documents why it stays local without trimming pending IME text. Constraint: React Native TextInput lacks a portable composition lifecycle, so pending IME text is guarded by a bounded timer that must not survive screen teardown. Rejected: Use clearPendingLiveInputCommit during unmount | it would also touch React state/native props during teardown when only timer/ref cleanup is required. Confidence: high Scope-risk: narrow Directive: Any delayed terminal input commit must have an owner-lifecycle cleanup path before sending to the PTY. Tested: pnpm --dir mobile test; pnpm --dir mobile lint; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile exec vitest run src/terminal/terminal-live-text-commit.test.ts --reporter=verbose; pnpm --dir mobile exec oxfmt --check src/terminal/terminal-live-text-commit.ts src/terminal/use-terminal-live-input-commit.ts; git diff --check Not-tested: Physical Galaxy Fold7 Samsung keyboard manual QA remains unavailable in this environment. * Use semantic accessory edits for mobile IME commits Accessory Backspace/Delete now carry semantic local-edit intent from built-in keys instead of inferring intent from raw bytes, and submit handling is reconnected to the pure submit-sequence model. Constraint: Custom terminal accessory keys may produce the same bytes as built-ins but should still flush pending IME text before sending rather than being silently treated as hidden-input edits. Rejected: Classify local accessory edits by raw bytes | That couples future custom controls to current built-in byte encodings. Confidence: high Scope-risk: narrow Directive: Keep semantic input intent separate from terminal byte payloads when pending IME text is present. Tested: pnpm --dir mobile test; pnpm --dir mobile lint; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile exec oxfmt --check src/terminal/terminal-live-text-commit.ts src/terminal/terminal-live-text-commit.test.ts src/terminal/use-terminal-live-input-commit.ts src/terminal/use-terminal-live-accessory-input-commit.ts app/h/[hostId]/session/[worktreeId].tsx; git diff --check Not-tested: Physical Galaxy Fold7 Samsung keyboard manual QA remains unavailable in this environment. * Respect IME flush failures before control input Propagate terminal.send success from pending Korean IME text before sending Enter, Tab, or accessory bytes, while keeping custom no-pending accessory bytes on the original direct path. Constraint: PR #7011 review required follow-up control bytes only after the pending composed text send actually succeeds. Rejected: Treating send invocation as success | It can still reject or no-op when RPC state changed. Confidence: high Scope-risk: narrow Directive: Keep pending IME flush paths async-success-aware before adding new terminal control inputs. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; pnpm --dir mobile exec oxfmt --check changed files; targeted no-excuse clean for mobile/src/terminal changed files. Not-tested: Physical Galaxy Fold7 Samsung keyboard; full session file no-excuse audit still reports pre-existing unrelated violations. * Serialize mobile IME flushes before live controls Treat terminal.send as successful only when the RPC response is ok and the runtime send result is accepted, then route all live-input control sends through a shared in-flight pending-flush barrier. Constraint: PR #7011 review found that resolved RPC promises and per-call sequencing were not enough to prove pending Hangul text reached the PTY before follow-up controls. Rejected: Only awaiting each flush-then-send call | Repeatable accessory keys and no-pending sends can arrive while the first flush is still in flight. Confidence: high Scope-risk: moderate Directive: Keep future mobile terminal control paths behind the pending-flush barrier whenever IME text may be in flight. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; pnpm --dir mobile exec oxfmt --check changed files; no-excuse clean for terminal changed files. Not-tested: Physical Galaxy Fold7 Samsung keyboard; full session file no-excuse audit still reports pre-existing unrelated violations. * Queue current IME snapshots behind active flushes Drain the pending snapshot captured by a control action after any already-active terminal send, and make accessory commit handling explicit so raw fallback is not encoded as an inverted boolean. Constraint: Architecture review found the previous single-slot barrier could wait for an older flush while skipping newly pending Hangul text. Rejected: Reusing the prior in-flight promise as the current flush result | It proves only an older snapshot, not the current pending buffer. Confidence: high Scope-risk: narrow Directive: New mobile terminal control paths must distinguish allow-raw, handled, and suppress-raw outcomes explicitly. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; pnpm --dir mobile exec oxfmt --check changed files; no-excuse clean for terminal changed files. Not-tested: Physical Galaxy Fold7 Samsung keyboard; full session file no-excuse audit still reports pre-existing unrelated violations. * Preserve accessory raw-send terminal targets Capture the terminal handle at accessory keypress time and suppress raw fallback if the active live terminal changes while waiting for pending IME flushes. Constraint: Independent review found raw accessory bytes could retarget to a different terminal after an async IME flush barrier. Rejected: Re-reading activeHandleRef as the send target after await | It can point at a different terminal than the keypress belonged to. Confidence: high Scope-risk: narrow Directive: Raw accessory fallback must use the keypress-time target and revalidate it after any await. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; pnpm --dir mobile exec oxfmt --check changed files; no-excuse clean for terminal changed files. Not-tested: Physical Galaxy Fold7 Samsung keyboard; full session file no-excuse audit still reports pre-existing unrelated violations. * Document accessory flush barrier intent Make the non-obvious raw accessory wait/suppress behavior explicit so future changes preserve IME-before-control ordering. Constraint: CodeRabbit requested a why-comment for the send-now accessory branch. Rejected: Leaving the barrier semantics implicit | The branch can otherwise look like unnecessary async defensive code. Confidence: high Scope-risk: narrow Directive: Keep comments focused on why raw accessory bytes wait behind IME flushes. Tested: targeted terminal vitest suite; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt check for changed file. Not-tested: Physical Galaxy Fold7 Samsung keyboard. * Preserve buffered accessory raw sends Keep the stale-handle guard focused on the captured active terminal instead of live-input opt-in state, so buffered mode keeps existing accessory key behavior while async live-input waits still cannot retarget to another terminal. Constraint: Buffered command input behavior must remain unchanged while fixing mobile Korean IME live input ordering. Rejected: Requiring live-input enabled handles for raw accessory fallback | suppresses valid buffered-mode accessory sends. Confidence: high Scope-risk: narrow Directive: Do not use live-input opt-in state as terminal liveness for raw accessory sends; validate captured target, active terminal tab, connection, and client instead. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt --check changed mobile terminal/session files; TypeScript no-excuse checker for changed terminal files. Not-tested: Physical Galaxy Fold7 Samsung Keyboard manual QA and GitHub Actions jobs, blocked by unavailable device and upstream fork workflow approval. * Keep Hangul IME text pending until explicit flush Avoid timer-driven PTY writes for Hangul candidates so paused Korean composition cannot leak intermediate jamo, while preserving the bounded settle timer for non-Hangul IME text. Also keep disabled live-input accessory fallback behind any existing pending flush barrier. Constraint: React Native TextInput does not expose a portable composition lifecycle on this mobile surface. Rejected: Fixed 150ms auto-flush for Hangul | can emit ㅎ or 하 if the user pauses mid-composition. Confidence: high Scope-risk: narrow Directive: Treat Hangul candidates as pending until submit/control/accessory flush; do not reintroduce idle timer commits for Hangul without device-level composition evidence. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt --check changed mobile terminal/session files; TypeScript no-excuse checker for changed terminal files. Not-tested: Physical Galaxy Fold7 Samsung Keyboard manual QA and GitHub Actions jobs, blocked by unavailable device and upstream fork workflow approval. * Gate dictation toast on accepted live send Honor the async live-input sender contract so the mobile UI reports dictation insertion only after terminal.send is accepted. Constraint: sendLiveTerminalInput now returns false for stale, disconnected, oversized, or rejected terminal sends. Rejected: Toasting immediately after dispatch | reports success for sends that never reached the PTY. Confidence: high Scope-risk: narrow Directive: Treat live-input UI success as terminal.send acceptance, not request dispatch. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt --check app/h/[hostId]/session/[worktreeId].tsx. Not-tested: Physical Galaxy Fold7 Samsung Keyboard manual QA and GitHub Actions jobs, blocked by unavailable device and upstream fork workflow approval. * Keep accessory edits on Hangul pending path Make accessory local edits reuse the Hangul-aware defer policy so built-in Backspace/Delete cannot reintroduce timer-driven Hangul PTY writes. Constraint: Hangul IME candidates must remain pending until explicit submit/control/accessory flush. Rejected: Reusing the non-Hangul 150ms settle timer for accessory local edits | can leak pending Hangul after Backspace/Delete. Confidence: high Scope-risk: narrow Directive: Any future pending-text reschedule must use getTerminalLiveDeferredTextDelayMs instead of a hardcoded timer. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt --check changed mobile terminal/session files; TypeScript no-excuse checker for changed terminal files. Not-tested: Physical Galaxy Fold7 Samsung Keyboard manual QA and GitHub Actions jobs, blocked by unavailable device and upstream fork workflow approval. * Prove Hangul live-input hook ordering Add a direct hook-level regression so Android Korean IME fixes are covered at the orchestration boundary, not only by lower-level helpers. Constraint: React Native mobile TextInput lacks portable composition lifecycle events in this path. Rejected: Relying only on helper tests | misses hook-level pending flush and submit ordering. Confidence: high Scope-risk: narrow Directive: Keep Hangul candidates pending until an explicit terminal action flushes them. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt --check changed mobile files; no-excuse on terminal modules Not-tested: Physical Galaxy Fold Samsung Keyboard manual QA is not available in this environment. * Keep accessory raw-send tests precise Remove a duplicate raw-target assertion whose title implied disabled live-input behavior that is covered at the accessory commit boundary instead. Constraint: Anti-slop cleanup must preserve existing Hangul/accessory behavior and stay within changed terminal tests. Rejected: Keeping the duplicate disabled-input wording | it tests the same active-terminal predicate as the preceding case. Confidence: high Scope-risk: narrow Directive: Test disabled live-input buffering in the accessory commit layer, not in the raw-target predicate helper. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; pnpm --dir mobile exec oxfmt --check changed mobile files; terminal no-excuse checker Not-tested: Physical Galaxy Fold Samsung Keyboard manual QA is not available in this environment. * Explain stale mobile terminal send gates Document why async IME flush paths re-check terminal/client refs before sending raw bytes or reporting live-send success. Constraint: CodeRabbit review requested short why comments for non-obvious stale-send safety gates. Rejected: Leaving the gates undocumented | future edits could remove the stale-target suppression contract. Confidence: high Scope-risk: narrow Directive: Keep async terminal sends guarded by current client, active handle, tab type, and connection state. Tested: pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; pnpm --dir mobile exec oxfmt --check changed mobile files; terminal no-excuse checker Not-tested: Physical Galaxy Fold Samsung Keyboard manual QA is not available in this environment. * Run mobile IME hook tests through effects Move the Hangul live-input hook regression from server rendering to react-test-renderer so effect cleanup and unmount timer cancellation are exercised. Constraint: @testing-library/react-native imports React Native's Flow entry under this Vitest setup, so the narrow effect-running renderer is the compatible test surface. Rejected: Keeping renderToString | it never runs useEffect cleanup and missed the pending timer cleanup path. Rejected: Adding @testing-library/react-native directly | it failed before tests with React Native Flow syntax under the current Vitest transform. Confidence: high Scope-risk: narrow Directive: Hook-level IME tests must use a renderer that runs effects when asserting pending flush cleanup. Tested: vitest targeted terminal tests; pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt --check changed mobile files; terminal no-excuse checker Not-tested: Physical Galaxy Fold Samsung Keyboard manual QA is not available in this environment. * Keep hook lifecycle tests quiet Suppress only the react-test-renderer deprecation warning around the effect-running hook harness so real console errors still surface. Constraint: CodeRabbit flagged React 19 renderer warning noise; @testing-library/react-native remains incompatible with the current Vitest/RN Flow transform path. Rejected: Global console silencing | it would hide unrelated test failures. Confidence: high Scope-risk: narrow Directive: Keep the renderer warning suppression scoped to this hook harness and pass all other console errors through. Tested: vitest targeted terminal tests; pnpm --dir mobile test; pnpm --dir mobile exec tsc --noEmit; pnpm --dir mobile lint; oxfmt --check changed mobile files; terminal no-excuse checker Not-tested: Physical Galaxy Fold Samsung Keyboard manual QA is not available in this environment. * fix: flush pending mobile IME input before external sends * fix: guard terminal command finished event dispatch --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> |
||
|---|---|---|
| .github | ||
| .husky | ||
| 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
- 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.18
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.








