Skip to content

CLI Reference

The qirabot command runs a task end-to-end without writing Python. It ships in the core package. android, ios, and desktop --window-title/--hwnd run on the built-in backends and need no extras. Only browser (qirabot[browser]), whole-screen desktop (qirabot[desktop]), and the Appium engine (qirabot[appium]) need one.

bash
# Browser (needs qirabot[browser] + `playwright install chromium`)
qirabot browser "Search for SpaceX and get the first sentence of the article" --url wikipedia.org

# Browser — headless/viewport; a persistent profile; or take over a running Chrome via CDP
qirabot browser "..." --headless --viewport 1920x1080
qirabot browser "..." --user-data-dir ~/.qira-profile --channel chrome
qirabot browser "..." --cdp-url http://localhost:9222

# Android — direct over adb (built in; only needs the adb binary, no server)
qirabot android "Open settings and turn on airplane mode"
qirabot android "..." -d emulator-5554 --app-package com.android.settings

# iOS — direct to WebDriverAgent (built in; WDA must be running on :8100)
qirabot ios "Send hi to Alice on WeChat" --bundle-id com.tencent.xin

# Either can go through an Appium server instead (needs qirabot[appium])
qirabot android "..." --appium-url http://localhost:4723
qirabot ios "..." --device "iPhone 15"   # simulators only (selects Appium)

# Desktop via pyautogui (needs qirabot[desktop])
qirabot desktop "Create a new note titled Groceries" --app Notes

# Desktop bound to ONE Windows window (built in) — DirectInput scancode input
qirabot desktop "Open the inventory and list all items" --window-title "Genshin"
qirabot desktop "..." --hwnd 132456

# Mount domain knowledge for the run — game rules, business terms (32KB total)
qirabot browser "Buy 10 stamina potions in the shop" -k game-rules.md -k gm-policy.md

# Environment check — Python, Google Cloud credentials (ADC), backend deps
qirabot doctor

# Model overview — Vertex providers, default models, credential status
qirabot models

Commands

CommandPurpose
browser INSTRUCTIONRun an AI task in a local browser (Browser backend)
android INSTRUCTIONRun an AI task on an Android device (adb direct, built in; --appium-url for Appium)
ios INSTRUCTIONRun an AI task on an iOS device (WDA direct, built in; --appium-url/--device for Appium)
desktop INSTRUCTIONRun an AI task on the desktop screen (pyautogui; --window-title/--hwnd binds one Windows window, built in)
install-browserOne-time Chromium download for the browser backend
open-browserOpen a browser to log in to websites by hand; the session persists in --user-data-dir for later runs
doctorCheck Python, Google Cloud credentials (ADC + project), and per-backend dependencies
modelsPrint the built-in Vertex providers with their default models, the session default model, and whether the configured auth (API key and/or ADC) resolves
skill install [AGENT]Copy the bundled Agent Skill into an AI agent's skills directory
skill uninstall [AGENT]Remove the skill installed by skill install
skill listShow known skills directories and the installed skill version

Global options

Global options go before the subcommand (they configure the Vertex AI connection):

bash
qirabot --vertex-project my-gcp-project --vertex-location global browser "..."

The project resolves in this order: --vertex-project flag > QIRA_VERTEX_PROJECT env var > GOOGLE_CLOUD_PROJECT > the ADC credentials' own project id. The location: --vertex-location > QIRA_VERTEX_LOCATION > GOOGLE_CLOUD_LOCATION > global. Also available: --version.

--vertex-api-key (or QIRA_VERTEX_API_KEY) authenticates with a Vertex AI API key instead of ADC, so no gcloud setup is needed. It's a Google Cloud API key, not an AI Studio key; it only covers gemini-vertex models, always uses the global endpoint, and overrides --vertex-project/--vertex-location.

--gemini-api-key (or QIRA_GEMINI_API_KEY / GEMINI_API_KEY) is the AI Studio API key for the gemini provider, which calls the Gemini Developer API instead of Vertex; no Google Cloud is involved (-m gemini/gemini-3.8-flash).

--service-tier (or QIRA_SERVICE_TIER) picks the consumption tier — flex for roughly half price on slower, sheddable capacity, priority for a premium on capacity served ahead of standard traffic. Add --tier-escalation to retry one rung up when a tier runs out of capacity instead of failing the run. Both need the global endpoint and a model that supports them; see Configuration.

The model is a task-command option (-m/--model, below) and resolves: -m flag > QIRA_MODEL env var > the built-in default gemini-vertex/gemini-3.8-flash. A bare provider name selects that provider's default model (geminigemini-3.8-flash).

Exit codes

The exit codes are script-friendly: 0 task succeeded, 1 task failed or any error, 130 interrupted with Ctrl+C. This means qirabot browser "..." && next-step only proceeds on success.

Machine-readable output

--output-format json makes stdout carry exactly one JSON result object (the human-readable output is suppressed; exit codes are unchanged):

json
{
  "type": "result",
  "success": true,
  "status": "completed",
  "output": "Signed in and reached the dashboard",
  "task_id": "1a2b3c4d",
  "usage": {
    "ai_steps": 6,
    "input_tokens": 48210,
    "output_tokens": 3120,
    "thinking_tokens": 0,
    "cache_read_tokens": 12040,
    "cache_write_tokens": 0,
    "step_duration_ms": 41830,
    "llm_decision_duration_ms": 28510,
    "total_tokens": 63370
  },
  "report": "qira_runs/2026-08-03/143012-1a2b3c4d/report.html"
}

status is completed / goal_failed / max_steps / error / cancelled: the same values as the SDK's RunResult.status, plus cancelled for Ctrl+C and the ESC kill switch. success is true only for completed. report is null when reporting is off; the file itself is written as the process exits, so read it after the CLI returns.

