Operio Docs

Command reference

Every Operio CLI command, grouped by resource

Run operio --help, or operio <group> --help, for the authoritative list at the version you have installed.

Authentication

operio auth login       # Browser login
operio auth status      # Show the current user
operio auth logout      # Clear stored credentials

operio login            # Aliases kept for compatibility
operio logout
operio whoami           # User, org, and the selected team and project
operio update           # Upgrade a global install to the latest version

Agent skill

operio skill install [--global | --dir <skills-dir>] [--force]
operio skill show       # Print SKILL.md

install copies the skill bundled with this CLI version into ./.claude/skills/operio (or ~/.claude/skills/operio with --global). It refuses to overwrite a copy that differs unless you pass --force. See Use a coding agent.

See The CLI for the login flow.

Team and project

operio teams list
operio teams use <team-id>

operio projects list [--limit 100] [--offset 0]
operio projects create --name "Web app" [--type web]
operio projects use <project-id>

auth login selects a team for you — the one your session already belongs to, or the first available — so projects list works immediately. Use teams use to change it. Selecting a team clears the selected project, since a project belongs to exactly one team.

teams use confirms in plain text rather than JSON — it records a choice, so there is nothing to parse back.

Project names accept English letters, digits, and single spaces between words (^[a-zA-Z0-9]+(?: [a-zA-Z0-9]+)*$). Hyphens and underscores are rejected — use composer test, not composer-test.

Environments

operio environments list [--project-id <id>]
operio environments get <environment-id>
operio environments create --project-id <id> --name staging --base-url https://staging.example.com
operio environments update <environment-id> [--name <name>] [--base-url <url>]
operio environments delete <environment-id>

Environments are web run targets and require --base-url. Mobile projects target an uploaded build directly and do not require an environment.

create also accepts --input:

operio environments create --input '{
  "name": "production",
  "baseUrl": "https://app.example.com"
}'

Builds (mobile)

operio builds list [--project-id <id>] [--platform ios|android]
operio builds get <build-id>
operio builds upload --file ./app.apk [--project-id <id>] [--name Nightly]

upload stores the binary and registers it as a runnable build in one step. The app ID, version, and build number are read from the file. Supported files are a zipped .app (iOS Simulator) or .apk. Device .ipa files are not supported. See Uploading Builds.

Test accounts

Project test accounts are managed independently of environments. See Test accounts for how they're used during a run.

operio test-accounts list [--project-id <id>]
operio test-accounts get <test-account-id>

operio test-accounts create --project-id <id> --label demo --username alex@demo.com --password-stdin
operio test-accounts create --type google --label gmail --username user@gmail.com --password secret
operio test-accounts create --type phone --label sms --username +15551234567 --password 123456

operio test-accounts update <test-account-id> --password new-secret
operio test-accounts update <test-account-id> --label "Primary Admin"
Type--username--password
password (default)Username or emailPassword
googleGoogle account emailGoogle password — used for "Sign in with Google" flows
phoneTest phone numberThe fixed OTP code that account always accepts

--password lands in your shell history and in ps output. Prefer --password-stdin (printf '%s' "$SECRET" | operio test-accounts create …) or the OPERIO_PASSWORD environment variable.

Deleting a test account is only available in the web app: it leaves dangling login steps in any test case that used it, which the CLI cannot show you.

Test cases

operio tests list [--project-id <id>] [--status active] [--severity high] [--name <name>] [--created-by <id>] [--limit 100] [--offset 0]
operio tests get <test-case-id>
operio tests create [--name <name>] [--description <text>] [--severity <severity>] [--step <type:value>…] [--status <status>] [--tag-ids <ids>] [--input <json|file|->] [--project-id <id>] [--suite <test-suite-id>…] [--full]
operio tests update <test-case-id> [--name <name>] [--severity <severity>] [--step <type:value>…] [--input <json|file|->] [--full]
operio tests activate <test-case-id> [--full]
operio tests deactivate <test-case-id> [--full]
operio tests run <test-case-id> (--environment-id <id> | --build-id <id>) [--wait] [--timeout 600]

From flags

Steps use <type>:<value> and run in flag order:

operio tests create \
  --name "Guest checkout" \
  --description "A guest can buy without an account" \
  --severity high \
  --step "action:Add the first item to the cart" \
  --step wait:2 \
  --step "verify:The cart badge shows 1 item"

Step types are action, verify, wait, screenshot, and login. Only the first colon separates the type, so instructions may contain URLs. Repeat --step as needed; flags override the same field in --input.

Test case payload

name, description, severity (critical, high, medium, low), and steps are required. Repeat --suite to add the case to multiple suites; it may only be used with active or inactive status. JSON input uses testSuiteIds.

Omitting status creates a draft from the CLI. The API defaults to active. Review the case before publishing, or pass --status active to create it as published.

tests activate publishes a draft or inactive case. tests deactivate returns an active one to inactive, excluding it from runs without deleting it. Only active test cases can be included in a run.

{
  "name": "Checkout",
  "description": "Complete a purchase as a signed-in customer",
  "severity": "high",
  "steps": [
    { "order": 1, "type": "login", "testAccountId": "cred-id" },
    { "order": 2, "type": "action", "instruction": "Open the checkout page" },
    { "order": 3, "type": "wait", "seconds": 5 },
    { "order": 4, "type": "screenshot", "label": "Order summary" },
    { "order": 5, "type": "verify", "assertion": "The order total is visible" }
  ]
}

Step types

Every step has a positive integer order and a type. Each type carries exactly the fields it needs — nothing else.

TypeRequired fieldMeaning
actioninstructionSomething to do, in plain English
verifyassertionSomething that must be true. Only verify failures fail a run
waitseconds (1–180)A fixed pause
screenshotlabelCapture the current view and file it under this name
logintestAccountIdSign in with a stored project test account

severity belongs to the test case, not to a step.

Field names changed

Earlier versions used a single action field on every step, plus waitSeconds on wait steps. Steps now use instruction (action), assertion (verify), and seconds (wait). Update stored JSON payloads when you upgrade.

Test suites

operio suites list [--project-id <id>]
operio suites get <test-suite-id> [--full]
operio suites create --name Smoke [--test-case-ids c1,c2] [--priority high] [--order-strategy suite_order] [--execution-mode sequential|parallel] [--start-from start|previous_test_case] [--preparation-test c0] [--full]
operio suites run <test-suite-id> (--environment-id <id> | --build-id <id>) [--wait] [--timeout 600]

Runs and results

operio runs create --input '{"projectId":"…","environmentId":"…","testCaseIds":["…"]}' [--wait] [--timeout 600]
operio runs create --project-id <id> (--environment-id <id> | --build-id <id>) --test-case-ids c1,c2 [--name "Nightly"] [--wait]
operio runs explore --goal "Buy the cheapest item as a guest" (--environment-id <id> | --build-id <id>) [--project-id <id>] [--name "Explore checkout"] [--wait] [--timeout 600]
operio runs list [--project-id <id>] [--status running] [--test-case-id <id>] [--start-date <iso>] [--end-date <iso>] [--limit 100] [--offset 0]
operio runs get <run-id> [--full]
operio runs stop <run-id>

operio results get <test-case-id> <result-id> [--full]

Run commands require exactly one target: --environment-id for a web project or --build-id for a mobile project. In --input JSON, the corresponding mobile field is mobileBuildId.

Exploratory runs

runs explore starts an exploratory run: instead of executing test cases, the agent works toward a plain-English --goal (up to 1000 characters) and reports what it found. It takes the same targets, --name, --wait, and --timeout as runs create, and --input accepts {"goal":"…","environmentId":"…"}. The run's summary includes its type and goal; runs get <run-id> --full returns the agent's complete result.

--wait

--wait polls until the run reaches a terminal state or --timeout seconds elapse (default 600), then prints a single final run summary on stdout.

The exit code carries the verdict:

  • 0 — the run completed and every case passed
  • 1 — the run completed with failing cases, or the run itself failed, errored, or was stopped

That's what makes --wait usable directly as a CI gate:

operio suites run "$SUITE_ID" --environment-id "$ENV_ID" --wait || exit 1

Pagination

tests list and runs list accept --limit and --offset and return pagination metadata (limit, offset, total, hasMore) alongside the page of items. Other list commands return the full collection.

operio tests list --limit 50 --offset 50

On this page