Skip to content

fix(cli): point wrong browser guesses at Orca's real top-level browser commands - #26100

Open
brennanb2025 wants to merge 5 commits into
mainfrom
brennanb2025/browser-cli-command-hints
Open

brennanb2025 wants to merge 5 commits into
mainfrom
brennanb2025/browser-cli-command-hints

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 4 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​214 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​213
Prod 7 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​151 $\color{#cf222e}{\Huge{\mathbf{−}}}$​37 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​114

ELI5

Agents running inside an SSH terminal kept failing to use Orca's built-in browser and gave up for Playwright. The browser worked fine; the orca command line steered them into dead ends. The orca browser help said the browser could only manage its "identity", wrong guesses like orca browser open <url> failed with no hint, orca goto <url> without --url was rejected, and every remote call printed a scary-looking relay line to the error stream. This PR makes each of those wrong guesses lead straight to the right command.

What Changed

The problem. A user runs Orca on a Mac and an agent (OMP) inside a Linux VM through an Orca SSH terminal. On Sep 25 we reproduced the setup: over SSH, orca reaches the Mac and every real browser command works (orca tab create --url, orca goto --url, orca snapshot, orca screenshot), including pages served from inside the VM. The failures all came from the command surface, which an agent without the orca-cli skill explores by trial and error:

  1. orca browser --help listed only browser identity get/set. The real browser commands are top-level (orca goto, orca snapshot, ...), so an agent that checked the browser group concluded Orca's browser can't open pages.
  2. Wrong guesses got no hint. I confirmed on main that typo recovery compared the whole typed line, URL included, against command names, so any URL in the command killed every suggestion: orca tab creat suggested tab create, but orca tab creat https://example.com suggested nothing.
  3. orca goto https://example.com and orca tab create https://example.com failed with "Unknown command", because the URL was accepted only as --url.
  4. Every orca call from an SSH host printed [relay-connect] Handshake OK at version=… to stderr, which an agent can read as a failure.

What is different for the user (and their agents):

  • orca browser --help now lists every top-level browser command, under a heading that says to run them as orca <command>.
  • An unknown command under orca browser names the real command when there is one (browser goto → orca goto, browser screenshot → orca screenshot) and always adds one line pointing at orca browser --help.
  • open and navigate, the two verbs agents reach for that edit distance can't connect to the real names, recover to orca tab create and orca goto.
  • Typo recovery now works when a URL or other value follows the mistyped command.
  • orca goto <url> and orca tab create <url> accept the URL positionally. --url still works; passing both is refused, as for other commands.
  • The remote orca CLI no longer prints the handshake success line. Errors still print.

The mechanism.

  • Command specs get an optional group field. The browser spec files mark their top-level commands group: 'browser'. The group help lists them, and the existing suggester treats browser <command> as a candidate path for each one. No second suggestion mechanism: it's the same ranking with more candidate paths.
  • The suggester compares each candidate with the same number of leading typed tokens, so trailing values no longer hide a near miss. To keep that from adding noise, it skips a prefix that already names a real path (tab in tab lst is not a typo of get), keeps only the match that explains the most tokens, and returns only exact hits when there are any. The destructive-command guard (feat(cli): make the CLI self-correcting and self-describing for agents #6303) now checks the token at the candidate's verb position, not the last typed token, so a trailing value can't unlock a delete.
  • Renames use a two-entry synonym table beside the existing flag-synonym table, the same pattern --from→--terminal uses.
  • goto and tab create declare positionalArgs: ['url'], the convention file open <path>, artifacts share <file> and search <query> already follow: a command's single main value can be positional, and the flag form stays.
  • The handshake helper is shared by two callers: the SSH bridge (relay.js --connect), whose stderr Orca captures for connection diagnostics and which ssh-relay-pinned-node.integration.test.ts asserts on, and the remote orca CLI (relay.js --orca-cli), whose stderr is the agent's. The helper now hands the accepted version to its caller instead of printing it, and only the bridge prints the line, unchanged. Nothing else reads it (I checked src/main and src/shared).

Why

  • Errors and help instead of accepting orca browser goto as an alias. Aliases would double the browser command surface and hide where the commands really live. The request was for wrong guesses to point to the real commands.
  • group on the spec instead of a hint table in the suggester. The help and the recovery read the same declaration, so a new browser command shows up in both without a second list to keep in sync.
  • Synonyms only for open and navigate. Edit distance handles typos. Without a synonym, browser open is three edits from hover, which would be a wrong suggestion.
  • Moving the success line to the bridge instead of an env-var debug switch. Its only consumer is the bridge path, which still prints it.

Linked Issue

User report (agents on an SSH VM failing at Orca browser commands; reproduced Sep 25). Out of scope: detecting the orca-cli skill on SSH hosts (#18357), onboarding, settings UI.

Visual Proof

Real output from the CLI built from origin/main and from this branch, run under env -i against an empty Orca user-data directory so nothing reached a live Orca.

Before (main)

$ orca browser --help
orca browser

Usage: orca browser <command> [options]

Commands:
  identity get       Show the browser identity configured on this Orca host
  identity set       Choose the browser identity for every page on this Orca host

Run `orca browser <command> --help` for command-specific usage.

$ orca browser open https://example.com
Unknown command: browser open https://example.com

$ orca browser goto https://example.com
Unknown command: browser goto https://example.com

$ orca browser screenshot
Unknown command: browser screenshot

$ orca tab creat https://example.com
Unknown command: tab creat https://example.com

$ orca goto https://example.com
Unknown command: goto https://example.com

$ orca tab create https://example.com
Unknown command: tab create https://example.com

After (this branch)

$ orca browser --help
orca browser

Usage: orca browser <command> [options]

Commands:
  identity get       Show the browser identity configured on this Orca host
  identity set       Choose the browser identity for every page on this Orca host

Run `orca browser <command> --help` for command-specific usage.

Top-level browser commands (run as `orca <command>`, not `orca browser <command>`):
  open-url           Open a URL on the paired client that hosts this terminal
  snapshot           Capture an accessibility snapshot of the active browser tab
  screenshot         Capture a viewport screenshot of the active browser tab
  click              Click a browser element by ref
  fill               Clear and fill a browser input by ref
  type               Type text at the current browser focus
  select             Select a dropdown option by ref
  scroll             Scroll the browser viewport
  goto               Navigate the active browser tab to a URL
  back               Navigate back in browser history
  reload             Reload the active browser tab
  eval               Evaluate JavaScript in the browser page context
  wait               Wait for element, text, URL, load state, JS condition, or timeout
  ... (all 78 top-level browser commands, including goto, tab create, snapshot, screenshot)

$ orca browser open https://example.com
Unknown command: browser open https://example.com
Next step: Did you mean: orca tab create
Next step: Orca's browser commands run at the top level (orca <command>, not orca browser <command>); list them with: orca browser --help

$ orca browser goto https://example.com
Unknown command: browser goto https://example.com
Next step: Did you mean: orca goto
Next step: Orca's browser commands run at the top level (orca <command>, not orca browser <command>); list them with: orca browser --help

$ orca browser screenshot
Unknown command: browser screenshot
Next step: Did you mean: orca screenshot
Next step: Orca's browser commands run at the top level (orca <command>, not orca browser <command>); list them with: orca browser --help

$ orca tab creat https://example.com
Unknown command: tab creat https://example.com
Next step: Did you mean: orca tab create, orca tab current

$ orca goto https://example.com          # accepted; this isolated run has no Orca to reach
Orca is not running. Run 'orca open' first.

$ orca tab create https://example.com    # accepted; same
Orca is not running. Run 'orca open' first.

With --json, the same recovery appears in error.data.suggestions (["tab create"]) and error.data.nextSteps. On main both were empty.

Relay stderr. A detached relay daemon bundled from each side, with the remote CLI path (relay.js --orca-cli status, no Orca client attached) and the SSH bridge path (relay.js --connect) run against it:

# main
--- remote orca CLI path, stderr:
[relay-connect] Handshake OK at version=0.1.0 runtime=host-node/26.5.0
No owning Orca client is connected to the relay
--- SSH bridge path, stderr:
[relay-connect] Handshake OK at version=0.1.0 runtime=host-node/26.5.0

# this branch
--- remote orca CLI path, stderr:
No owning Orca client is connected to the relay
--- SSH bridge path, stderr:
[relay-connect] Handshake OK at version=0.1.0 runtime=host-node/26.5.0

Testing

  • I manually tested these changes locally (macOS: built CLI before/after and bundled relay before/after, output above)
  • Automated tests added/updated
    • src/cli/specs/browser-command-discovery.test.ts (new, against the real command registry): group help lists the browser commands; each reported wrong guess recovers to the real command; the group pointer line; typo-plus-URL recovery; positional URL for goto and tab create; positional and --url together is refused.
    • src/cli/command-suggestion.test.ts: operands after a near miss, destructive intent judged at the verb, group-prefixed recovery, synonyms, the destructive guard on group-prefixed candidates, no cross-group leakage.
    • src/cli/browser.test.ts: goto <url> and tab create <url> send the same RPC payload as the --url form.
    • src/relay/relay-handshake-roundtrip.test.ts: the handshake helper hands the version to its caller and writes no [relay-connect] line; the bridge line format is unchanged.
  • Ran all 363 test files under src/cli and src/relay with config/vitest.config.ts: 361 passed, 2 skipped. pnpm tc:cli, pnpm tc:node and pnpm run check:code-quality:changed pass on top of a3ecee0dce1.
  • Not run: a live orca goto <url> against a running Orca on this branch. The positional form reaches the handler as the same url flag (unit-tested payload), and the --url path itself is unchanged and was verified over SSH on Sep 25. ssh-relay-pinned-node.integration.test.ts (the bridge-line assertion) was not run locally. The bridge still prints the identical line, which the roundtrip test pins.

Review

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • SSH / mixed versions: an SSH host's orca forwards its arguments to the Mac app, so the help, recovery and positional changes take effect when the Mac app updates. The stderr change ships in the relay, which Orca redeploys to the host for each app version. No wire format changes.
  • Cross-platform: pure argument handling and string output; no platform-specific code.
  • Compatibility: --url keeps working everywhere. Scripts parsing orca agent-context --json see positionalArgs: ["url"] on goto and tab create. Nothing else in that schema changes.

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 (CLI text output pasted above)
  • 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). Ran tc:cli, tc:node, the changed-files gate, and the src/cli + src/relay suites locally; CI covers the rest.

orca browser --help now lists the top-level browser commands, unknown
commands under 'browser' (and 'open'/'navigate' renames) recover to the
real verb, typo recovery survives trailing operands like URLs, goto and
tab create take the URL as a positional, and the remote orca CLI no
longer prints the relay handshake success line to stderr.
@coderabbitai

coderabbitai Bot commented Oct 7, 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: 88295eb5-ef1f-445d-9538-0d51d8720b38
📥 Commits

Reviewing files that changed from the base of the PR and between 5fdbac1 and bc77d94.

📒 Files selected for processing (2)
  • src/cli/command-suggestion.ts
  • src/cli/specs/browser-command-discovery.test.ts

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

Walkthrough

The CLI now supports browser command grouping in help and command suggestions. The goto and tab create commands accept URLs as positional arguments as well as through --url. The relay connect handshake passes the accepted version and optional runtime to its callback, and the connect channel writes a formatted success message to stderr.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to bc77d

Nested browser typos no longer receive misleading top-level guidance, and browser synonyms followed by URLs recover correctly. The change is mergeable after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 11 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 identifies the main change: guiding users from incorrect browser commands to the real top-level commands.
Description check ✅ Passed The description is detailed and covers the user impact, changes, rationale, visual proof, and testing. The Linked Issue section does not include an actual issue link, and the Review section is empty.
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 💡 1
📝 Generate docstrings 💡
  • 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

🔇 Additional comments (4)
src/relay/relay-handshake.ts (1)

168-179: LGTM!

Also applies to: 216-216

src/relay/relay-connect-channel.ts (1)

4-4: LGTM!

Also applies to: 44-45

src/relay/relay-handshake-roundtrip.test.ts (1)

10-12: LGTM!

Also applies to: 130-161

src/cli/specs/browser-basic.ts-70-70 (1)

70-70: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Document both supported URL forms in usage. Both commands accept a positional URL and --url, but their usage strings show only the positional form.

  • src/cli/specs/browser-basic.ts#L70-L70: add the --url <url> alternative to the goto usage.
  • src/cli/specs/browser-basic.ts#L203-L203: add the --url <url> alternative to the tab create usage.

Based on learnings, keep flags listed in usage in parity with allowedFlags.

Source: Learnings


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7ac16491-252f-4602-9e37-92a66dcdb4df
📥 Commits

Reviewing files that changed from the base of the PR and between a3ecee0 and 5fdbac1.

📒 Files selected for processing (11)
  • src/cli/browser.test.ts
  • src/cli/command-spec.ts
  • src/cli/command-suggestion.test.ts
  • src/cli/command-suggestion.ts
  • src/cli/help.ts
  • src/cli/specs/browser-advanced.ts
  • src/cli/specs/browser-basic.ts
  • src/cli/specs/browser-command-discovery.test.ts
  • src/relay/relay-connect-channel.ts
  • src/relay/relay-handshake-roundtrip.test.ts
  • src/relay/relay-handshake.ts

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

Comment thread src/cli/command-suggestion.ts Outdated
Comment on lines +170 to +172
if (commandPath.length > 1 && isCommandGroupName(specs, group)) {
nextSteps.push(
`Orca's ${group} commands run at the top level (orca <command>, not orca ${group} <command>); list them with: orca ${group} --help`

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

Do not give top-level guidance for nested browser commands. If the user enters orca browser identity gte, this branch says browser commands do not run under browser. The valid command is orca browser identity get. Restrict this guidance to guesses outside a registered nested browser command prefix.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Agents using Orca browser commands through an SSH terminal could miss the working commands: browser --help showed only identity commands, a URL operand erased typo suggestions, navigation required --url, and every successful remote command printed a handshake diagnostic to stderr.

This change lists the existing top-level browser commands in browser help, recovers likely commands even with operands, accepts positional URLs for goto and tab create while retaining --url, and keeps successful handshake diagnostics on the SSH bridge. Review fixed contradictory advice for browser identity gett and browser identit get; those now suggest the valid identity commands without redirecting them to top-level syntax. Browser help ordering/length and an optional separate PR for diagnostic routing are deferred; neither is a proven functional defect.

Verified at bc77d94babebeed7d0dfcba523dffc48abcf6f83: architecture review, fresh review of all eight readiness categories without counsel, CLI and main-process typechecks, 91 targeted tests, changed-code quality, and independent command-registry and local relay socket checks. All final-head CI checks settled: 34 passed and 20 expected routing skips across six successful workflows (PR checks, Windows SSH hosts, other SSH hosts). The original CI failure came from an unchanged renderer test on main, repaired by the main merge from #26097. No open code findings remain.

Live remote browser/SSH QA is blocked and remains unverified. The required first QA driver failed startup before receiving the task; the safety check then found a change in the Windows host's real Codex config hash, so QA stopped before an Electron rig or test container launched. The hash alone does not establish the cause, and the config was not read or restored. There is no Electron UI change, so screenshots are not applicable; no real remote-command output is claimed as evidence. Deployed old/new release pairs, manual WSL/mobile flows and live navigation were not tested in this loop. This PR has not been merged and auto-merge has not been enabled.

This branch has not been deployed

No deployments
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