--output-format stream-json emits NDJSON: one JSON object per line, flushed per step, for tools that supervise a run live:

{"type": "start", "task_id": "1a2b3c4d", "max_steps": 20}
{"type": "step", "step": 1, "action_type": "click", "params": {"locate": "Login button"}, "decision": "...", ...}
{"type": "step", "step": 2, "action_type": "input", ...}
{"type": "result", "success": true, ...}

step lines carry the same fields as the SDK's StepResult (step, action_type, params, decision, output, finished, per-step token and duration counts); the final result line is identical to the json format's object. Errors that stop the run, including setup failures such as an unreachable device, still end with a result object (status: "error"), so a consumer always sees one terminal line.

Shared run options

browser / android / ios / desktop all take:

OptionDefaultWhat it does
-n, --namederived from the instructionRun name shown in the HTML report
-m, --modelQIRA_MODEL, else gemini-vertex/gemini-3.8-flashModel as {provider}/{model}, provider one of gemini-vertex / gemini (see Configuration)
--thinking-levelengine defaultThinking override: minimal / low / medium / high (see Configuration)
--media-resolutionQIRA_MEDIA_RESOLUTION, else highScreenshot detail the model sees: low / medium / high / ultra_high (Gemini only; ultra_high needs a Gemini 3 model); lower it to cut image tokens per step
-l, --languageinstruction's languageResponse language: a tag (zh, ja, de, …) or any language name
--max-steps20Step budget for the AI task
-k, --knowledgeKnowledge file the AI consults during the task (UTF-8 text; repeatable, 32KB total). Same rules as bot.ai(knowledge=...): files only, no URLs; fetch remote sources yourself first
--report / --no-reportonWrite an HTML run report
--report-dir./qira_runs/...Report output root (env QIRA_REPORT_DIR)
--annotate / --no-annotateonCrosshair click/type coordinates on saved screenshots
--overlay / --no-overlayonAlways-on-top progress window, plus the hold-ESC kill switch that rides it (macOS/Windows; a silent no-op elsewhere). See Progress Overlay & Kill Switch
--recordoffRecord the run to recording.mp4 (see below)
--output-formattextjson / stream-json for machine-readable stdout (see Machine-readable output)

Per-command options

Options for browser (see the Browser backend):

OptionDefaultWhat it does
-u, --urlURL to open (AI navigates if omitted)
--headlessoffHeadless mode (auto-on when there's no display)
--viewport1280x800Viewport as WIDTHxHEIGHT
--channelbundled ChromiumUse an installed browser: chrome, msedge, …
--user-data-dirPersistent profile dir (cookies/logins survive runs)
--browser-argExtra Chromium launch arg, repeatable
--cdp-urlAttach to a running Chrome via CDP; mutually exclusive with the four options above

Options for android (see the Android backend):

OptionDefaultWhat it does
-d, --devicethe only connected deviceadb serial from adb devices
--app-packageApp package to launch (e.g. com.android.settings)
--app-activityApp activity to launch
--appium-urldirect adb, no serverPassing it switches to the Appium engine
--recordoffRecord the device screen (adb screenrecord / Appium API)

Options for ios (see the iOS backend):

OptionDefaultWhat it does
--wda-urlhttp://127.0.0.1:8100WebDriverAgent URL; this selects the device (USB real device: iproxy 8100 8100)
--bundle-idApp bundle id to launch (e.g. com.tencent.xin)
--deviceSimulator device type from xcrun simctl list devicetypes; switches to the Appium engine, simulators only (no -d short: switching engines is deliberate)
--appium-urldirect WDA, no serverAppium server URL (with --device)
--recordoffRecord the device screen (WDA MJPEG + ffmpeg / Appium API)
--mjpeg-url--wda-url host on port 9100MJPEG stream override for --record

Options for desktop (see Desktop and Windows & Games):

OptionDefaultWhat it does
--appLaunch/activate an app first (macOS: name or bundle id; Windows: exe/registered name/UWP id; Linux: executable)
--app-wait2.0Seconds to wait for the window after --app
--window-titleBind to the window matching this title regex (Windows window backend)
--hwndBind to a window handle, decimal (Windows window backend)
--ambiguouserrorWhen several windows match --window-title: error fails listing them; largest picks the biggest matching window

skill install [AGENT] installs the bundled Agent Skill (SKILL.md, preflight script, API reference, starter templates), version-matched to the installed qirabot. AGENT is one of agents (the shared .agents/skills convention used by Codex, Cursor, Gemini CLI, and others), claude, codex, cursor; any other tool is targeted via --dir PATH. --project targets the project-level directory under the current directory instead of the user-level one. Rerun after uv tool upgrade qirabot to upgrade; a directory the command didn't create is never overwritten without --force. For Claude Code the plugin marketplace remains the recommended install (it auto-updates). skill uninstall takes the same target options; skill list shows what's installed where.

--record saves recording.mp4 into the run dir and embeds it in the HTML report. What gets recorded differs per target:

  • browser / desktop record the host screen via ffmpeg (ffmpeg must be on PATH). With a window bound (--window-title/--hwnd), the recording follows that window.
  • android records the device screen: adb screenrecord on the default engine, or Appium's recording API on the Appium engine.
  • ios records the device screen: WDA's MJPEG stream on the default engine (needs ffmpeg; a USB real device also needs iproxy 9100 9100), or Appium's recording API on the Appium engine.

Recording mechanics, report layout, and audio capture are covered in Reports & Recording. Runs honor the same env vars as the SDK (QIRA_REPORT_DIR, QIRA_SETTLE_SECONDS, QIRA_RECORD*, and so on); the full list is in Configuration.

Released under the MIT License.