Skip to main content

Autosana CLI

Connect local simulators, emulators, physical devices, and dev servers to Autosana to test locally.

Install

pipx install autosana

Or with uv:

uv tool install autosana

Quick Start

# Check prerequisites
autosana doctor

# Auto-install Node.js + Appium + cloudflared
autosana doctor --fix

# Start local session (iOS)
autosana up --platform ios

# Start local session on a physical iPhone by UDID
autosana up --platform ios --device 00008140-00064D5930E3C01C --detach --json

# Diagnose a physical iPhone setup before running flows
autosana doctor --platform ios --device 00008140-00064D5930E3C01C --json

# Start local session (web — point to your dev server, http or https)
# The scheme (http vs https) is auto-detected. HTTPS dev servers like
# `next dev --experimental-https` and `vite --https` work out of the box.
autosana up --platform web --port 3000

# Multi-device — start sessions for all booted simulators
autosana up --platform ios --all-devices --detach --json

# Or start specific devices by name/UDID
autosana up --platform ios --device "iPhone 16 Pro" --detach --json
autosana up --platform ios --device "iPhone 17 Pro" --detach --json

# Check running sessions (includes device and screenshot readiness checks)
autosana status

# Recover a degraded session without a full restart when possible
autosana recover --session-id <SESSION_ID> --json

# Stop all sessions
autosana down --all

Working with flows

Store your end-to-end tests as YAML under a .autosana/ folder (code-managed flows), then validate, export, and run them from the terminal.

# Validate your .autosana/ flow & suite files offline (same rules the sync applies)
autosana flows validate

# Export existing dashboard flows/suites to .autosana/ YAML for review + commit
autosana flows export --all

# Run your branch's flows in the cloud (attributed to the current git ref), no PR needed
autosana flows run --flow login --bundle-id com.acme.app --platform ios

# In a GitLab CI job: sync .autosana/ on the default branch, check it in merge requests
autosana flows sync

Run a flow on your local simulator

Run the flow you're currently editing — your uncommitted .autosana/ YAML — on the simulator you booted with autosana up. No commit, no push, no cloud device.

# 1. Boot a local session (once)
autosana up --platform ios

# 2. Run your working-copy flow on it
autosana run login --local

# ...or a whole suite (its setup_flow runs on the device first)
autosana run --suite checkout --local

# Web: connect your dev server, then target its Autosana app ID
autosana up --platform web --port 3000
autosana run login --local --app-id <APP_ID>

autosana run is shorthand for autosana flows run. Targeting uses sensible defaults, so the everyday command is just autosana run <flow> --local:

  • App — web runs use --app-id; mobile runs use --bundle-id, the AUTOSANA_BUNDLE_ID env var, or your org's single app for the platform.
  • Platform — web is inferred from --app-id; mobile is taken from your up session. Pass --platform / --session-id only to disambiguate mobile sessions.
  • Environment — --environment <name> selects the variable set that ${env:…} references (and your flows) resolve against; required when the app spans multiple environments.

Notes:

  • Runs your instructions; hooks are not executed locally (they manipulate the environment, not the device) — a suite's setup_flow gives you on-device setup instead.

Upload a build

Send a build you just made to Autosana so cloud runs test it. It becomes the app's active build for the whole workspace: flow and suite runs that don't pin a build use it, and the app's CI/CD automations start, as for any build upload.

# iOS Simulator build: pass the .app folder (zipped for you); the bundle id comes from Info.plist
autosana builds upload ~/Library/Developer/Xcode/DerivedData/MyApp-*/Build/Products/Debug-iphonesimulator/MyApp.app --json

# Real-iPhone build (.ipa), or Android (.apk / .aab) with its package name
autosana builds upload MyApp.ipa
autosana builds upload app-debug.apk --bundle-id com.acme.app

# Upload to a specific existing app (its `id` from apps_list), in its own environment
autosana builds upload app-debug.apk --app-id <APP_ID>

A device build (an .app from an Xcode archive, platform iphoneos) can't run on the iOS Simulator, so it is refused; build for a Simulator destination or export an .ipa. --json prints app_id and app_build_id.

No login? An agent connected to the Autosana MCP (OAuth) calls the builds_upload tool for a signed link, runs autosana builds upload <path> --link "<url>" (checks and uploads the build, no login or API key), then calls builds_upload again with the printed upload_id to make it the active build.

Sandboxes

Drive a cloud simulator or emulator directly, one command at a time. Built for coding agents that want to check their work on a real device while they build, without writing a flow first. Sandboxes have to be enabled for your company.

# Lease a device, install your app's active build, launch it, save the first screenshot
autosana sandbox start --platform ios --bundle-id com.example.app

# Tap at X,Y in pixels of the last screenshot; the settled screen is saved as the next one
autosana sandbox tap 603,1311

# Double-tap
autosana sandbox tap 603,1311 --count 2

# Press and hold
autosana sandbox long-press 603,1311 --duration 1.5s

