AI vision-driven GUI automation across browsers, mobile, desktop, and games
Project description
Qirabot Python SDK
English | 简体中文
Cross-platform GUI automation, driven by multimodal AI vision. Drive browsers, mobile apps, full desktops, and games through pixels — no DOM, no selectors — reaching what frameworks like Playwright, Selenium, and Appium cannot.
Run it standalone (bot.open() launches a browser for you; Android / iOS / Windows-window backends are built in with zero extra dependencies), bolt it onto your existing Playwright / Selenium / Appium / pyautogui session, drop it into a pytest suite, or bind by HWND to drive a Unity / Unreal / native desktop game. Same API across all of them.
📖 Full documentation: qirabot.com/docs (中文)
See it work
Real, unedited runs — the AI sees only pixels. Click a poster to watch (all demos →):
Play an MMORPG from zero to level 15, hands-free — iOS real device · script
|
Clear AFK Journey's tutorial and reach the open world — iOS real device |
Play chess on lichess.org — Android real device |
Beat a fruit tile-match game on its own — Android real device |
Installation
One line — installs uv, qirabot (isolated, never touches your system Python), and Chromium. No pre-installed Python required:
# macOS / Linux
curl -LsSf https://qirabot.com/install | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://qirabot.com/install.ps1 | iex"
Driving a device instead of a browser? The Android (adb), iOS (WDA), and Windows single-window backends are built into the core package:
uv tool install qirabot # Android + iOS + Windows window; zero extras
pip, virtualenvs, per-framework extras, and troubleshooting:
Installation guide.
Whichever path you took, qirabot doctor reports what is installed, what is
missing (with the exact fix), and whether your API key reaches the server.
Quick Start
Save your API key once (get it from your dashboard):
qirabot login
Then hand the AI a task. Real, unedited output:
$ qirabot browser "Search for SpaceX and get the first sentence of the article" --url wikipedia.org
Task: 6237d4ff-b96b-4c7d-addb-30d8a0334970
[1/20] type_text ← "SpaceX"
└ Type 'SpaceX' into the Wikipedia search bar and press enter to search.
Done: Space Exploration Technologies Corp., doing business as SpaceX, is an
American spaceflight, telecommunications, and artificial intelligence
company headquartered at the Starbase development site in Starbase, Texas.
Every run writes an HTML report with per-step screenshots; --record
captures a video of the whole run.
Python SDK
The CLI is powered by the same engine. Call bot.ai() from Python and the AI
likewise looks at the screen, decides the next action, and loops until the
task is done — except the result lands directly in your code:
from qirabot import Qirabot
bot = Qirabot()
page = bot.open("https://www.wikipedia.org")
result = bot.ai(page, "Search for SpaceX and get the first sentence of the article")
print(f"Success: {result.success}")
print(f"Result: {result.output}")
bot.close()
Prefer to drive each step yourself? The same natural-language targeting works
as single-step calls — bot.click(page, "Login button"),
bot.extract(...), bot.verify(...) — with your code in control.
Bolt onto your existing stack
No rewrite: pass your existing page / driver / device object and mix AI
steps with the selectors you already have. Add AI where selectors hurt —
visual assertions, dynamic widgets, and flows too tedious to script:
import pytest
from qirabot import Qirabot
@pytest.fixture(scope="session")
def bot():
with Qirabot(task_name="test-checkout") as bot: # one task per run
yield bot
def test_checkout(page, bot): # `page` is your pytest-playwright fixture
page.goto("https://shop.example.com")
page.fill("#username", "test_user") # your selectors, as-is
page.click("#login-btn")
# Visual assertion — survives markup rewrites and CSS refactors
assert bot.verify(page, "the product grid shows items with prices and no error banner")
# One line replaces a page of brittle selector steps
result = bot.ai(page, "Complete checkout, name John Doe zip 10001", max_steps=8)
assert result.success
Works the same for Selenium, Appium, pyautogui, and the built-in device
backends (AdbDevice, WdaClient, Window) — and anything else via a
7-primitive custom adapter.
Custom tools: let the AI call your code
Mid-task, the AI isn't limited to clicking and typing. custom_tools
registers plain Python functions the model can invoke as it works — hit an
internal API, query a database, fetch an OTP from your mail server, seed test
data, or pause for a human at a CAPTCHA. Name, description, and parameters are
introspected from the function itself:
def gm_command(command: str) -> str:
"""Send a command to the game's GM backend and return its reply.
Available commands: add_energy <amount>, add_gold <amount>"""
return requests.post(GM_URL, json={"cmd": command}, timeout=10).text
result = bot.ai(
device,
"Complete every daily quest. If an out-of-energy popup appears, "
"use gm_command to add 100 energy and continue",
custom_tools=[gm_command],
)
The tool runs locally on your machine — the server never sees your endpoints or credentials — and its return value becomes the model's next observation. One instruction now spans systems that used to take a page of glue code: UI steps, backend calls, and human handoffs in a single flow. Details (schemas, error handling, pruning built-in tools): AI Tasks & Custom Tools. Runnable examples: custom_tool_gm.py · 06_human_in_the_loop.py.
Documentation
| Topic | |
|---|---|
| Getting started | Installation · Quick Start · CLI Reference |
| Platforms | Browser · Android (adb, no Appium) · iOS (WDA, no Appium) · Windows & Games (DirectInput) · Desktop · Custom Adapters |
| Integrations | Playwright · Selenium · Appium · pytest |
| Advanced | AI Tasks & Custom Tools · Reports & Recording · Configuration · Error Handling |
| Reference | API — Actions & Platform Matrix |
Examples
Runnable examples live in examples/, in three styles:
- Bolt onto your existing tests (pytest) — playwright/, selenium/, appium/, desktop/
- Standalone automation (plain scripts) — scraping / RPA / agents: automation/
- Drive a game — Windows desktop games (bind by HWND) and the iOS MMORPG script behind the demo video: game/
See examples/README.md for which to pick.
Agent Skill
plugins/qirabot/skills/qirabot/ is a pre-built agent skill: an AI agent
(Claude Code, Cursor, …) loads it and handles setup, scripting, and
verification from a natural-language automation goal. Install in Claude Code:
/plugin marketplace add qirabot/claude-plugins
/plugin install qirabot@qirabot
The skill's reference and templates are drift-tested against the live SDK in
CI (tests/test_skill.py). Details: plugins/qirabot/README.md.
Migrating from 1.x (airtest)
2.0 removed the airtest integration; the built-in backends are drop-in
replacements (AdbDevice / WdaClient / Window), and a copyable adapter
keeps existing airtest scripts running unchanged. Guide:
Custom Adapters — Migrating from Airtest.
The 1.x series lives on the 1.x branch
in maintenance mode — pip install "qirabot<2" always resolves to the newest
1.9.x patch.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qirabot-2.1.2.tar.gz.
File metadata
- Download URL: qirabot-2.1.2.tar.gz
- Upload date:
- Size: 223.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62f8def743228fcebdd8d1df6feba1f47b3061699a52fef9ff50c7cb935febbb
|
|
| MD5 |
08943c3d5fdb335eb6eaf36e20dcd9b8
|
|
| BLAKE2b-256 |
66ec1da6410bc6422d77a01c6e6107a23af12c2e090ebd97f9154973e9809b49
|
Provenance
The following attestation bundles were made for qirabot-2.1.2.tar.gz:
Publisher:
publish.yml on qirabot/qirabot-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qirabot-2.1.2.tar.gz -
Subject digest:
62f8def743228fcebdd8d1df6feba1f47b3061699a52fef9ff50c7cb935febbb - Sigstore transparency entry: 2183250761
- Sigstore integration time:
-
Permalink:
qirabot/qirabot-python@ad98a2279d94f159668a2863650c6e52fb0d987b -
Branch / Tag:
refs/tags/v2.1.2 - Owner: https://github.com/qirabot
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ad98a2279d94f159668a2863650c6e52fb0d987b -
Trigger Event:
push
-
Statement type:
File details
Details for the file qirabot-2.1.2-py3-none-any.whl.
File metadata
- Download URL: qirabot-2.1.2-py3-none-any.whl
- Upload date:
- Size: 162.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c218a9332025a74cbf052f6d96ecfcceef1472f7b76b525bba9c0070e5eb7d0
|
|
| MD5 |
e9e04b186c208624578f4c53498951e4
|
|
| BLAKE2b-256 |
cb741c5941697d343d2876b7486c8a4dead4a4063dcce0574991808087e36fa9
|
Provenance
The following attestation bundles were made for qirabot-2.1.2-py3-none-any.whl:
Publisher:
publish.yml on qirabot/qirabot-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qirabot-2.1.2-py3-none-any.whl -
Subject digest:
3c218a9332025a74cbf052f6d96ecfcceef1472f7b76b525bba9c0070e5eb7d0 - Sigstore transparency entry: 2183250984
- Sigstore integration time:
-
Permalink:
qirabot/qirabot-python@ad98a2279d94f159668a2863650c6e52fb0d987b -
Branch / Tag:
refs/tags/v2.1.2 - Owner: https://github.com/qirabot
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ad98a2279d94f159668a2863650c6e52fb0d987b -
Trigger Event:
push
-
Statement type: