Operio Doc
CLI & Agents

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

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 create --project-id <id> --name devices --platform ios
operio environments update <environment-id> [--name <name>] [--base-url <url>] [--color <color>]
operio environments delete <environment-id>

--platform says what the environment targets and defaults to web, which needs --base-url. A mobile project's environments use --platform ios or --platform android and carry no base URL — the app under test is an installed build, and the platform tells a run which device to lease. It is fixed at creation, so update cannot change it.

create also accepts --input:

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

Credentials

Project credentials are managed independently of environments. See Auth & Credentials for how they're used during a run.

operio credentials list [--project-id <id>]
operio credentials get <credential-id>

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

operio credentials update <credential-id> --password new-secret
operio credentials update <credential-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 credentials create …) or the OPERIO_PASSWORD environment variable.

Deleting a credential 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] [--type deterministic] [--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>…] [--precondition <text>…] [--status <status>] [--type <type>] [--goal <goal>] [--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> [--wait] [--timeout 600]

From flags

Nothing here needs JSON. 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, login, and shared-steps. Only the first colon separates the type, so instructions may contain URLs. Repeat --precondition and --step as needed; flags override the same field in --input.

Test case payload

name, description, severity (critical, high, medium, low), and steps are required. --suite may only be used with active or inactive status.

Omitting status creates a draft from the CLI, even though the API creates an active test case by default. A case written by a script or an agent has not been reviewed, and an active one is immediately eligible for a run — so publishing is deliberate. Pass --status active to skip the draft.

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", "credentialId": "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
logincredentialIdSign in with a stored project credential
shared-stepssharedStepsIdInsert a reusable shared step group

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] [--full]
operio suites run <test-suite-id> --environment-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> --test-case-ids c1,c2 [--name "Nightly"] [--wait]
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]

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