Skip to content

Provide Orca CLI on managed Linux and macOS servers - #26539

Merged
OrcaWin merged 4 commits into
mainfrom
nwparker/orcad-host-cli
Oct 9, 2026
Merged

OrcaWin merged 4 commits into
mainfrom
nwparker/orcad-host-cli

Conversation

@nwparker

@nwparker nwparker commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​180 $\color{#cf222e}{\Huge{\mathbf{−}}}$​3 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​177
Prod 9 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​118 $\color{#cf222e}{\Huge{\mathbf{−}}}$​4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​114

ELI5

After an SSH host moves to Remote, agents on that machine still need the orca command. The managed server did not include it. This gives Linux and macOS servers their own CLI so agents can inspect their work and use Orca commands on the machine doing the work.

What Changed

Bundle the existing CLI and its version metadata into the server's verified artifact inventory. After acquiring the host profile lock, create an atomic, profile-scoped Unix launcher using the same pinned Node that runs the server. Reuse the child PATH function for terminals and structured agents, pinning the launcher and profile to the execution host.

The normal upgrade test now creates a real managed-host terminal, runs orca status and orca worktree ps, checks rendered terminal output, and verifies the returned runtime ID matches the remote host. The headless-server terminal smoke test checks CLI commands too.

Why

The real conversion left a fresh Linux host with no orca on PATH. A desktop resources directory does not exist on a Node server. Reusing the full CLI preserves command behavior and local host authentication; forwarding these commands back to the desktop would target the wrong execution owner. The launcher stays under the profile rather than claiming a global command or Linux's screen-reader name.

Linked Issue

Independently reproduced the managed-server CLI gap recorded as F3 in #26483.

Visual Proof

Before, an actual managed terminal reports QA_CLI_ABSENT. After, the CLI runs both commands and prints QA_CLI_READY. No network or command-handler fault injection was used.

Before After
CLI absent CLI commands succeed

Testing

  • I manually tested these changes locally
  • Automated tests added/updated

macOS client → real Linux arm64 Docker SSH server: all five conversion scenarios pass, including relay-era migration, first upgrade with CLI use, refused TCP forwarding, occupied port 6768, and server update. Before reproduction, five passing real-host tests.

A separately built macOS arm64 headless server passes real terminal creation and CLI commands with an isolated profile. macOS runtime smoke log.

82 affected unit tests pass, including profile isolation, quoted paths and multiline arguments, clearing inherited Node preloads, slot refresh, old slots without CLI files, and terminal/structured-child PATH behavior. pnpm tc, pnpm lint, changed-code quality, Electron e2e build, and pnpm run build:orcad pass. The server build checks the CLI's import graph for Electron and node:sqlite too.

The Linux fixture combines the successfully built source JavaScript with the adhoc package's unchanged Linux native slot and pinned Node reference; every manifest hash was recomputed and normal candidate preflight verified it. Native modules were not rebuilt for Linux on macOS.

Review

Self-reviewed host ownership, profile-lock ordering, atomic launcher refresh, inherited environment isolation, packaging hashes, and reuse of the existing CLI/PATH implementation.

Agent skill upstream boundary

  • Not applicable; no upstream skill implementation is copied.

Notes

This fixes Unix managed servers. Windows still needs a native launcher that preserves argument boundaries; this change deliberately does not add a cmd.exe message proxy, and Windows runtime behavior was not exercised here. No RPC or stream protocol changes. Old server slots without CLI files remain usable. The bundled CLI adds about 1.9 MB before compression.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • Before/after screenshots attached
  • Self-reviewed for correctness, security, and performance
  • Cross-platform and SSH/remote ownership considered
  • Typecheck, lint, affected tests, and relevant builds pass

@OrcaWin
OrcaWin force-pushed the nwparker/orcad-host-cli branch from bd28ba5 to 3e96501 Compare October 9, 2026 02:07
@OrcaWin
OrcaWin changed the base branch from OrcaWin/phase35 to main October 9, 2026 02:07
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4a854f0a-eb34-4379-b349-5893698d7f8f
📥 Commits

Reviewing files that changed from the base of the PR and between 3e96501 and 3716f05.

📒 Files selected for processing (1)
  • tests/e2e/ssh-orcad-auto-convert.spec.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

The build now produces and packages a Node-based CLI bundle. Orcad prepares a host-scoped Unix launcher and exposes its path through the app environment. Child processes can use that launcher with an updated PATH and CLI environment. Runtime smoke and end-to-end tests exercise CLI commands in managed terminals.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to 3716f

The Orca CLI launcher change looks sound. The only open concern is that the SSH upgrade end-to-end test can pass without checking the CLI when the host fixture has no exec. Marking it as skipped with a reason would make that gap visible. This is a small follow-up and does not block merging.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 14 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: providing the Orca CLI on managed Linux and macOS servers.
Description check Passed The description covers the required sections, including the user impact, implementation, rationale, linked issue, visual proof, testing, review notes, platform limitations, and checklist. It provides …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 422958ce-2631-4bfb-9633-5d2230f858e3
📥 Commits

Reviewing files that changed from the base of the PR and between 37833ce and 3e96501.

📒 Files selected for processing (14)
  • config/scripts/build-orcad.mjs
  • config/scripts/orcad-entry-build.mjs
  • config/scripts/runtime-serve-terminal-smoke.mjs
  • src/main/cli/cli-command-privileged-transaction.test.ts
  • src/main/cli/cli-dev-launcher.ts
  • src/main/cli/orca-cli-child-path.test.ts
  • src/main/cli/orca-cli-child-path.ts
  • src/main/orcad/orcad-cli-launcher.test.ts
  • src/main/orcad/orcad-cli-launcher.ts
  • src/main/orcad/orcad-entry.ts
  • src/main/runtime/structured-session-child-identity-env.test.ts
  • src/shared/app-environment.ts
  • src/shared/orcad-artifacts.ts
  • tests/e2e/ssh-orcad-auto-convert.spec.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

Comment on lines +253 to +255
if (!host.exec) {
return
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

sed -n '200,300p' tests/e2e/ssh-orcad-auto-convert.spec.ts
rg -n 'host\.exec|test\.skip|hostCanExecute|canExecute' tests/e2e/ssh-orcad-auto-convert.spec.ts

Repository: stablyai/orca

Length of output: 4892


🏁 Script executed:

rg -n -F --glob '*.ts' -- 'function startHost' tests
rg -n -F --glob '*.ts' -- 'startHost(' tests/e2e tests
rg -n -F --glob '*.ts' -- 'exec?:' tests
rg -n -F --glob '*.ts' -- 'exec:' tests/e2e tests
rg -n -F --glob '*.ts' -- 'defineConfig' playwright.config.ts tests 2>/dev/null || true
rg -n -F --glob '*.ts' -- 'test.skip' tests/e2e/ssh-orcad-auto-convert.spec.ts tests/e2e/helpers

Repository: stablyai/orca

Length of output: 3728


🏁 Script executed:

set -o pipefail
printf '%s\n' '--- startHost definitions and uses ---'
rg -n -F --glob '*.ts' -- 'function startHost' tests || true
rg -n -F --glob '*.ts' -- 'startHost(' tests/e2e tests || true
printf '%s\n' '--- exec declarations and fixture definitions ---'
rg -n -F --glob '*.ts' -- 'exec?:' tests || true
rg -n -F --glob '*.ts' -- 'exec:' tests/e2e tests || true
printf '%s\n' '--- runner configuration and skip usage ---'
rg -n -F --glob '*.ts' -- 'defineConfig' playwright.config.ts tests 2>/dev/null || true
rg -n -F --glob '*.ts' -- 'test.skip' tests/e2e/ssh-orcad-auto-convert.spec.ts tests/e2e/helpers || true

Repository: stablyai/orca

Length of output: 3861


🏁 Script executed:

printf '%s\n' '--- startHost definitions and uses ---'
rg -n -F --glob '*.ts' -- 'function startHost' tests || true
rg -n -F --glob '*.ts' -- 'startHost(' tests/e2e tests || true
printf '%s\n' '--- exec declarations and fixture definitions ---'
rg -n -F --glob '*.ts' -- 'exec?:' tests || true
rg -n -F --glob '*.ts' -- 'exec:' tests/e2e tests || true
printf '%s\n' '--- runner configuration and skip usage ---'
rg -n -F --glob '*.ts' -- 'defineConfig' playwright.config.ts tests 2>/dev/null || true
rg -n -F --glob '*.ts' -- 'test.skip' tests/e2e/ssh-orcad-auto-convert.spec.ts tests/e2e/helpers || true

Repository: stablyai/orca

Length of output: 3861


🏁 Script executed:

printf '%s\n' '--- ssh-orcad-auto-convert.spec.ts imports, constants, startHost ---'
nl -ba tests/e2e/ssh-orcad-auto-convert.spec.ts | sed -n '1,115p'
printf '%s\n' '--- orcad-convert-host helper ---'
nl -ba tests/e2e/helpers/orcad-convert-host.ts | sed -n '1,115p'
printf '%s\n' '--- Playwright config ---'
nl -ba tests/playwright.config.ts | sed -n '1,120p'
printf '%s\n' '--- package runner declarations/scripts ---'
rg -n -F --glob 'package.json' -- 'playwright' . || true
rg -n -F --glob '*.ts' -- 'test(' tests/playwright.config.ts tests/e2e/helpers | head -80 || true

Repository: stablyai/orca

Length of output: 16192


Make the missing CLI coverage explicit.

The Windows host fixture does not provide exec, so this test returns before it runs the CLI assertions. The runner then records the test as passed because the test body returns without an error. Mark this condition as skipped with a reason, or fail it if CLI verification is required.

🐛 Suggested fix
--- "a/tests/e2e/ssh-orcad-auto-convert.spec.ts"
+++ "b/tests/e2e/ssh-orcad-auto-convert.spec.ts"
@@ -250,9 +250,10 @@
     app = upgraded.app
     await waitForSessionReady(upgraded.page)
     await convertAndRetain(upgraded.page, session.userDataDir, seeded)
+    test.skip(!host.exec, 'This host fixture cannot read files to verify CLI output')
     if (!host.exec) {
       return
     }
     const environment = (
       await upgraded.page.evaluate(() => window.api.runtimeEnvironments.list())
     ).find((entry) => entry.orcadDeployment?.sshTargetId === seeded.targetId)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!host.exec) {
return
}
test.skip(!host.exec, 'This host fixture cannot read files to verify CLI output')
if (!host.exec) {
return
}

# Conflicts:
#	tests/e2e/ssh-orcad-auto-convert.spec.ts
@OrcaWin
OrcaWin merged commit bdf0d66 into main Oct 9, 2026
88 of 91 checks passed
brennanb2025 added a commit that referenced this pull request Oct 9, 2026
Main now bundles the CLI into the server slot and writes a profile launcher
on Unix. Drop this branch's parallel CLI packaging, slot launchers, and
build-time version; keep the owning-host binding (now exported by main's
launcher), the Windows native launcher on main's layout, the Claude command
order, and the refreshed shell environment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants