* feat(source-control-ai): add {linkedIssue} recipe variable for commit and PR prompts
Custom commit-message and pull-request recipes can now reference the GitHub
issue linked to the workspace, so a template like "Fixes #{linkedIssue}" lands
the closing trailer without the user retyping the number.
- register `linkedIssue` on the commitMessage and pullRequest actions only,
with the VARIABLE_INFO entry the chip hover card requires
- substitute unconditionally via `formatLinkedIssueTemplateValue` (empty string
when nothing resolves) so the token never survives into a prompt; enrich the
draft context conditionally via `withLinkedIssueDraftContext` so unlinked
workspaces keep their existing context shape
- attach at the 7 call boundaries (runtime commit x2, runtime PR shared, IPC
commit x2, IPC PR x2); the pure git gather stays pure
- validate the renderer-supplied worktreeId against the request path and repoId
before any meta read, comparing SSH paths as raw strings so a Windows host
cannot rewrite a remote POSIX path
- built-in prompts are unchanged; no GitLab dual-read and no default trailer
* fix(source-control-ai): resolve {linkedIssue} adversarial review findings
Addresses 13 of the 14 findings from the {linkedIssue} code review
(6 minor, 8 nit, 0 critical, 0 major); Issue 5 (GitLab provider naming)
is deferred to design Open Question 3 as product expansion.
Behavior:
- Dialog previews the workspace's real linked issue instead of the
synthetic 123, in both the chip hover card and the plan preview, so an
unlinked workspace previews the `Fixes #` it will actually generate.
Settings dry-runs stay fully synthetic.
- Reject non-positive, fractional and unsafe-integer issue numbers at the
IPC resolver via a shared isLinkedIssueNumber predicate, so corrupt meta
never reaches a draft context (previously -7 rendered `Fixes #-7` and
1e21 rendered `Fixes #1e+21`).
- Fail closed on an empty-string repoId instead of skipping the cross-check.
Structure:
- Split the variable registry into source-control-ai-action-variables.ts
and re-export it, restoring max-lines headroom with no consumer churn
and no lint disable.
- Constrain withLinkedIssueDraftContext to contexts declaring linkedIssue.
- Move the misplaced shared imports into their import group.
Docs and tests:
- Document that the IPC id/path validator guards relay/CLI/future callers,
not the renderer (whose path is id-derived), and rename the three tests
that read as proof of a protection that cannot fire.
- Add PR-side coverage that was missing: three git:generatePullRequestFields
handler tests, a built-in PR prompt no-leak guard, and the runtime PR
unlinked case.
- Replace the coincidental '42' assertion with a fixture-unique sentinel.
- Type the runtime worktree fixture with satisfies, which surfaced and
fixed pre-existing drift in its git sub-object.
- Add an e2e case covering the preload -> main -> meta -> template chain.
Co-authored-by: Orca <help@stably.ai>
* fix(source-control-ai): resolve {linkedIssue} adversarial re-review findings
Addresses all 8 findings from the {linkedIssue} code re-review
(2 minor, 6 nit, 0 critical, 0 major); none deferred.
Behavior:
- Revert the variableOverrides parameter on planSourceControlTextGeneration.
Its result is a Save/Generate gate, not a preview, and the recipe it
validates is saved repo- or globally scoped -- so rendering it against the
active workspace disabled both buttons with "Command input is empty." for a
{linkedIssue}-only template on any unlinked workspace, blocking a global
settings write. Validation is synthetic again; chip previews are unchanged.
- Make the chip hover card additive instead of either/or. A supplied preview
now appends a "This workspace" sample below the description and Example
rather than replacing them, so the GitLab-empty and dangling `Fixes #`
warning survives on the two dialogs where recipes are actually authored.
basePrompt keeps its preview-only shape, where the preview is the content.
Structure:
- Drop the registry re-export from source-control-ai-actions.ts and move the
last two consumers onto source-control-ai-action-variables, so one import
path per symbol keeps a grep of the registry's consumers complete.
- Split the registry/helper suites into source-control-ai-action-variables.test.ts
so each test file mirrors its module.
Tests:
- Cover the Save/Generate gate at the canRunGeneration level for a bare
{linkedIssue} recipe on linked and unlinked workspaces, with a negative
control proving the buttons can still be disabled.
- Cover the chip hover card directly; the dialog tests mock it away.
- Guard the PR mismatched-id test with toHaveLength(1) so it cannot pass
vacuously on an unrelated early return.
- Add an unlinked-workspace e2e case (saw-issue:empty), which is what
distinguishes a real resolver from one that always returns a number.
Spec now runs green: 3 passed.
- Rename the dialog test that claimed a synthetic-fallback assertion it did
not make, and route its renders through one shared helper.
Docs are worktree-local (.gitignore:84 ignores docs/**): the design doc's
plan-preview and chip-surface claims, the manual QA rows, and both reviews'
statements about pre-existing PR-handler tests are corrected there.
* fix(source-control-ai): make the {linkedIssue} e2e guard and dialog test falsifiable
The e2e unlinked case extracted the echoed issue with `ORCA_E2E_ISSUE=(\d*)`,
which matches zero digits in front of an unexpanded `{linkedIssue}` and reported
it as `empty` — so the case that exists to catch a literal token surviving into
a prompt passed on exactly that regression. Capture the whole line instead: a
literal now arrives as `saw-issue:{linkedIssue}` and fails, verified by dropping
the substitution key for unlinked contexts and watching the case go red.
Also drop the inert `not.toContain('Command input is empty.')` assertion — that
copy is click-driven `generationError` state and this suite renders statically,
so it could never fail; the claim it reached for is carried by the plan test.
Rename two plan tests off the "plan preview" framing the design now rejects.
Local review artifacts (design doc, implementation notes, final review) were
swept to match the tree in the same pass; they are gitignored here.
* Resolve {linkedIssue} from live metadata, not cache
Resolved worktrees are cached for a second, causing commit and PR
generation to use stale linked-issue state. Hosts now implement
getWorktreeLinkedIssue to provide fresh issue metadata by worktree id,
with proper fallback for unlinked workspaces. Updates both commit
message and PR field generation paths; includes integration and e2e
coverage.
* Keep cached linkedIssue when metadata is unavailable
Return undefined from getWorktreeLinkedIssue when live metadata cannot be read
(store not ready), distinguishing it from null (unlinked). The caller now falls
back to the cached worktree value instead of treating unavailable as unlinked.
Also extract the linked-issue echo generator as a shared e2e test helper.
---------
Co-authored-by: Orca <help@stably.ai>
|
||
|---|---|---|
| .github | ||
| .husky | ||
| Casks | ||
| build-plugins | ||
| config | ||
| docs | ||
| mobile | ||
| native | ||
| resources | ||
| skill-guides | ||
| skill-stubs | ||
| 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
中文 · 日本語 · 한국어 · 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.32
Community & Support
-
Discord: Join the community on Discord.
-
Twitter / X: Follow @orca_build for updates and announcements.
-
WeChat: All other groups are full, now we're on group 5.
-
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.