# Set a field's text (replaces what it holds); --submit presses return
autosana sandbox type "jane@example.com" --into 603,880
autosana sandbox type "hunter2" --into 603,1020 --submit

# Scroll (down shows what is further down), or swipe between two points
autosana sandbox scroll down
autosana sandbox swipe 1000,1311 200,1311

# Open a link, go home, then bring the app back: as it was, as a new process, or as a new install
autosana sandbox open myapp://orders/42
autosana sandbox press home
autosana sandbox launch
autosana sandbox launch --cold
autosana sandbox launch --reset

# Send your app a push notification (iOS simulators), from flags or a JSON file
autosana sandbox push --title "Order shipped" --body "Your order is on its way."
autosana sandbox push payload.json

# Change the device, or just wait for the app
autosana sandbox set orientation landscape
autosana sandbox set location 37.77,-122.41
autosana sandbox wait 2s

# Look again without acting
autosana sandbox look

# List live sandboxes (* marks this worktree's current one), then release the device
autosana sandbox list
autosana sandbox end
  • Builds: start installs a build already uploaded to Autosana (--app-build-id, default: the app's active build). iOS needs a simulator build (.app or .zip), not an .ipa. Apps that ship with the simulator (Safari, Reminders, Photos) need no build: --bundle-id com.apple.mobilesafari. The app can be left out when .autosana/config.yaml names a default.
  • Device: --device "iPhone 17 Pro" --os 26.0 picks a model and OS; the default is the latest.
  • Lifetime: a sandbox holds its device until end or until --ttl runs out (default 30m). End sandboxes you are done with.
  • Screenshots: saved to .autosana/.sandboxes/<sandbox-id>/step-<n>.png in your repository (the folder ignores itself in git), or under ~/.autosana/sandboxes/ outside a repository.
  • Coordinates: tap in pixels of the most recent screenshot, exactly as you see it. Screenshots are scaled so their longest side is 1568 px (an iPhone 17 Pro comes back as 721x1568), which image readers show without resizing, so there is nothing to convert. --max-size <px> on start, look and tap changes that, for example --max-size 2622 to read fine print at full resolution; the next tap then uses that screenshot's pixels.
  • Actions: tap, long-press, type, scroll, swipe, press home, open, launch, wait, push and set (location, orientation, clipboard, locale, network). Each one answers like a tap: what it did, whether the screen changed, and the next screenshot. Positions are always pixels of the most recent screenshot.
  • Push notifications: push delivers a notification to your app the way your server would, so you can check the banner, what tapping it opens, and what your app does with the payload. Pass --title and --body, or a JSON file with an aps object for anything more (badges, custom keys). iOS simulators only, and your app must have been allowed to show notifications. The banner stays up for about five seconds: tap it, or wait 5s before tapping elsewhere, because a tap elsewhere while it is up may not reach your app.
  • Launching: launch brings your app back to the front exactly as it was. launch --cold closes it first, so it starts as a new process with its saved data. launch --reset reinstalls it, so it starts as it does after a first install.
  • Typing: type sets the field's whole text, it does not append. --into X,Y picks the field; without it the text goes to whichever field has the keyboard. The keyboard stays up afterwards so you can see what you typed; --submit presses return. type "" --into X,Y empties a field.
  • Speed: every action waits for the screen to settle and returns it. --no-settle captures immediately; --no-observe skips the screenshot.
  • What a tap tells you: whether the screen changed (screen changed or no change on screen, changed in --json) and how long the tap and the settle each took, so you can often skip opening the screenshot. Without settling it makes no claim about change.
  • Watching: start prints a watch link to the sandbox's page in the Autosana dashboard, where a signed-in teammate sees each step and its screenshot as it happens. The same page is the replay once the sandbox ends; end prints it again (watch_url in --json).
  • Name: --name "checkout confirm button" says what the sandbox is for and is the title of its page. Without it the sandbox is named after the git branch you are on.
  • Several sandboxes: each git worktree has its own current sandbox. Address another with --sandbox <id>, using an id from autosana sandbox list.
  • If the app stops running: when your app crashes or is closed, the sandbox keeps its device. The next tap relaunches the app and fails with code app_relaunched without tapping, because the screen you aimed at is gone; look at the screenshot it saved, then tap again. look shows whatever is on the device, which may be the home screen.
  • Scripting: every command takes --json. Exit codes: 0 ok, 1 the command failed, 2 bad usage, 3 not logged in, not enabled, or at the sandbox limit, 4 the sandbox is gone.

look and tap go straight to the sandbox's own address, authorized by a short-lived sandbox token that start receives. Only start, list and end call the Autosana API.

Multi-Device Parallel Testing

Test across multiple simulators simultaneously:

  1. Boot multiple iOS Simulators or Android Emulators
  2. Run autosana up --platform ios --all-devices --detach --json to start sessions for all devices
  3. Your coding agent dispatches flows to different devices in parallel via device_tunnel_map
  4. All flows execute simultaneously — 3 devices = 3x faster

Works with both iOS and Android. Each device gets its own Appium server and Cloudflare tunnel.

Device Health Checks

autosana up and autosana status verify that devices are actually responsive — not just listed by ADB/simctl:

  • Android: runs adb shell echo ok with a 5s timeout to detect zombie emulators
  • iOS Simulators: runs xcrun simctl getenv with a 5s timeout to detect frozen simulators
  • Physical iOS devices: uses Xcode CoreDevice (xcrun devicectl) to verify the device is paired, connected, awake, and available to Xcode. If the device is locked, unplugged, offline, or missing a Trust This Computer prompt, autosana up exits before starting Appium.
  • Web: probes http://127.0.0.1:<port> and https://127.0.0.1:<port> in parallel (3 attempts with backoff, to cover dev servers still booting). The responding scheme is used for the Cloudflare tunnel origin, preferring https on tie. HTTPS origins skip TLS verification on loopback — self-signed certs from mkcert, next dev --experimental-https, and vite --https just work. Verification is intentionally disabled here because the cloudflared origin is 127.0.0.1 (no MITM surface); to lock cloudflared back into strict verification with a trusted CA, you'd run cloudflared yourself instead of via autosana up.

If a mobile device is unresponsive, autosana up fast-fails before wasting time on Appium/tunnel setup. autosana status --json reports device_responsive: false with an actionable issue message.

autosana status --json also includes components, next_action, and each session's session_id. Agents should read these before every local run. If a Cloudflare tunnel or local proxy process died, run autosana recover --session-id <SESSION_ID> --json using the matching status.sessions[].session_id first. Recovery restarts the smallest failed scope when possible: tunnel first, local proxy next, and full session restart only when Appium/WebDriverAgent needs it.

The detected scheme is reported in autosana up --json as scheme: "http" or scheme: "https".

Physical iPhone Readiness

Physical iPhone local runs use Appium/WebDriverAgent (WDA) for both control and screenshots. WDA is installed on the device by autosana up and validated with a real screenshot capture before the session reports ready — no extra brew installs are required. For physical iOS sessions, autosana up --platform ios --device <UDID> --detach --json starts a local Autosana proxy in front of Appium and tunnels that proxy. The proxy exposes:

  • /_autosana/health
  • /_autosana/screenshot
  • /_autosana/diagnostics

autosana up fails fast if no real screenshot provider is ready. autosana status --json includes physical-readiness fields:

  • screenshot_ready
  • screenshot_provider
  • screen_non_black
  • wda_ready
  • screenshot_diagnostics
  • local_proxy_token (physical iPhone only, internal token for Autosana proxy screenshots)
  • components
  • next_action

Treat local_proxy_token as a secret. Read it from autosana status --json, pass it directly to Autosana MCP tools for physical iPhone runs, and do not paste real token values into bug reports, chat logs, or public docs. Re-read status after recovery or restart because the token can change. If recovery rotates the token during an in-flight run, start a fresh flows_run with the new session values.

Run autosana doctor --platform ios --device <UDID> --json when physical setup fails. It checks CoreDevice connectivity, pairing/trust, Developer Mode, DDI services, WebDriverAgent signing, and the optional iPhone Mirroring host capture fallback. WDA screenshots are validated by autosana up itself at session start, so doctor warnings on the optional fallback do not block up — the doctor only surfaces the concrete blocker when the WDA path itself fails.

Keep the iPhone awake, unlocked, trusted, in Developer Mode, and plugged into power during physical local runs. If the display turns off, WDA may still return an accessibility tree, but Autosana treats black screenshots as a hard error and will not reconstruct a fake screenshot from accessibility data.

Requirements

  • iOS Simulator: macOS with one or more booted iOS Simulators
  • Physical iOS: macOS with Xcode, a paired/unlocked iPhone in Developer Mode, and an Apple Development signing identity (with private key) available to Xcode. After WebDriverAgent first installs on the device, you must trust the developer certificate: Settings → General → VPN & Device Management → tap your "Apple Development" entry → Trust. For team-specific WebDriverAgent signing, set AUTOSANA_IOS_XCODE_ORG_ID and optionally AUTOSANA_IOS_UPDATED_WDA_BUNDLE_ID.
  • Android: macOS, Linux, or Windows with one or more booted Android Emulators
  • Web: a local dev server running on any OS
  • An Autosana account

Metadata

Release files for autosana 0.10.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for autosana 0.10.0
File Interpreter ABI Platform
autosana-0.10.0-py3-none-any.whl Python 3 none any Details

Release files / autosana-0.10.0-py3-none-any.whl

Download URL autosana-0.10.0-py3-none-any.whl
Size 153.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e90c58cc5c2b48b8c54edafc532c642bb33862c9dee066178bd6d8273422c109
BLAKE2b-256 checksum
How to use checksums
9822286e9ae83c6cf9c5fada8d8c405d3b3b49d0ea0c9e764d63316b9bdfa131
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Security for autosana 0.10.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 1 file in this release has been uploaded with provenance metadata.

Attestation for autosana-0.10.0-py3-none-any.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.10.0 This release

1 release file Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page