Skip to content

fix(ssh): turn a host's orca CLI control on by default and stop resetting saved choices - #29856

Merged
nwparker merged 4 commits into
mainfrom
nwparker/remote-cli-control-default-on
Oct 16, 2026
Merged

nwparker merged 4 commits into
mainfrom
nwparker/remote-cli-control-default-on

Conversation

@nwparker

@nwparker nwparker commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 10 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​220 $\color{#cf222e}{\Huge{\mathbf{−}}}$​66 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​154
Prod 18 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​62 $\color{#cf222e}{\Huge{\mathbf{−}}}$​91 $\color{#cf222e}{\Huge{\mathbf{−}}}$​29

ELI5

Each SSH host has a switch, "Allow this host's orca CLI to control Orca". Until now it was off unless you had turned it on recently, and on the next start Orca turned off every host where it had been saved on by an older version. People upgrading from the stable release (1.4.227), where "on" meant the host's terminals could run orchestration commands, would have lost that without being told. Now the switch is on by default, a saved "on" stays on, and only an explicit "off" turns it off.

What Changed

Before: a host with no saved value was off. On load, a saved true without the new consent stamp was turned off, and the settings page showed a notice saying Orca had turned it off.

After:

  • No saved value means on. One check, isRemoteCliControlAllowed (src/shared/ssh-remote-cli-control.ts), is now used by both gates: the desktop browser bridge's choice of which managed hosts may attach (desktop-browser-bridge-wiring.ts), and the relay-era CLI server's admission check (legacy-relay-bridge-ipc.ts). An explicit false is refused at both. A host that has been removed is refused.
  • No reset. The one-time load step (normalizeRemoteCliControlConsent), the consent stamp written on save, and the reset notice (with its strings in every locale) are gone. A stray allowRemoteCliControlReset flag from an earlier build is dropped on load, so a host that build reset comes back on. The old allowRemoteCliControlConsent field is still in the type and is left on disk untouched, but nothing reads it. Leaving it means a downgrade to a build that checks it does not reset a host it already stamped.
  • Settings and the sidebar's add-host dialogs start with the switch on and always save it as an explicit true or false. The advanced section only opens on its own when the switch is off, since off is now the non-default value.
  • Paired servers (RPC). ssh.listEditableTargets now returns the value that actually applies (absent is listed as true). ssh.addTarget and ssh.updateTarget save a missing value as false. Older clients leave the field out when their switch shows off, so this keeps what they save meaning what they showed. Current clients always send a boolean.
  • Help text, in all locales: "On by default", what it allows (desktop browser tabs in this host's workspaces while it is connected, and orchestration commands from terminals started by an older Orca), what it cannot do, and what off means.

Unchanged: orchestration stays behind the same switch. The caller scope, the identity and pane binding, the per-host concurrency cap, timeouts, aborting in-flight calls when the switch turns off, and the target-scoped lookups from #29571/#29596 are all as they were. Only the default and the reset changed.

Why

This is the user's decision, made to keep the SSH upgrade smooth. It matches what VS Code Remote, paseo and superset do: a host you connect to can already run code as you in its own workspaces. The alternatives were to keep off as the default and only drop the reset (stable users would still lose relay-era orchestration, because stable never saved the stamp), or to add a separate opt-in for orchestration (more switches, and the same upgrade break).

Security note

What a compromised SSH host can now do by default, with no action from the user:

  • Drive this desktop's in-app browser pane for that host. It can open, navigate, read and script tabs, but only in that host's own workspaces, only in that host's own browser partition, and only while it is connected. It cannot reach file:// or the clipboard, cannot download files to this desktop, and cannot choose the profile, focus or placement of a tab. Every forwarded command is written to the audit log. These are the same limits fix(ssh): agents on a managed SSH host can drive the desktop Orca browser again, behind the per-host switch #29384 put in place for when the switch is on.
  • Run orchestration commands (check, inbox, send, ask, reply) from its own relay-era terminals, scoped to the supervised work those terminals are bound to. The identity and pane binding and the target-scoped lookups still stop it from acting as another terminal or touching another host's work.

It still cannot read the desktop's files, clipboard or cookies outside that host's partition. Turning the switch off detaches the bridge at once and cancels in-flight relay CLI calls. This matches the trust model of VS Code Remote, paseo and superset, where a connected host is trusted inside its own workspaces.

Linked Issue

Refs #29145, #29384, #29571, #29596

Visual Proof

N/A for screenshots: the only UI change is the switch's default value, the help text, and removing the reset notice. The live run below saved screenshots of the host driving a desktop tab with the switch at its default, and of it being refused once the switch was off.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

Unit tests (each failed before this change where it covers the new default):

  • src/main/ipc/desktop-browser-bridge-wiring.test.ts (new): the browser bridge attaches a host with no saved value or an explicit true, and never an explicit false.
  • legacy-relay-cli-server.test.ts: the relay CLI server admits no saved value or an explicit true, and refuses an explicit false with LEGACY_RELAY_CLI_CONTROL_OFF.
  • legacy-relay-cli-call-limits.test.ts: turning a default-on switch off at runtime still cancels a waiting check --wait.
  • ssh-normalization-remote-cli-control.test.ts (replaces the consent test): a saved true is kept on load (no reset), false stays false, absent stays absent and is allowed, and the retired reset flag is dropped.
  • ssh-connection-store.test.ts: saves the switch as given, with no stamp.
  • ssh-target-save-payload.test.ts, add-remote-host-ssh-actions.test.ts: settings and sidebar save explicit true/false, and an absent value shows as on.
  • ssh-target-management.test.ts: over RPC, an older client's missing value is saved as off, and the list shows the value that applies.
  • tests/e2e/ssh-orcad-desktop-browser-bridge.spec.ts: now checks that the host works with no saved value and is refused, with the setting's name, after the switch is set to false.

Local gates: every step of the "static analysis and typecheck" job (lint, anti-slop, code-quality plugins, type-aware lint, changed-code quality, React Doctor, typecheck, the ratchets including focus-read, the localization extraction, catalog and coverage checks, the RPC catalog). Unit folders: src/renderer/src/components/settings, src/renderer/src/components/sidebar, src/main/runtime/rpc/methods, src/main/ssh/legacy-relay-bridge, src/main/persistence/leasing-ssh-ptys.

Verified live (macOS desktop, Linux host): an isolated desktop built from this branch (e2e session with its own user data, ORCA_BACKGROUND_LAUNCH=1, no visible window) on an M-series Mac. The host was omarchy (x86_64 Linux), reached through an ssh -L tunnel to a private user-level sshd that ran with a throwaway HOME and XDG dirs under /tmp. The desktop deployed a real managed orcad there, built from this branch for linux-x64-glibc. The run used a local copy of the browser-bridge e2e flow, pointed at that host instead of Docker, and did not modify the shipped spec. It confirmed:

  • The saved host had no allowRemoteCliControl value (undefined).
  • With no saved value, the host's own orca CLI ran tab create, goto, snapshot, tab list and tab close against a desktop browser tab in the host's workspace. file:// was refused with invalid_argument.
  • After allowRemoteCliControl: false was saved, the host was refused with desktop_browser_bridge_unavailable, and the error named the setting.

All test processes and directories on both machines were removed afterwards. Only in tests: the relay-era orchestration path (relay CLI admit, refuse and runtime abort), the no-reset load, and the mixed-version RPC mapping.

Review

Codex (gpt-6.1-sol, high effort), three rounds:

  1. P1: the sidebar's add-host dialogs left the switch out, so an explicit off would have been read as on. Fixed: they now save it explicitly, with a test.
  2. P1: an older paired client leaves the switch out when it shows off, so an upgraded server would have read that as on. Fixed at the RPC boundary (a missing value is saved as off, and the list shows the value that applies), with a test.
  3. Clean.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Mixed versions: a new client talking to a server from before this change sees a host with no saved value as on, while that server still treats it as off. That errs in the safe direction (the host gets less access than shown), and the next save from the new client writes an explicit value. Folder workspaces and git worktrees are affected the same way. No platform-specific code.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@coderabbitai

coderabbitai Bot commented Oct 16, 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: 585994b4-279d-4c9c-8a7d-8723c29f0893
📥 Commits

Reviewing files that changed from the base of the PR and between 878fc14 and 5edb214.

📒 Files selected for processing: 2
  • src/main/ipc/desktop-browser-bridge-wiring.ts
  • src/renderer/src/i18n/locales/en.json
🚧 Files skipped from review as they are similar to previous changes: 1
  • src/renderer/src/i18n/locales/en.json

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

📝 Walkthrough

Remote CLI control now defaults to allowed when an SSH target has no saved setting, and an explicit false disables it. SSH target normalization, storage, RPC handling, settings forms, desktop browser bridge selection, and legacy relay checks use the updated behavior. The reset-notice field and consent-based normalization are removed. Help text and translations describe the default and no longer show the reset warning.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 5edb2

The described changes consistently apply the new default and explicit opt-out across SSH settings and bridge eligibility. No actionable merge-blocking risk is established in the supplied review context.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 20 files. (1 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly summarizes the main change: enabling SSH host Orca CLI control by default and stopping resets of saved choices.
Description check Passed The description is detailed, focused, and covers the required user impact, implementation, rationale, security considerations, testing, compatibility, and checklist items. The linked issue section lis…
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.
Full details: Description check

Explanation

The description is detailed, focused, and covers the required user impact, implementation, rationale, security considerations, testing, compatibility, and checklist items. The linked issue section lists issue references but does not use the required Fixes # linkage.

Full details: Docstring Coverage

Explanation

Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 20 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · 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.

…p resetting saved choices

An absent allowRemoteCliControl now means on; only an explicit false turns the
desktop browser bridge and relay-era orchestration commands off. Removes the
one-time reset of saved true values, the consent stamp writes and the reset
notice, which would have silently turned off hosts upgraded from stable.
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.

1 participant