mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* fix(cli): resolve host names across both kinds, and stop ssh: answering empty `--host ssh:<id>` was never validated. An unknown target filtered to nothing and returned ok:true with an empty list — the same silent wrong-machine answer that unknown `runtime:` ids gave before they were rejected. And because SSH target ids are machine-generated (`ssh-<timestamp>-<random>`) while the name anyone actually knows is the label, this fired on the ordinary spelling rather than a rare typo: every human-typed SSH name missed. The two kinds of remote machine are also reached on different axes. A paired Orca server is a connection (`--environment <name>`); an SSH target is a machine the connected host reaches (`--host ssh:<id>`). A caller only knows "the machine called X", so naming X on the wrong axis was the common failure and produced either an empty answer or a dead-end "unknown environment". Now: `ssh:` resolves labels as well as ids and rejects an unknown target with the known ones listed; `runtime:` accepts the environment name as well as its id, matching --environment, and canonicalizes to the id so stored host ids still compare; and when a name misses on one axis but exists on the other, the error says which and gives the exact flag. Candidates ride along in error.data so an agent can recover without parsing prose. `orca host list` is the discovery surface that was missing entirely — nothing in the CLI listed SSH targets, so a caller told to use one had nowhere to look. It prints this machine, the SSH targets registered on the connected host, and the paired servers, each with the selector to use. * fix(cli): give --environment the same cross-kind hint, and validate the ssh host on setup-create Two gaps a follow-up survey found in the first pass. `--environment openclaw` still dead-ended with a bare "Unknown environment" while an SSH target by that name sat right there — the inverse of the case just fixed, and the direction the report actually hit. The store's own error cannot carry the hint: translateStoreError forwards code and message and drops data. So the selector is resolved before the client is built, where the payload survives. Only the explicit flag is asserted eagerly; an ambient ORCA_ENVIRONMENT stays lazy, because failing local-only commands over stale background config would be a regression. `project setup-create` records independent metadata and, unlike the other setup paths, is not covered by the runtime's ssh rejection — so an unknown target persisted a row pointing at a machine that does not exist. It now resolves the host. `local` and `runtime:` still pass through untouched: this is also the provisioning path, where a runtime host legitimately may not exist yet when its metadata is written. `setup-existing-folder` and `setup-clone` deliberately keep the unresolved id. The runtime rejects every ssh host for those operations regardless of whether it exists, so resolving first would answer "no such target" and imply the command would have worked with the right id. * fix(cli): refuse an ambiguous host name instead of resolving the first match Name lookup took the first match while the environment store itself refuses an ambiguous name rather than guessing. That put the guess back, in the selector whose entire purpose is to stop a command reaching a machine the caller did not choose — and it applied to both spellings: two SSH targets sharing a label, and two paired servers sharing a name. Both now resolve to nothing and report every candidate with its id, so the caller picks. An exact id still resolves past a colliding name, since an id is never ambiguous. Also pins the property that makes accepting a name safe at all: `runtime:<id>` is a persisted token that lands in ProjectHostSetup.hostId and is embedded in generated setup ids, so the name is canonicalized to the id before anything downstream sees it. A test now asserts a name never reaches the wire. * fix(cli): fall back to the older ssh listing so an old host is not read as having no targets Hosts predating ssh.listTargetSummaries still answer ssh.listTargets, and both are served by the same summariser. Swallowing the method_not_found made such a host indistinguishable from one with no SSH targets registered, which would reject a target id that is valid there — a new-client/old-host regression on a path that previously passed the id through unvalidated.
662 lines
36 KiB
TypeScript
662 lines
36 KiB
TypeScript
/* eslint-disable max-lines -- Why: root and generated command help text live together so CLI discovery stays greppable. */
|
|
import type { CommandSpec } from './args'
|
|
import { findCommandSpec, isCommandGroup, supportsBrowserPageFlag } from './args'
|
|
import { unknownCommandData } from './command-suggestion'
|
|
|
|
const ROOT_HELP_TEXT = `orca
|
|
|
|
Usage: orca <command> [options]
|
|
|
|
Startup:
|
|
open Launch Orca and wait for the runtime to be reachable
|
|
serve Start a headless Orca runtime server
|
|
status Show app/runtime/graph readiness
|
|
|
|
Diagnostics:
|
|
diagnostics memory Collect a memory snapshot for Orca and managed terminals
|
|
|
|
Agent Discovery:
|
|
agent-context Print the machine-readable command schema for agents
|
|
|
|
Accounts:
|
|
account add Add a managed Claude or Codex account on this Orca host
|
|
account list List managed Claude and Codex accounts on this Orca host
|
|
|
|
Skills:
|
|
skills installed List installed skill selectors
|
|
skills share Publish selected skills behind one unlisted link
|
|
skills list List version-matched skill guides bundled with this Orca CLI
|
|
skills get Print a version-matched skill guide as Markdown
|
|
skills install Install bundled Orca skills globally via the community skills CLI
|
|
skills update Update already-installed Orca skills via the community skills CLI
|
|
|
|
Hosts:
|
|
host list List targetable machines and how to name each one
|
|
|
|
Environments:
|
|
environment add Save a remote Orca runtime from a pairing code
|
|
environment list List saved remote Orca runtimes
|
|
environment show Show one saved remote Orca runtime
|
|
environment rm Remove a saved remote Orca runtime
|
|
|
|
Environment Recipes:
|
|
vm recipe doctor Validate a per-workspace environment recipe
|
|
|
|
Automations:
|
|
automations list List scheduled Orca automations
|
|
automations show Show one Orca automation
|
|
automations create Create a scheduled Orca automation
|
|
automations edit Edit an Orca automation
|
|
automations remove Remove an Orca automation and its run history
|
|
automations run Run an Orca automation now
|
|
automations runs List automation run history
|
|
|
|
Projects:
|
|
project list List durable projects known to Orca
|
|
project setups List project host setups
|
|
project setup-existing-folder Make a project available on a host by importing an existing folder
|
|
project setup-clone Make a project available on a host by cloning a repository
|
|
project setup-create Create independent project host setup metadata
|
|
project setup-update Update project host setup metadata
|
|
project setup-delete Remove a project host setup
|
|
|
|
Repos:
|
|
repo list List repos registered in Orca
|
|
repo add Add a project to Orca by filesystem path
|
|
repo show Show one registered repo
|
|
repo set-base-ref Set the repo's default base ref for future worktrees
|
|
repo search-refs Search branch/tag refs within a repo
|
|
|
|
Worktrees:
|
|
worktree list List Orca-managed worktrees
|
|
worktree show Show one worktree
|
|
worktree current Show the Orca-managed worktree for the current directory
|
|
worktree create Create a new Orca-managed worktree
|
|
worktree set Update Orca metadata for a worktree
|
|
worktree rm Remove a worktree from Orca and git
|
|
worktree ps Show a compact orchestration summary across worktrees
|
|
|
|
Files:
|
|
file open Open a workspace file in the Orca editor
|
|
file diff Open a workspace file diff in the Orca editor
|
|
file open-changed Open all git-changed files for a workspace
|
|
|
|
Terminals:
|
|
terminal list List live Orca-managed terminals
|
|
terminal show Show terminal metadata and preview
|
|
terminal read Read bounded terminal output
|
|
terminal send Send input to a live terminal
|
|
terminal wait Wait for a terminal condition (exit, tui-idle)
|
|
terminal stop Stop terminals for a worktree
|
|
terminal create Create a terminal session in a worktree
|
|
terminal rename Set or clear the title of a terminal tab
|
|
terminal split Split an existing terminal pane
|
|
terminal switch Bring a terminal tab to the foreground
|
|
terminal focus Alias for terminal switch
|
|
terminal close Close a terminal pane/session, or its whole tab with --tab
|
|
|
|
Orchestration:
|
|
orchestration run-create Create and bind a lightweight orchestration Run
|
|
orchestration run-use Bind this coordinator terminal to an existing Run
|
|
orchestration run-current Show this terminal's bound Run
|
|
orchestration run-list List lightweight orchestration Runs
|
|
orchestration run-show Show one lightweight orchestration Run
|
|
orchestration send Send an inter-agent message
|
|
orchestration check Check the bound Run mailbox
|
|
orchestration ask Ask the coordinator a blocking question
|
|
orchestration reply Reply to a message
|
|
orchestration inbox Show all messages across recipients
|
|
orchestration task-create Create an orchestration task
|
|
orchestration task-list List orchestration tasks
|
|
orchestration task-update Update a task status
|
|
orchestration dispatch Dispatch a task to a terminal
|
|
orchestration dispatch-show Show dispatch context for a task
|
|
orchestration worker-start Start a supervised worker locally or on a connected Orca server
|
|
orchestration worker-show Inspect one supervised worker
|
|
orchestration worker-read Read bounded output from one supervised worker
|
|
orchestration worker-stop Fence one Dispatch; stop only its supervised worker
|
|
orchestration worker-abandon Fence an uncertain worker without claiming it stopped
|
|
orchestration worker-release Release a settled worker's terminal after archiving its output
|
|
orchestration worker-retain Keep a worker terminal live for debugging
|
|
orchestration worker-list Report worker terminal resource accounting
|
|
orchestration coordinator-start Start the legacy automatic coordinator loop
|
|
orchestration coordinator-stop Stop the legacy automatic coordinator loop
|
|
orchestration gate-create Create a decision gate blocking a task
|
|
orchestration gate-resolve Resolve a pending decision gate
|
|
orchestration gate-list List decision gates
|
|
orchestration reset Reset orchestration state
|
|
|
|
Computer Use:
|
|
computer capabilities Show computer-use provider capabilities
|
|
computer permissions Show or open computer-use permission setup
|
|
computer list-apps List running apps available to computer-use
|
|
computer list-windows List visible windows for a target app
|
|
computer get-app-state Capture a compact accessibility snapshot of an app
|
|
computer click Click an app element or window coordinate
|
|
computer perform-secondary-action Run an advertised accessibility action
|
|
computer scroll Scroll an app element
|
|
computer drag Drag between app elements or window coordinates
|
|
computer type-text Type literal text at the current app focus
|
|
computer press-key Press a single key such as Return or Escape
|
|
computer hotkey Press a shortcut combination such as CmdOrCtrl+A
|
|
computer paste-text Paste text through the native clipboard path
|
|
computer set-value Set the value of a settable app element
|
|
|
|
Linear:
|
|
linear Read Linear ticket context for agents
|
|
|
|
Mobile Emulator (iOS Simulator):
|
|
emulator list List available/running emulators (Orca-managed + raw serve-sim)
|
|
emulator attach <device> Attach/start helper and make active for the worktree
|
|
emulator tap <x> <y> Tap at normalized 0..1 coords (preferred for single taps)
|
|
emulator type <text> Type text (US ASCII only)
|
|
emulator gesture <json> Send begin/move/end touch points
|
|
emulator button <name> Hardware button (home, side_button, etc.)
|
|
emulator rotate <o> Rotate device (portrait|landscape_left|...)
|
|
emulator exec --command Raw serve-sim subcommand passthrough (no "serve-sim" prefix)
|
|
emulator kill Stop helper for device
|
|
|
|
Browser Automation:
|
|
tab create Create a new browser tab (navigates to --url)
|
|
tab list List open browser tabs
|
|
tab show Show one browser tab by page id
|
|
tab current Show the current browser tab
|
|
tab profile list List browser session profiles
|
|
tab profile create Create a browser session profile
|
|
tab profile delete Delete a browser session profile
|
|
tab profile set Switch a browser tab to a different profile
|
|
tab profile show Show the profile bound to a browser tab
|
|
tab profile use-default Switch a browser tab back to the default profile
|
|
tab profile clone Clone a browser tab into another profile
|
|
tab switch Switch the active browser tab by --index or --page
|
|
tab close Close a browser tab by --index/--page or the current tab
|
|
snapshot Accessibility snapshot with element refs (e.g. @e1, @e2)
|
|
goto Navigate the active tab to --url
|
|
click Click element by --element ref
|
|
fill Clear and fill input by --element ref with --value
|
|
type Type --input text at the current focus (no element needed)
|
|
select Select dropdown option by --element ref and --value
|
|
hover Hover element by --element ref
|
|
keypress Press a key (e.g. --key Enter, --key Tab)
|
|
scroll Scroll --direction (up/down) by --amount pixels
|
|
back Navigate back in browser history
|
|
reload Reload the active browser tab
|
|
screenshot Capture viewport screenshot (--format png|jpeg)
|
|
eval Evaluate --expression JavaScript in the page context
|
|
wait Wait for page idle or --timeout ms
|
|
check Check a checkbox by --element ref
|
|
uncheck Uncheck a checkbox by --element ref
|
|
focus Focus an element by --element ref
|
|
clear Clear an input by --element ref
|
|
drag Drag --from ref to --to ref
|
|
upload Upload --files to a file input by --element ref
|
|
dblclick Double-click element by --element ref
|
|
forward Navigate forward in browser history
|
|
scrollintoview Scroll --element into view
|
|
get Get element property (--what: text, html, value, url, title)
|
|
is Check element state (--what: visible, enabled, checked)
|
|
inserttext Insert text without key events
|
|
mouse move Move mouse to --x --y coordinates
|
|
mouse down Press mouse button
|
|
mouse up Release mouse button
|
|
mouse wheel Scroll wheel --dy [--dx]
|
|
find Find element by locator (--locator role|text|label --value <v>)
|
|
set device Emulate device (--name "iPhone 12")
|
|
set offline Toggle offline mode (--state on|off)
|
|
set headers Set HTTP headers (--headers '{"key":"val"}')
|
|
set credentials Set HTTP auth (--user <u> --pass <p>)
|
|
set media Set color scheme (--color-scheme dark|light)
|
|
clipboard read Read clipboard contents
|
|
clipboard write Write --text to clipboard
|
|
dialog accept Accept browser dialog (--text for prompt response)
|
|
dialog dismiss Dismiss browser dialog
|
|
storage local get Get localStorage value by --key
|
|
storage local set Set localStorage --key --value
|
|
storage local clear Clear localStorage
|
|
storage session get Get sessionStorage value by --key
|
|
storage session set Set sessionStorage --key --value
|
|
storage session clear Clear sessionStorage
|
|
download Download file via --selector to --path
|
|
highlight Highlight --selector on page
|
|
exec Run any agent-browser command (--command "...")
|
|
|
|
Common Commands:
|
|
orca open [--json]
|
|
orca serve [--port <port>] [--pairing-address <host>] [--mobile-pairing] [--no-pairing] [--project-root <path>] [--recipe-json] [--json]
|
|
orca status [--json]
|
|
orca diagnostics memory [--json]
|
|
orca agent-context [--json]
|
|
orca account add [--agent claude|codex] [--json]
|
|
orca account list [--json]
|
|
orca host list [--json]
|
|
orca environment add --name <name> --pairing-code <code> [--json]
|
|
orca environment list [--json]
|
|
orca environment show --environment <selector> [--json]
|
|
orca environment rm --environment <selector> [--json]
|
|
orca worktree list [--repo <selector>] [--limit <n>] [--json]
|
|
orca worktree create --name <name> [--repo <selector>|--project <id> [--host <host-id>]|--project-host-setup <id>] [--agent <id>] [--prompt <text>] [--setup run|skip|inherit] [--base-branch <ref>] [--issue <number>] [--linear-issue <identifier-or-url>] [--comment <text>] [--parent-worktree <selector>] [--no-parent] [--run-hooks] [--activate] [--json]
|
|
orca worktree show --worktree <selector> [--json]
|
|
orca worktree current [--json]
|
|
orca worktree set --worktree <selector> [--display-name <name>] [--issue <number|null>] [--linear-issue <identifier-or-url|null>] [--comment <text>] [--workspace-status <id>] [--parent-worktree <selector>|--no-parent] [--json]
|
|
orca worktree rm --worktree <selector> [--force] [--run-hooks] [--json]
|
|
orca worktree ps [--limit <n>] [--json]
|
|
orca file open <path> [--worktree <selector>] [--json]
|
|
orca file diff <path> [--staged] [--worktree <selector>] [--json]
|
|
orca file open-changed [--mode edit|diff|both] [--worktree <selector>] [--json]
|
|
orca terminal list [--worktree <selector>] [--limit <n>] [--include-visual-layouts] [--json]
|
|
orca terminal show [--terminal <handle>] [--json]
|
|
orca terminal read [--terminal <handle>] [--cursor <n>] [--limit <n>] [--json]
|
|
orca terminal send [--terminal <handle>] [--text <text>] [--enter] [--interrupt] [--json]
|
|
orca terminal wait [--terminal <handle>] --for exit|tui-idle [--timeout-ms <ms>] [--json]
|
|
orca terminal stop --worktree <selector> [--json]
|
|
orca terminal create [--worktree <selector>] [--title <name>] [--command <text>] [--focus] [--json]
|
|
orca terminal split [--terminal <handle>] [--direction horizontal|vertical] [--json]
|
|
orca terminal switch [--terminal <handle>] [--json]
|
|
orca terminal close [--terminal <handle>] [--tab] [--json]
|
|
orca project list [--json]
|
|
orca project setups [--project <id>] [--host <host-id>] [--json]
|
|
orca project setup-existing-folder --project <id> --host <host-id> --path <path> [--kind git|folder] [--display-name <name>] [--json]
|
|
orca project setup-clone --project <id> --host <host-id> --url <clone-url> --destination <path> [--display-name <name>] [--json]
|
|
orca project setup-create --project <id> --host <host-id> [--setup-id <id>] [--path <path>] [--kind git|folder] [--display-name <name>] [--worktree-base-path <path>] [--git-username <name>] [--state ready|not-set-up|setting-up|error|unsupported] [--method imported-existing-folder|cloned|provisioned] [--json]
|
|
orca project setup-update --setup <setup-id> [--display-name <name>] [--path <path>] [--worktree-base-path <path>] [--git-username <name>] [--kind git|folder] [--state ready|not-set-up|setting-up|error|unsupported] [--method legacy-repo|imported-existing-folder|cloned|provisioned] [--json]
|
|
orca project setup-delete --setup <setup-id> [--json]
|
|
orca repo list [--json]
|
|
orca repo add --path <path> [--json]
|
|
orca repo show --repo <selector> [--json]
|
|
orca repo set-base-ref --repo <selector> --ref <ref> [--json]
|
|
orca repo search-refs --repo <selector> --query <text> [--limit <n>] [--json]
|
|
|
|
Selectors:
|
|
--repo <selector> Registered repo selector such as id:<id>, name:<name>, or path:<path>
|
|
--worktree <selector> Worktree selector such as id:<repo-id>::<path>, name:<displayName>, branch:<branch>, issue:<number>, path:<path>, or active/current
|
|
--terminal <handle> Runtime-issued terminal handle returned by \`orca terminal list --json\`
|
|
--parent-worktree <selector> Parent worktree selector such as id:<repo-id>::<path>, branch:<branch>, issue:<number>, path:<path>, or active/current
|
|
--no-parent Force no parent lineage for unrelated worktree creation/update
|
|
|
|
Terminal Send Options:
|
|
--text <text> Text to send to the terminal
|
|
--enter Append Enter after sending text
|
|
--interrupt Send as an interrupt-style input when supported
|
|
|
|
Terminal List Options:
|
|
--include-visual-layouts Include tab and pane topology in JSON output
|
|
|
|
Wait Options:
|
|
--for exit Wait until the target terminal exits
|
|
--timeout-ms <ms> Maximum wait time before timing out
|
|
|
|
Output Options:
|
|
--json Emit machine-readable JSON instead of human text
|
|
--pairing-code <code> Connect to a remote Orca runtime using an orca://pair?... code
|
|
--environment <selector> Connect using a saved environment id or name
|
|
--help Show this help message
|
|
|
|
Behavior:
|
|
Most commands require a running Orca runtime. If Orca is not open yet, run \`orca open\` first.
|
|
Remote runtime access can also be supplied with ORCA_PAIRING_CODE or ORCA_ENVIRONMENT.
|
|
Use selectors for discovery and handles for repeated live terminal operations.
|
|
|
|
Agent Sessions And Worktrees:
|
|
\`worktree create --agent\` creates a new checkout with an agent.
|
|
To start a fresh agent in the current worktree, use:
|
|
orca terminal create --worktree active --command "codex"
|
|
|
|
Browser Workflow:
|
|
1. Create or navigate: orca tab create --url https://example.com
|
|
orca goto --url https://example.com
|
|
2. Inspect the page: orca snapshot
|
|
(Returns an accessibility tree with element refs like e1, e2, e3)
|
|
For concurrent workflows, prefer: orca tab list --json
|
|
then reuse tabs[].browserPageId with --page <id> on later commands.
|
|
3. Interact: orca click --element e2
|
|
orca fill --element e5 --value "search query"
|
|
orca keypress --key Enter
|
|
4. Re-inspect: orca snapshot
|
|
(Element refs change after navigation — always re-snapshot before interacting)
|
|
|
|
Browser Options:
|
|
--element <ref> Element ref from snapshot (e.g. @e3)
|
|
--url <url> URL to navigate to
|
|
--value <text> Value to fill or select
|
|
--input <text> Text to type at current focus (no element needed)
|
|
--expression <js> JavaScript expression to evaluate
|
|
--key <key> Key to press (Enter, Tab, Escape, Control+a, etc.)
|
|
--direction <dir> Scroll direction: up or down
|
|
--amount <pixels> Scroll distance in pixels (default: viewport height)
|
|
--index <n> Tab index (from \`tab list\`)
|
|
--page <id> Stable browser page id (preferred for concurrent workflows)
|
|
--profile <id> Browser profile id
|
|
--show-profile Include the tab's browser profile in text output
|
|
--no-ua-spoof Keep Electron's native user agent for a new profile
|
|
--format <png|jpeg> Screenshot image format
|
|
--from <ref> Drag source element ref
|
|
--to <ref> Drag target element ref
|
|
--files <path,...> Comma-separated file paths for upload
|
|
--timeout <ms> Wait timeout in milliseconds
|
|
--worktree <selector> Scope commands to a specific worktree's browser tabs
|
|
|
|
Examples:
|
|
$ orca open
|
|
$ orca status --json
|
|
$ orca diagnostics memory --json
|
|
$ orca repo list
|
|
$ orca worktree create --name agent-task --agent codex --prompt "hi"
|
|
$ orca worktree create --repo name:orca --name cli-test-1 --issue 273
|
|
$ orca worktree create --repo name:orca --name linear-task --linear-issue https://linear.app/stably/issue/STA-335/test-issue
|
|
$ orca worktree create --name linear-task --linear-issue STA-335
|
|
$ orca worktree show --worktree branch:Jinwoo-H/cli
|
|
$ orca worktree current
|
|
$ orca worktree set --worktree active --comment "waiting on review"
|
|
$ orca worktree set --worktree active --linear-issue null
|
|
$ orca worktree ps --limit 10
|
|
$ orca file open-changed --mode diff
|
|
$ orca file open src/App.tsx
|
|
$ orca terminal create --worktree active --command "codex"
|
|
$ orca terminal list --worktree path:/Users/me/orca/workspaces/orca/cli-test-1 --json
|
|
$ orca terminal send --terminal term_123 --text "hi" --enter
|
|
$ orca terminal wait --terminal term_123 --for exit --timeout-ms 60000 --json
|
|
$ orca tab current --json
|
|
$ orca tab show --page page_123 --json
|
|
$ orca tab create --url https://example.com --profile work
|
|
$ orca tab profile clone --page page_123 --profile work --json
|
|
$ orca snapshot
|
|
$ orca click --element e3
|
|
$ orca fill --element e5 --value "hello"
|
|
$ orca goto --url https://example.com/login
|
|
$ orca keypress --key Enter
|
|
$ orca eval --expression "document.title"
|
|
$ orca tab list --json`
|
|
|
|
export function printHelp(specs: CommandSpec[], commandPath: string[] = []): void {
|
|
const exactSpec = findCommandSpec(specs, commandPath)
|
|
if (exactSpec) {
|
|
console.log(formatCommandHelp(exactSpec))
|
|
return
|
|
}
|
|
|
|
if (isCommandGroup(commandPath)) {
|
|
console.log(formatGroupHelp(specs, commandPath[0]))
|
|
return
|
|
}
|
|
|
|
if (commandPath.length > 0) {
|
|
const { nextSteps } = unknownCommandData(specs, commandPath)
|
|
const recovery = nextSteps.map((step) => `Next step: ${step}`).join('\n')
|
|
console.log(`Unknown command: ${commandPath.join(' ')}${recovery ? `\n${recovery}` : ''}\n`)
|
|
}
|
|
|
|
console.log(ROOT_HELP_TEXT)
|
|
}
|
|
|
|
export function formatCommandHelp(spec: CommandSpec): string {
|
|
const lines = [`orca ${spec.path.join(' ')}`, '', `Usage: ${spec.usage}`, '', spec.summary]
|
|
const displayedFlags =
|
|
spec.argumentMode === 'passthrough'
|
|
? []
|
|
: supportsBrowserPageFlag(spec.path)
|
|
? [...spec.allowedFlags, 'page']
|
|
: spec.allowedFlags
|
|
|
|
if (displayedFlags.length > 0) {
|
|
lines.push('', 'Options:')
|
|
for (const flag of displayedFlags) {
|
|
lines.push(` ${formatCommandFlagHelp(flag, spec.path)}`)
|
|
}
|
|
}
|
|
|
|
if (spec.notes && spec.notes.length > 0) {
|
|
lines.push('', 'Notes:')
|
|
for (const note of spec.notes) {
|
|
lines.push(` ${note}`)
|
|
}
|
|
}
|
|
|
|
if (spec.examples && spec.examples.length > 0) {
|
|
lines.push('', 'Examples:')
|
|
for (const example of spec.examples) {
|
|
lines.push(` $ ${example}`)
|
|
}
|
|
}
|
|
|
|
return lines.join('\n')
|
|
}
|
|
|
|
export function formatGroupHelp(specs: CommandSpec[], group: string): string {
|
|
const groupSpecs = specs.filter((spec) => spec.path[0] === group)
|
|
const lines = [`orca ${group}`, '', `Usage: orca ${group} <command> [options]`, '', 'Commands:']
|
|
for (const spec of groupSpecs) {
|
|
lines.push(` ${spec.path.slice(1).join(' ').padEnd(18)} ${spec.summary}`)
|
|
}
|
|
lines.push('', `Run \`orca ${group} <command> --help\` for command-specific usage.`)
|
|
return lines.join('\n')
|
|
}
|
|
|
|
function formatCommandFlagHelp(flag: string, commandPath: string[]): string {
|
|
const command = commandPath.join(' ')
|
|
if (command === 'skills install' && flag === 'agent') {
|
|
return '--agent <names> Comma-separated install targets; default is detected agents'
|
|
}
|
|
if (command === 'terminal close' && flag === 'tab') {
|
|
return '--tab Close the whole tab and wait for durable persistence'
|
|
}
|
|
if (command === 'linear issue' && flag === 'id') {
|
|
return '--id <id> Linear issue key, id, or URL'
|
|
}
|
|
if (command === 'linear issue' && flag === 'workspace') {
|
|
return '--workspace <id> Connected Linear workspace id'
|
|
}
|
|
if (command === 'linear search' && flag === 'query') {
|
|
return '--query <text> Text to search across Linear issues'
|
|
}
|
|
if (command === 'linear search' && flag === 'workspace') {
|
|
return '--workspace <id|all> Connected Linear workspace id, or all'
|
|
}
|
|
if (command === 'linear list-issues' && flag === 'cursor') {
|
|
return '--cursor <cursor> Opaque cursor returned by a previous list-issues page'
|
|
}
|
|
if (command === 'artifacts list' && flag === 'cursor') {
|
|
return '--cursor <cursor> Opaque cursor returned by a previous artifacts page'
|
|
}
|
|
if (command === 'orchestration worker-read' && flag === 'cursor') {
|
|
return '--cursor <cursor> Opaque cursor returned by a previous worker-read page'
|
|
}
|
|
if (command === 'orchestration worker-list' && flag === 'terminal-state') {
|
|
return '--terminal-state <state> Terminal accounting filter: active, reclaimable, retained, release_pending, release_unknown, or released'
|
|
}
|
|
if (command === 'linear list-issues' && flag === 'workspace') {
|
|
return '--workspace <id|all> Connected Linear workspace id, or all'
|
|
}
|
|
if (command.startsWith('linear ') && flag === 'workspace') {
|
|
return '--workspace <id> Connected Linear workspace id'
|
|
}
|
|
if (command.startsWith('linear ') && flag === 'body') {
|
|
return '--body <text> Linear comment or issue body'
|
|
}
|
|
if (command.startsWith('linear ') && flag === 'body-file') {
|
|
return '--body-file <path|-> Read Linear body from a file or stdin'
|
|
}
|
|
if (command.startsWith('linear ') && flag === 'write-id') {
|
|
return '--write-id <uuid> Retry id from linear_write_unconfirmed'
|
|
}
|
|
if (command.startsWith('linear ') && flag === 'to') {
|
|
return '--to <state> Exact Linear workflow state name'
|
|
}
|
|
if (command === 'linear comment add' && flag === 'reply-to') {
|
|
return '--reply-to <id> Comment id to reply to'
|
|
}
|
|
if (command === 'linear attach' && flag === 'url') {
|
|
return '--url <url> Absolute http(s) link to attach'
|
|
}
|
|
if (command === 'linear attach' && flag === 'title') {
|
|
return '--title <text> Attachment title'
|
|
}
|
|
if (command === 'linear create' && flag === 'title') {
|
|
return '--title <text> New Linear issue title'
|
|
}
|
|
if (command === 'linear create' && flag === 'team') {
|
|
return '--team <key> Linear team key'
|
|
}
|
|
if (command === 'linear create' && flag === 'parent') {
|
|
return '--parent <id> Parent Linear issue key, id, or URL'
|
|
}
|
|
if (command === 'linear create' && flag === 'parent-current') {
|
|
return '--parent-current Use the current linked issue as parent'
|
|
}
|
|
if (command === 'worktree create' && flag === 'parent-worktree') {
|
|
return '--parent-worktree <selector> Parent selector such as active/current, id:<repo-id>::<path>, branch:<branch>, issue:<number>, path:<path>, folder:<id>, or worktree:<worktreeId>'
|
|
}
|
|
if (command === 'orchestration task-create' && flag === 'task-title') {
|
|
return '--task-title <text> Concise title for the orchestration task'
|
|
}
|
|
if (command === 'orchestration task-create' && flag === 'display-name') {
|
|
return '--display-name <text> UI label shown for dispatched worker rows'
|
|
}
|
|
// Why: the shared --agent help describes launching a TUI agent in a terminal,
|
|
// which is the wrong meaning here — this selects the account provider.
|
|
if (command === 'account add' && flag === 'agent') {
|
|
return '--agent <id> Account provider: claude or codex (default claude)'
|
|
}
|
|
if (flag === 'key' && command === 'computer hotkey') {
|
|
return '--key <key-combo> Modifier chord with one key, e.g. CmdOrCtrl+A'
|
|
}
|
|
if (flag === 'key' && command === 'computer press-key') {
|
|
return '--key <key> Single key, e.g. Return, Escape, Tab, Left, or PageUp'
|
|
}
|
|
return formatFlagHelp(flag)
|
|
}
|
|
|
|
export function formatFlagHelp(flag: string): string {
|
|
const helpByFlag: Record<string, string> = {
|
|
agent: '--agent <id> Launch a known TUI agent in the first terminal',
|
|
'base-branch': '--base-branch <ref> Base branch/ref to create the worktree from',
|
|
command: '--command <text> Command to run in the terminal on startup',
|
|
comment: '--comment <text> Comment stored in Orca metadata',
|
|
cursor: '--cursor <n> Line cursor from a previous read (returns only new output)',
|
|
action: '--action <name> Secondary accessibility action name',
|
|
activate: '--activate Reveal the new worktree in the Orca app',
|
|
app: '--app <app> App name, bundle ID, or pid:N',
|
|
direction:
|
|
'--direction <dir> Direction: up|down|left|right for scroll, horizontal|vertical for split',
|
|
'display-name': '--display-name <name> Override the Orca display name',
|
|
'element-index': '--element-index <n> Element index from get-app-state',
|
|
title: '--title <text> Custom title for the terminal tab (omit to reset)',
|
|
enter: '--enter Append Enter after sending text',
|
|
force: '--force Force worktree removal when supported',
|
|
focus: '--focus Reveal the created terminal session in Orca',
|
|
for: '--for exit|tui-idle Wait condition to satisfy',
|
|
'from-element-index': '--from-element-index <n> Source element index from get-app-state',
|
|
'from-x': '--from-x <x> Source window-local x coordinate',
|
|
'from-y': '--from-y <y> Source window-local y coordinate',
|
|
help: '--help Show this help message',
|
|
'include-visual-layouts':
|
|
'--include-visual-layouts Include tab and pane topology in JSON output',
|
|
interrupt: '--interrupt Send as an interrupt-style input when supported',
|
|
id: '--id <id> Identifier for a target item or permission',
|
|
issue: '--issue <number|null> Linked GitHub issue number',
|
|
'linear-issue':
|
|
'--linear-issue <id|url|null> Linked Linear issue identifier or URL; null clears on set',
|
|
json: '--json Emit machine-readable JSON',
|
|
key: '--key <key> Key argument for this command',
|
|
limit: '--limit <n> Maximum number of rows to return',
|
|
local: '--local Target the current project instead of the global install',
|
|
skill: '--skill <name> Bundled skill to act on; repeat for several',
|
|
mode: '--mode <mode> Mode such as edit, diff, or both',
|
|
model: '--model <id> Provider model id for a new agent launch',
|
|
effort: '--effort <level> Reasoning effort for the selected model',
|
|
'mouse-button': '--mouse-button <btn> Mouse button: left, right, or middle',
|
|
modifiers: '--modifiers <chord> Modifier keys held only for this click',
|
|
name: '--name <name> Name for the new worktree or automation',
|
|
'no-parent': '--no-parent Force no parent lineage for unrelated work',
|
|
'no-screenshot': '--no-screenshot Skip screenshot capture after the operation',
|
|
pages: '--pages <n> Number of scroll pages',
|
|
'parent-worktree':
|
|
'--parent-worktree <selector> Parent worktree selector such as id:<repo-id>::<path>, branch:<branch>, issue:<number>, path:<path>, or active/current',
|
|
path: '--path <path> Path argument for the command',
|
|
prompt: '--prompt <text> Prompt text for agent-backed commands',
|
|
query: '--query <text> Search text for matching refs',
|
|
ref: '--ref <ref> Base ref to persist for the repo',
|
|
repo: '--repo <selector> Repo selector such as id:<id>, name:<name>, or path:<path>',
|
|
'restore-window':
|
|
'--restore-window Bring the target app/window forward before the operation',
|
|
session: '--session <id> Snapshot namespace for a related computer-use workflow',
|
|
setup: '--setup run|skip|inherit Setup policy for repo-defined setup hooks',
|
|
terminal: '--terminal <handle> Runtime-issued terminal handle',
|
|
text: '--text <text> Text payload to send or type',
|
|
'text-stdin': '--text-stdin Read text payload from stdin',
|
|
'task-id': '--task-id <id> Task id to include in orchestration payload JSON',
|
|
'task-title': '--task-title <text> Concise title for an orchestration task',
|
|
'dispatch-id': '--dispatch-id <id> Dispatch id to include in orchestration payload JSON',
|
|
'files-modified': '--files-modified <csv> Comma-separated files for orchestration payload JSON',
|
|
'report-path': '--report-path <path> Report path to include in orchestration payload JSON',
|
|
phase: '--phase <text> Worker phase to include in orchestration payload JSON',
|
|
'timeout-ms': '--timeout-ms <ms> Maximum wait time before timing out',
|
|
'to-element-index': '--to-element-index <n> Destination element index from get-app-state',
|
|
'to-x': '--to-x <x> Destination window-local x coordinate',
|
|
'to-y': '--to-y <y> Destination window-local y coordinate',
|
|
worktree:
|
|
'--worktree <selector> Worktree selector such as id:<repo-id>::<path>, name:<displayName>, branch:<branch>, issue:<number>, path:<path>, or active/current',
|
|
workspace: '--workspace <selector> Existing worktree selector for automation runs',
|
|
'workspace-status':
|
|
'--workspace-status <id> Board status id (defaults: todo, in-progress, in-review, completed)',
|
|
staged: '--staged Open staged source-control changes',
|
|
provider: '--provider <agent> Agent id such as codex, claude, or gemini',
|
|
'source-context':
|
|
'--source-context <json|null> Explicit TaskSourceContext for automation task/provider data',
|
|
trigger: '--trigger <schedule> Automation schedule preset, cron, or RRULE',
|
|
schedule: '--schedule <schedule> Alias for --trigger',
|
|
time: '--time <HH:MM> Time used with daily/weekdays/weekly presets',
|
|
day: '--day <0-6> Day used with weekly preset, Sunday=0',
|
|
timezone: '--timezone <tz> IANA timezone for the automation',
|
|
enabled: '--enabled Enable the automation',
|
|
disabled: '--disabled Disable the automation',
|
|
'reuse-session':
|
|
'--reuse-session Reuse the previous live session for existing-workspace runs',
|
|
'fresh-session': '--fresh-session Disable session reuse for future runs',
|
|
'workspace-mode': '--workspace-mode <mode> existing or new-per-run',
|
|
'missed-run-grace-minutes': '--missed-run-grace-minutes <n> Missed-run grace window',
|
|
'value-stdin': '--value-stdin Read set-value payload from stdin',
|
|
'window-id': '--window-id <id> Target a window id from list-windows',
|
|
'window-index': '--window-index <n> Target a window index from list-windows',
|
|
// Browser automation flags
|
|
element: '--element <ref> Element ref from snapshot (e.g. e3)',
|
|
url: '--url <url> URL to navigate to',
|
|
value: '--value <text> Value to fill or select',
|
|
input: '--input <text> Text to type at current focus',
|
|
expression: '--expression <js> JavaScript expression to evaluate',
|
|
amount: '--amount <pixels> Scroll distance in pixels',
|
|
index: '--index <n> Tab index to switch to',
|
|
page: '--page <id> Stable browser page id from `orca tab list --json`',
|
|
profile: '--profile <id> Browser profile id',
|
|
'show-profile': '--show-profile Include tab profile in text output',
|
|
'no-ua-spoof': "--no-ua-spoof Keep Electron's native user agent",
|
|
format: '--format <png|jpeg> Screenshot image format'
|
|
}
|
|
|
|
if (flag === 'current') {
|
|
return '--current Use the current Orca worktree linked Linear issue'
|
|
}
|
|
if (flag === 'comments') {
|
|
return '--comments Include threaded Linear comments'
|
|
}
|
|
if (flag === 'children') {
|
|
return '--children Include recursive child issues'
|
|
}
|
|
if (flag === 'depth') {
|
|
return '--depth <n> Child issue depth for --children/--full'
|
|
}
|
|
if (flag === 'attachments') {
|
|
return '--attachments Include attachment metadata and URLs'
|
|
}
|
|
if (flag === 'relations') {
|
|
return '--relations Include blocking, related, and duplicate links'
|
|
}
|
|
if (flag === 'activity') {
|
|
return '--activity Include issue field-change history'
|
|
}
|
|
if (flag === 'full') {
|
|
return '--full Include all supported V1 issue context within caps'
|
|
}
|
|
|
|
return helpByFlag[flag] ?? `--${flag}`
|
|
}
|