Dein Agent. Ein Android-Gerät.
sim baut deine App, startet sie auf Android und lässt einen Agent echte Abläufe ausprobieren. Du bekommst Ergebnisse und Screenshots zurück.
In drei Schritten zum Test
- Account erstellen und den Wiederherstellungscode sicher ablegen.
- Die CLI installieren und einmal mit
sim login anmelden. - Im App-Ordner
sim up ausführen und einen Test beschreiben.
cd meine-app
sim up
sim test "Öffne die Suche und prüfe, ob Ergebnisse erscheinen."
sim screenshot --output suche.jpg
Deine App bleibt eingerichtet
Beim Stoppen einer Session werden die Android-Daten gespeichert. Starte später dieselbe Testumgebung innerhalb der App, um installierte Apps, lokale Daten und bestehende Logins wiederzuverwenden. Eine App kann dich trotzdem abmelden, wenn ihr eigener Server die Sitzung ablaufen lässt.
APK-Updates werden mit Erhalt der App-Daten installiert. Dafür müssen Paketname und Signatur zur installierten App passen. Ein expliziter Neustart mit --fresh beginnt mit einem leeren Android-Gerät.
Welche Projekte funktionieren?
Eine fertige APK ist der direkteste Weg und unabhängig vom verwendeten Framework. Sie muss ARM64 unterstützen oder ohne native, architekturabhängige Bibliotheken auskommen.
Remote-Builds unterstützen native Gradle-Projekte sowie Adapter für React Native, Expo, Flutter und Capacitor. Besondere SDKs, private Abhängigkeiten oder individuelle Build-Schritte können eine sim.json benötigen. Native Gradle-Builds sind Ende zu Ende geprüft; ein Adapter ist keine Garantie für jede Projektkonfiguration.
Dieselben Abläufe im Dashboard
Das Dashboard verwendet die öffentliche API. Apps, Geräte, Aufträge und Artefakte haben dieselben IDs wie in CLI und MCP. Du kannst einen Auftrag per API starten, im Browser übernehmen und anschließend wieder an den Agent zurückgeben.
Die API-Referenz beschreibt Felder und Ereignisse; die Anleitungen für CLI und MCP beschreiben dieselben Abläufe für Agents.
Gerätevarianten, Live-Prüfung und Bilddiagnose
Im Live-Simulator unter „Testbedingungen“ wählst du Telefon- oder Tablet-Display, eigene Auflösung/Dichte und Gerätesprache. Diese Einstellungen bleiben bei der Testumgebung gespeichert. Die Profile emulieren Bildschirmgeometrie, keine Herstellerhardware oder Firmware.
Testoptionen enthalten Ticket-Referenz, Tags, Aufbewahrungsdauer und die Wartezeit für Rückfragen. Standardmäßig endet eine unbeantwortete Rückfrage nach 15 Minuten mit inconclusive; „unbegrenzt warten“ deaktiviert ausschließlich diese Frist. Aufträge erhalten kein Gesamtzeit- oder Schrittlimit.
Unter Testberichte kannst du nach Tickets, Requests, Tags, Apps, Umgebungen und Ergebnis suchen. Im Bericht verwaltest du die Aufbewahrung und findest „Läufe vergleichen“ sowie „Bildbereich vergleichen“. Ziehe den zu prüfenden Bereich auf dem Screenshot auf; Unterschiede werden rot hervorgehoben. Ohne explizite Referenz wird der letzte frühere bestandene Auftrag derselben Umgebung verwendet. Achte auf denselben App-Zustand. Ein Pixelvergleich bewertet weder die Ursache noch automatisch die fachliche Richtigkeit.
„Live beobachten“ zeigt den aktuellen Bildschirm und die Ereignisse, ohne in den Auftrag einzugreifen. Agents verwenden dafür sim watch, android_watch oder die Live- und Ereignis-API. Beobachten verlängert die Leihfrist nicht.
Neue Belege werden standardmäßig 30 Tage nach Job-Ende gelöscht, pro Job sind 1–365 Tage oder Anpinnen möglich. Vor Einführung dieser Regel vorhandene Berichte erhalten eine 30-tägige Übergangsfrist ab Erfassung durch die Aufbewahrungsverwaltung. Angepinnte Belege bleiben bis zum Entpinnen oder expliziten Löschen. Ohne Speicherung werden keine dauerhaften Belegdateien angelegt; Screenshots für Modellaufrufe und die Live-Ansicht bleiben flüchtig. Prompt, Ereignistexte, Ergebnis und Verbrauch bleiben als Metadaten gespeichert. Genauer Umfang und Endpunkte →
Kapazität, Limits und Aufbewahrungsregeln sind außerdem maschinenlesbar unter GET /v1/limits verfügbar.
Ändern, synchronisieren, im Gerät prüfen
sim dev startet einen eigenen entfernten Dev-Server für deine Sitzung und synchronisiert anschließend geänderte Dateien. Metro und die Abhängigkeiten laufen auf dem zugehörigen Android-Worker, nicht auf deinem Rechner. Verschiedene Testumgebungen und Worktrees verwenden getrennte Server und Quellstände. Bei einem kurzen Verbindungsabbruch bleibt der Server weiter aktiv; die CLI gleicht nach Wiederverbindung ab. Ein fremder Revisionsstand wird nicht still überschrieben.
JavaScript-Änderungen benötigen danach keinen neuen APK-Build. Voraussetzung ist eine passende Debug-/Development-Version der App; eine Produktions-APK wird dadurch nicht automatisch zu einem Dev-Client. Native Änderungen können weiterhin einen Neubau erfordern. Die erste Installation von Abhängigkeiten und das erste Bundle brauchen länger als spätere Dateiänderungen. Einrichtung und CLI-Befehle →
Im Live-Simulator unter Entwicklung & Daten verwaltest du den Dev-Server, lädst einen Quellcode-ZIP hoch, öffnest den Dev-Client und liest den Status. Dort findest du außerdem Galerie-/Datei-Upload, Downloads, Clipboard, Live-Logcat und die App-Update-Schnittstelle. Für automatischen inkrementellen Dateiabgleich verwende die CLI oder android_dev_sync.
Ein OTA-Kanalwechsel funktioniert nur über einen von deiner App bereitgestellten Deep Link oder ContentProvider. sim zeigt angeforderten Kanal, Rückmeldung und gemeldete Revision getrennt an. Ohne bestätigte Update-ID behauptet es keinen erfolgreichen Bundle-Wechsel. App-Vertrag und Prüfung →
APK-Updates verwenden adb install -r: Android-App-Daten werden bei kompatiblem Paket und gleicher Signatur behalten. Bei einem Signaturkonflikt bricht die Installation ab; sim deinstalliert oder löscht die Daten nicht automatisch. Die App kann durch eigene Migrationen oder abgelaufene Backend-Sitzungen dennoch einen erneuten Login verlangen.
Ein Neustart des Dev-Server-Kontrolldienstes beendet laufende Dev-Server. Sie werden derzeit nicht automatisch mit ihrem Quellstand wiederhergestellt. Prüfe danach den Status, stoppe den alten Dev-Server ausdrücklich, warte auf stopped und starte sim dev erneut. Dabei wird der Quellstand erneut hochgeladen; die gespeicherten Android-App-Daten sind davon getrennt.
Während eines laufenden Tests bleibt der Quellstand stabil: Konfiguration, Synchronisierung, Stoppen und Öffnen des Dev-Servers sind erst nach Übernahme oder Stoppen des Tests möglich. Der CLI-Watch wartet in dieser Zeit. Neue Tests und das Fortsetzen nach einer Übernahme sind erst bei ready:true des konfigurierten Dev-Servers möglich.
Wackler über mehrere Aufträge erkennen
Die Ablaufhistorie verbindet die letzten 20 abgeschlossenen Jobs je Test über verschiedene Sessions derselben App-Umgebung. Maestro nutzt den YAML-Einstiegspfad, Modelltests einen ausdrücklich gesetzten test_key. Neue ZIP-Versionen unter demselben Pfad bleiben vergleichbar; ein neuer Dateipfad beginnt eine neue Historie.
Fehlerquote, gemischte Wiederholungen innerhalb eines Jobs und Grün/Rot-Wechsel zwischen Jobs werden getrennt ausgewiesen. Infrastruktur- und Navigationsfehler zählen nicht als App-Fehler. Ein immer roter Test ist fehlerhaft, aber kein nachgewiesener Wackler. Änderungen an Build, Quellrevision oder Gerät können unterschiedliche Ergebnisse erklären.
Quarantäne ist eine manuelle, begründete Markierung mit optionalem Ablaufdatum. Tests laufen weiterhin, Rohurteile bleiben erhalten. Nur eine Pipeline, die sich ausdrücklich für die Überwachung mit Quarantäne-Ausnahmen entscheidet, darf gate:non_blocking verwenden. Die normale Abnahme wird dadurch nicht automatisch grün. CLI-Befehle · API und Kennzahlen
Gespeicherte Tests und Ausgangszustände
Benannte Snapshots sichern einen lokalen Android-Zustand. Starte daraus eine separate Umgebung und verwirf ihre Änderungen nach dem Test. Gespeicherte Testdefinitionen lernen aus überprüften erfolgreichen Läufen einen wiederverwendbaren Ablauf; Pointer und UI-Prüfungen sichern Wiederholungen ab, das Modell übernimmt bei Abweichungen.
CLI-Anleitung · API-Vertrag · MCP-Werkzeuge
Vom Projektordner in die App.
Die CLI kümmert sich um Quellstand, Remote-Build, Session und Installation. Du brauchst Python 3.10 oder neuer — kein lokales Android SDK.
1. CLI installieren
Für macOS und Linux. Der Download ist ein lesbares Python-Skript ohne zusätzliche Python-Pakete.
mkdir -p "$HOME/.local/bin"
curl -fSL https://sim.davidhe.de/cli -o "$HOME/.local/bin/sim"
chmod +x "$HOME/.local/bin/sim"
export PATH="$HOME/.local/bin:$PATH"
sim --version
Trage die export PATH=…-Zeile bei Bedarf in deine ~/.zshrc oder ~/.bashrc ein. Unter Windows kannst du die heruntergeladene Datei mit python sim ausführen.
CLI aktualisieren
sim update
sim update --check # Nur prüfen
sim --version
Funktioniert aus jedem Ordner und ohne Anmeldung. Die CLI lädt die aktuelle Version von deinem konfigurierten Server, prüft die Datei und ersetzt die bestehende Installation. Zugangsdaten, Projekte und laufende Simulatoren bleiben erhalten. Schlägt der Download fehl, bleibt deine CLI unverändert.
Für Agents: sim --json update liefert Versionsnummern und Update-Status als JSON. Ab Version 0.3.0 verfügbar; kennt deine CLI den Befehl noch nicht, wiederhole einmal die Installation oben.
2. Anmelden
Die CLI fragt nach E-Mail und Passwort und speichert einen persönlichen API-Token lokal mit eingeschränkten Dateirechten. Das Passwort wird nicht als Argument in deiner Shell-History abgelegt.
Für einen vorhandenen Token nutze sim login --token. Der Token wird verdeckt abgefragt. Agents können alternativ SIM_API_KEY und optional SIM_URL über ihre geschützte Umgebung erhalten.
3. App starten
cd /pfad/zu/deiner-app
sim up
sim erkennt das Framework, lädt den relevanten Quellstand hoch, wartet auf den Remote-Build und öffnet die APK in einer Session. Die App bleibt mit dem Projekt verbunden; Git-Worktrees bekommen automatisch ihre eigene Testumgebung. Unveränderte Quellen können eine bereits gebaute APK wiederverwenden.
# Eine bereits gebaute APK installieren
sim up --apk ./app.apk --workspace meine-app
# Denselben Workspace wieder verwenden
sim up --workspace meine-app
# Ausdrücklich mit leerem Android beginnen
sim up --workspace meine-app --fresh
# APK neu bauen statt ein fertiges Build-Artefakt wiederzuverwenden
sim up --no-cache
Frisch bedeutet leer. --fresh überspringt den bisherigen Android-Zustand. Für normale Updates und weitere Tests reicht sim up.
Mehrere Agents, eine App
Ab CLI 0.4 arbeiten App und Testumgebung getrennt. Eine App sammelt Builds und Berichte. Jede Umgebung hat ein eigenes Android mit unabhängig gespeicherten lokalen App-Daten.
# In einem Git-Worktree: Umgebung wird automatisch zugeordnet
sim up --app swipestyle
# Zwei Agents im selben Ordner wählen verschiedene IDs
sim up --app swipestyle --environment checkout
sim up --app swipestyle --environment suche
# Agent-Auswahl auch für spätere Befehle festhalten
export SIM_ENVIRONMENT=checkout
sim test "Prüfe den Checkout"
sim down
Ungemergte Branches und uncommittete Änderungen können unabhängig gebaut und getestet werden. Build und Bericht enthalten Umgebung, Build-ID und Quellstand. Remote-Builds warten bei Bedarf auf den gemeinsamen Build-Server; Simulatoren können gleichzeitig laufen.
Mit einem eingerichteten Android starten
sim down --app swipestyle --environment main
sim environments --app swipestyle # Sicherung abwarten
sim baseline --app swipestyle --environment main
sim up --app swipestyle --environment checkout
- Eine Umgebung starten, die App installieren und beispielsweise mit dem Testkonto anmelden.
- Mit
sim down beenden und warten, bis der Android-Stand gesichert ist. - Unter Apps & Simulatoren die App öffnen. Bei der gespeicherten Umgebung unter „Umgebung verwalten“ auf „Als Ausgangszustand speichern“ klicken.
- Neue Umgebungen übernehmen eine unabhängige Kopie dieses Ausgangszustands. Bestehende Umgebungen behalten ihre Daten.
Ein ausdrücklich frischer Start mit --fresh lädt weder gespeicherte Daten noch den gemeinsamen Ausgangszustand. Stoppen und Fortsetzen gilt immer für die ausgewählte Umgebung.
Lokale Daten sind getrennt. Die Umgebungen sprechen weiterhin mit dem Backend deiner App. Für unabhängig veränderbare Profile, Warenkörbe oder andere Serverdaten benötigst du gegebenenfalls verschiedene Testkonten.
Tests delegieren
sim test "Prüfe, ob die Suche nach roten T-Shirts Ergebnisse zeigt."
# Modell und zusätzlichen App-Kontext auswählen
sim test "Prüfe den Login-Ablauf" \
--model robot --context-file ./test-context.txt
# Direkt eine Job-ID zurückgeben
sim --json test "Prüfe die Navigation" --no-wait
# Screenshot und Session-Status
sim screenshot --output ./ergebnis.jpg
sim --json status
Verfügbare Modellnamen: robot, qwen, astra und opus. Beschreibe ein überprüfbares Ziel. App-Kontext hilft bei Navigation und Erwartungen; der aktuelle Bildschirm bleibt der Beleg für das Testergebnis.
Die globale Option --json steht vor dem Befehl. So bekommt dein Agent maschinenlesbare Ausgabe, während Fortschrittsmeldungen separat ausgegeben werden.
Nur bauen, Logs lesen, stoppen
sim build --output ./app.apk
sim logs
sim cancel-build
# Android-Zustand sichern und Session beenden
sim down
Builds werden in einer Warteschlange verarbeitet. Der Cache gehört zum jeweiligen Projekt und wird bei späteren Builds wiederverwendet. Ein Build-Abbruch beendet keinen separat laufenden Test.
Projekt konfigurieren
Für ein natives Gradle-Projekt reicht häufig die automatische Erkennung. Mit einer sim.json im Projektordner kannst du die Erkennung präzisieren:
{
"framework": "gradle",
"command": "./gradlew :app:assembleDebug --no-daemon",
"apk": "app/build/outputs/apk/debug/app-debug.apk",
"package": "com.example.meineapp",
"java": 17
}
Ein eigener Build-Befehl läuft remote im hochgeladenen Projekt. Die APK muss eigenständig startbar sein. Insbesondere bei React Native darf sie für einen Remote-Test nicht auf einen lokalen Metro-Server angewiesen sein.
Was wird hochgeladen?
In Git-Projekten werden versionierte und nicht ignorierte neue Dateien berücksichtigt, einschließlich uncommitteter Änderungen. Ohne Git wird der Projektordner gelesen. Generierte Verzeichnisse wie node_modules, .gradle und build sowie typische Geheimnisdateien wie .env* und Signaturschlüssel werden ausgeschlossen.
Mit .simignore kannst du weitere Dateien ausschließen:
docs/
private-fixtures/
*.csv
Prüfe projektspezifische Dateien vor dem Upload. Automatische Dateifilter können unbekannte Speicherorte von Geheimnissen nicht erkennen. Private Paketquellen und spezielle Cloud-Konfigurationen funktionieren nicht automatisch ohne ihre benötigte Einrichtung.
Autonome Testaufträge (CLI 0.9.0)
Mit sim update aktualisieren. Alle Befehle verwenden dieselben Session- und Job-IDs wie HTTP und MCP. Jeder Projektbefehl akzeptiert --app, --environment und optional --session-id für ein über eine andere Schnittstelle gestartetes Gerät. --json steht vor dem Befehl; Fortschritt geht auf stderr.
Ein Briefing bleibt für die App gespeichert und wird neuen Tests als Kontext mitgegeben. Nutze eine private JSON-Datei außerhalb des Repositorys:
{
"context": "Explore enthält die Produktsuche; Partnershops öffnen im Browser.",
"credentials": {"email": "test@example.invalid", "password": "TEST_PASSWORD"},
"known_pitfalls": ["Onboarding: Damen, Alter und Größen, Farben überspringen, zwei Likes."]
}
sim briefing --app fashion --file /private/test-briefing.json
sim --json briefing --app fashion
sim briefing --app fashion --delete
PUT ersetzt das Briefing. Der Inhalt geht an den ausgewählten Modellanbieter; Testkonten verwenden. Umgebungsbezogener Kontext über --context-file ergänzt die App-Vorgabe. Ein laufender Auftrag behält seinen ursprünglichen Kontext.
Abnahmekriterien stehen als Array in criteria.json:
[
{"id":"cards","description":"Produktkarten sind ohne abgeschnittene Bilder sichtbar","kind":"visual"},
{"id":"heading","description":"Explore wird angezeigt","kind":"text_visible","value":"Explore"},
{"id":"error","description":"Kein Fehlerhinweis","kind":"text_absent","value":"Something went wrong"}
]
sim --json test "Suche rote T-Shirts und prüfe den Ergebnisbildschirm" \
--criteria-file criteria.json --repeat 5 --reset-between restart_app \
--package dev.example.app --request-id issue-412-rev-abc-test-1 --no-wait
sim --json job JOB_ID
sim --json artifacts JOB_ID
sim artifacts JOB_ID --filename NAME_FROM_MANIFEST --output evidence.xml
--repeat startet eine Serie (1–1000 Wiederholungen). --reset-between none behält den vorherigen App-Zustand, restart_app startet das Paket neu und clear_data löscht dessen lokale Daten samt Login. Externe Backend-Daten werden nicht zurückgesetzt. Für einen vollständig frischen Android-Stand eine neue Umgebung mit sim up --fresh verwenden. Video-Aufzeichnung ist voreingestellt; --no-video schaltet sie ab. Fehlende Aufzeichnungen stehen als Erfassungsfehler im Bericht. Screenshots, UI-Baum, Logcat und verfügbare Videos sind Artefakte.
Ein terminaler Job-Status ist kein automatisches Grün. Prüfe outcome, criteria_results, repetitions und Belege. Mögliche Ergebnisse: passed, app_failed, navigation_failed, environment_failed, inconclusive, cancelled. Nur ein belegter App-Fehler gehört automatisch ins Bug-Ticket. Ein gemischter Testlauf darf nicht durch das letzte Grün ersetzt werden. --request-id bei Netzwerk-Wiederholungen desselben Auftrags in derselben Session wiederverwenden; für einen neuen Test eine neue ID wählen.
Rückfragen beantworten oder kurz selbst übernehmen
sim test wartet normalerweise auf das Ergebnis. Bei needs_input oder Caller-Kontrolle gibt es den aktuellen Zustand zurück, damit dein Agent antworten kann. --no-wait liefert sofort die Job-ID. Es gibt kein Gesamt-Schritt- oder Zeitlimit für normale Testaufträge. Ein optional gewählter Reservierungsvertrag hat dagegen eine ausdrückliche Leihfrist.
sim --json job JOB_ID
sim answer JOB_ID QUESTION_ID "Den unteren Weiter-Button im Onboarding wählen"
sim takeover JOB_ID
sim --json observe JOB_ID
sim actions JOB_ID --file /private/actions.json
sim resume JOB_ID --message "Onboarding fertig. Ursprüngliche Kriterien prüfen."
sim --json job JOB_ID
sim stop
actions.json enthält ein Array:
[{"action":"tap","x":0.5,"y":0.85},{"action":"key","key":"BACK"}]
Unterstützt: tap, swipe, text, key, keycombo, wait, launch. Koordinaten x/y/x2/y2 sind 0–1 auf dem echten Android-Bild, duration ist in Millisekunden. Android-Tasten ohne KEYCODE_ verwenden. Aktionen sind nur bei übernommener Kontrolle erlaubt. Der Robot wird an einer sicheren Aktionsgrenze angehalten. --recovery-after 3 ist die Vorgabe für eine Rückfrage nach wiederholt erfolgloser Navigation; es beendet keinen gesamten Auftrag.
Maestro, Geräte-Konfiguration und geladene Revision
sim --json flows ./maestro
sim --json flows
sim --json test "Android-Suite" --flows ./maestro --flow smoke.yaml --flow search.yaml --repeat 5 \
--reset-between clear_data --package dev.example.app --no-wait
# Ein hochgeladenes Paket wiederverwenden
sim --json test "Android-Suite" --kind maestro --flow-id FLOW_ID --no-wait
sim flows --delete FLOW_ID
sim configure --file /private/device.json
sim --json revision --package dev.example.app
sim --json revision --package dev.example.app \
--probe-uri content://dev.example.app.test/revision
Das explizit ausgewählte Maestro-Verzeichnis wird mit relativen YAML-Dateien und Assets hochgeladen; nichts wird lokal ausgeführt. Symlinks und typische Geheimnisdateien werden ausgeschlossen. Grenzen: 256 Dateien, 32 MiB entpackt, 8 MiB ZIP. Unterstützte Assets: YAML, JavaScript, JSON, PNG/JPEG/WebP und Text. Mit wiederholtem --flow PATH wählst du Einstiegspunkte in Reihenfolge. Helper bleiben im ZIP. Ohne Auswahl laufen nur YAML-Dateien direkt im ZIP-Hauptverzeichnis, ersatzweise direkt in .maestro/. Verschachtelte Helper werden nicht automatisch gestartet. Pakete mit config.yaml/config.yml oder nur tiefer verschachtelten Einstiegspunkten benötigen explizite --flow-Angaben; ohne Auswahl kommt HTTP 422 vor dem Jobstart. Config-Include/Exclude/Reihenfolge wird nicht automatisch übernommen. Referenzierte Dateien müssen mit im Verzeichnis liegen; vor dem Löschen eines Flow-Pakets dessen laufende Jobs beenden. Je Ablauf und Wiederholung stehen erfasste Ergebnisse und Artefakte zur Verfügung. Maestro verwendet YAML-Assertions; --criteria-file gilt nur für Modelltests.
Gesammelte Maestro-Artefakte sind auf insgesamt 512 MiB pro Job begrenzt; eine Überschreitung ist ein ausdrücklicher Erfassungsfehler. Das Manifest enthält Größe, SHA-256 und mime, etwa application/xml für JUnit, video/mp4 für Videos und image/png für Screenshots. Verwende den angegebenen MIME-Typ; nicht alle Dateien sind JPEG-Bilder. Maestro-Berichte enthalten flow_id, die ausgewählten flow_paths und den Archiv-Hash flow_sha256 als Ausführungsstand.
device.json kann Berechtigungen, Deep Link, Offline-Zustand und Uhr enthalten:
{
"package":"dev.example.app",
"permissions":[{"package":"dev.example.app","permission":"android.permission.POST_NOTIFICATIONS","grant":true}],
"deep_link":"exampleapp://explore",
"offline":false,
"timezone":"Europe/Berlin"
}
time verschiebt die Geräteuhr; reset_clock:true stellt automatische Zeit wieder her. Das verändert nicht die Zeit im Backend. Android kann nicht unterstützte Berechtigungen oder Zeiteinstellungen zurückweisen.
APK-Version und Hash beweisen nicht das aktive OTA-JavaScript-Bundle. Optional liefert ein von deiner App bereitgestellter Test-Content-Provider Update-ID, Channel und Runtime-Version. Diese Werte sind app_reported; ohne solchen Provider bleibt die OTA-Revision unbekannt. Beim Test gibt --revision-probe-file probe.json mit {"uri":"content://dev.example.app.test/revision"} den Probe-Auftrag mit.
Die Antwort enthält revision, update_channel, update_id, runtime_version und bundle_hash als Strings oder bei unbekannten Werten null. ota_verified bleibt false. Der Test-Content-Provider muss genau eine Zeile mit expliziten Spalten liefern:
Row: 0 revision=abc123, update_channel=preview, update_id=update-42, runtime_version=2.4.4, bundle_hash=abcd1234
Werte dürfen 1–256 Zeichen aus Buchstaben, Ziffern und . _ : + / @ - enthalten. Mehrere Zeilen, doppelte Spalten oder fehlerhafte Ausgaben ergeben keinen Revisionsnachweis. ota enthält source:"app_reported", uri, den Rohwert value, available und gegebenenfalls error. Ohne Probe bleibt ota:null. Providerfehler verhindern die APK-Versionsabfrage nicht. Die Werte sind App-Auskünfte, keine unabhängige Verifikation.
Kapazität und Webhooks
sim --json capacity
sim --json reserve --app fashion --environment agent-4 \
--request-id issue-412-device-1 --ttl-seconds 3600 --wait-timeout-seconds 1800
sim --json reservations
sim --json reservation RESERVATION_ID
# Nach status: allocated die zurückgegebene session_id verwenden:
sim up --session-id SESSION_ID --app fashion --environment agent-4
# Mit vorhandener APK: zusätzlich --apk ./app.apk
sim reservation RESERVATION_ID --cancel
sim keep
sim down
sim --json webhooks --file /private/webhook.json
sim --json webhooks
sim --json webhooks --deliveries WEBHOOK_ID
sim --json test "Prüfe die Suche" --webhook-id WEBHOOK_ID --no-wait
sim webhooks --delete WEBHOOK_ID
Eine Reservierung wartet auf einen freien Platz. Bei allocated enthält sie session_id; die CLI merkt sich diese beim Abfragen für dieselbe App/Umgebung. sim up --session-id SESSION_ID --app fashion --environment agent-4 baut und installiert auf dieser Session, ohne eine weitere anzulegen. App und Umgebung müssen zur Session passen. --fresh und --session-id schließen sich aus. Bei einer reservierten Umgebung die Session-ID ausdrücklich übergeben. --wait-timeout-seconds begrenzt das Warten (Vorgabe 3600), --ttl-seconds die Leihfrist ab Zuteilung (Vorgabe 1800). Beide erlauben 60–86400 Sekunden. Die explizite Leihfrist beendet auch aktive Tests und sichert/gibt das Gerät zurück. Heartbeats verlängern diese absolute Reservierungsfrist nicht. Normales sim up verwendet keine solche feste Reservierungsfrist; aktive Tests bleiben aktiv.
webhook.json enthält {"url":"https://ci.example.com/sim-events"} und optional einen eigenen mindestens 32 Zeichen langen secret. Andernfalls wird ein Secret erzeugt und nur bei Erstellung zurückgegeben. Unterstützt sind öffentlich erreichbare HTTPS-Ziele auf Port 443 ohne Redirects. Callbacks für Abschluss und Rückfragen sind HMAC-signiert; genaue Header und Verifikation in der API-Referenz. Doppelte Zustellungen über die Event-ID deduplizieren und das Job-Ergebnis anschließend authentifiziert abrufen. Zustellfehler ändern das Testergebnis nicht.
Bildschirm und Gerätesprache
CLI 0.9.0: sim update installiert diese Befehle. Profile bilden Bildschirmgröße, Auflösung und Dichte nach; Hersteller-Modellidentität, Firmware und Hardware werden nicht emuliert. Die App und ihre Daten bleiben in derselben Umgebung erhalten.
sim device-profiles
sim up --device-profile compact --locale en-US
sim configure --display 1080,2400,420 --locale de-DE
sim configure --device-profile tablet
Wähle entweder --device-profile oder --display WIDTH,HEIGHT,DENSITY. --locale ist ein BCP-47-Sprachcode, etwa en-US oder de-DE. Beim nächsten Start derselben Umgebung wird die Konfiguration wiederhergestellt. Weggelassene Werte bleiben unverändert. Ein Profil wird beim Start oder per configure gesetzt; während eines laufenden Tests ist dafür erst eine Übernahme erforderlich. Größenänderungen können eine Activity neu aufbauen; Apps mit eigener Spracheinstellung können die Gerätesprache übersteuern.
Live zuschauen und Läufe finden
sim --json test "Prüfe den Produktdialog" --no-wait \
--external-id '#673' --tag branch=fix/dialog --needs-input-timeout 300
sim --json watch JOB_ID --session-id SESSION_ID
sim --json watch JOB_ID --session-id SESSION_ID --after 12 --once
sim --json jobs --external-id '#673'
sim --json jobs --query 'Produktdialog' --tag branch:fix/dialog --limit 20 --offset 20
sim --json limits
watch liefert fortlaufend ein JSON-Objekt pro Zeile: neue Aktionen, Status, Frage, Verbrauch, Cursor und private Screenshot-URL. Es übernimmt das Gerät nicht und verlängert seine Leihfrist nicht. Der Aufrufer kann die Screenshot-URL mit seinem API-Token abrufen. --once liefert genau einen Stand; mit --after setzt ein Agent beim letzten Cursor fort. Standardabstand: zwei Sekunden; --interval setzt mindestens eine Sekunde. Strg+C beendet nur das Zuschauen.
jobs durchsucht standardmäßig den gesamten eigenen Account, auch beendete Sessions. Optional: --app, --environment, --external-id, --request-id, --outcome, --query und --tag KEY:VALUE. external_id und Tags dienen der Suche; request_id bleibt der Idempotenzschlüssel. --tag KEY=VALUE beim Teststart ist wiederholbar.
Unbeantwortete Rückfragen enden standardmäßig nach 900 Sekunden mit inconclusive. --needs-input-timeout SECONDS (60–86400 Sekunden) ändert nur diese Wartezeit; none schaltet sie ausdrücklich ab. Normale Modellarbeit hat weiterhin kein Gesamtschritt- oder Zeitlimit. Reservierungsfristen gelten unabhängig davon.
Belege aufbewahren und vergleichen
sim test "Prüfe die Kachel" --retention-days 90
sim test "Prüfe ohne gespeicherte Bildschirmbelege" --no-store-artifacts
sim artifacts JOB_ID --session-id SESSION_ID --pin
sim artifacts JOB_ID --session-id SESSION_ID --unpin --retention-days 30
sim artifacts JOB_ID --session-id SESSION_ID --delete
sim divergence JOB_ID --session-id SESSION_ID --threshold 0.03
sim compare JOB_ID --session-id SESSION_ID --region 0.1,0.2,0.8,0.3
sim compare JOB_ID --session-id SESSION_ID --region 0.1,0.2,0.8,0.3 \
--baseline-job GREEN_JOB_ID --baseline-session GREEN_SESSION_ID \
--current-filename step-current.jpg --baseline-filename step-green.jpg
Belege bleiben standardmäßig 30 Tage ab Jobende erhalten, wählbar sind 1–365 Tage. --pin verhindert die automatische Löschung bis zum Entpinnen; eine ausdrückliche Löschung entfernt auch angepinnte Dateien. --delete erfordert einen abgeschlossenen Job. Gelöschte oder nicht gespeicherte Dateien können nicht zurückgeholt werden.
--no-store-artifacts verhindert persistente Screenshots, Videos, UI-Bäume, Logcat und Modell-Ein-/Ausgabedateien. Live-Beobachtung bleibt möglich. Der Auftrag selbst mit Prompt, Zusammenfassung, Ereignistexten, Kennzahlen und Suchmetadaten bleibt gespeichert. Das ist keine vollständige Löschung personenbezogener Inhalte aus dem Jobtext. Details und Fristen: API: Aufbewahrung.
divergence vergleicht gespeicherte Bildschirmfolgen bestandener und nicht bestandener Wiederholungen und nennt die erste sichtbare Abweichung. compare vergleicht einen normalisierten Bereich X,Y,WIDTH,HEIGHT mit einem früheren bestandenen Job derselben Umgebung oder dem ausdrücklich gewählten Vergleichsstand. Standardgrenze: drei Prozent veränderte Pixel; --threshold ändert sie. Passende Bilddateien auswählen und bewegte Inhalte aussparen. Das Pixelergebnis samt markiertem Differenzbild ist ein eigener Beleg und ändert nicht rückwirkend das Testurteil.
Remote entwickeln mit Fast Refresh
sim dev startet einen eigenen Dev-Server bei deiner Android-Session. Metro und Paketinstallation laufen auf dem Worker. Lokal benötigt die CLI Python und deine Projektdateien, keinen laufenden Metro-Server. Sie lädt den ersten Quellstand hoch und synchronisiert anschließend geänderte und gelöschte Dateien.
sim update
# Expo mit expo-dev-client oder ein React-Native-Projekt:
sim dev --scheme myapp --package com.example.myapp
# Bereits vorhandenen Development-Build verwenden:
sim dev --apk development.apk --scheme myapp --package com.example.myapp
sim dev --status
sim dev --open
sim dev --stop
Ohne bestehende Session erstellt die CLI für Expo mit expo-dev-client oder für React Native einmalig einen nativen Debug-Build auf dem Build-Worker und installiert ihn. Bei Expo ohne diese Abhängigkeit kommt eine konkrete Fehlermeldung; die CLI fügt keine Abhängigkeiten stillschweigend hinzu. Eine bestehende Session muss bereits eine kompatible Development-APK enthalten. Bei Bedarf ausdrücklich mit sim up --variant Debug bauen oder --apk angeben. Eine Release-APK wird durch einen Metro-Server nicht zum Dev-Client.
--scheme und --package werden, soweit vorhanden, aus einer statischen app.json übernommen. Dynamische Projektkonfigurationen können diese Angaben ausdrücklich benötigen. --once lädt hoch, wartet auf den gestarteten Server, öffnet die App und beendet nur die lokale CLI. --interval setzt den Abstand der Dateiprüfung, Standard zwei Sekunden. Während der Dateibeobachtung erneuert die CLI die Session alle etwa 25 Sekunden, auch ohne Änderungen. Eine ausdrücklich gebuchte Reservierungsfrist bleibt verbindlich. Netzfehler und ein laufender Test verzögern die Synchronisierung; die CLI versucht dieselbe Session erneut. Strg+C beendet nur die lokale Synchronisierung; Server mit sim dev --stop stoppen. Beim Freigeben der Session wird er ebenfalls bereinigt.
Für besondere Projekte: --framework custom --command '…', optional --install-command '…'. Diese Befehle laufen im isolierten Container auf dem zugewiesenen Worker, nicht auf deinem Rechner oder dem API-Server. Dev-Server sind an die Session gebunden; parallele Agents verwenden eigene Testumgebungen. Ein bereits laufender Server wird nicht still ersetzt. Ein erneutes sim dev setzt mit der privaten lokalen Quellrevision derselben Session fort. Bei einem fremden Quellstand wird angehalten, statt ihn zu überschreiben. Für eine bewusst neue Serverkonfiguration zuerst stoppen und neu starten.
Es gelten Git-Dateiauswahl, .simignore und dieselben Geheimnis-/Abhängigkeitsfilter wie beim Build. Grenzen pro Upload: 100 MiB ZIP, 500 MiB entpackt und 20.000 Einträge. Native Änderungen und neue native Abhängigkeiten benötigen weiterhin einen passenden APK-Build. Reinstallationen verwenden adb install -r zum Erhalt vorhandener Android-App-Daten; Paketname und Signatur müssen passen. App-eigene Migrationen und ablaufende Backend-Sitzungen können den Login unabhängig davon ändern.
Ein Neustart des Dev-Server-Kontrolldienstes beendet laufende Dev-Server. Sie werden derzeit nicht automatisch mit ihrem Quellstand wiederhergestellt. Prüfe danach den Status, stoppe den alten Dev-Server ausdrücklich, warte auf stopped und starte sim dev erneut. Dabei wird der Quellstand erneut hochgeladen; die gespeicherten Android-App-Daten sind davon getrennt.
Während eines aktiven Modelltests wartet der Datei-Watch mit Änderungen, damit der geprüfte Stand stabil bleibt. Übernimm oder stoppe den Test, wenn du den Dev-Server konfigurieren, synchronisieren, stoppen oder die App erneut öffnen möchtest. Neue Jobs und resume werden mit HTTP 409 abgewiesen, solange ein konfigurierter Dev-Server nicht ready:true meldet; nach Bereitschaft erneut aufrufen. Ein Custom-Server muss im Container auf 0.0.0.0:8081 lauschen und GET /status mit HTTP 2xx beantworten; ein bestimmter Antworttext ist nicht erforderlich.
Dateien, Zwischenablage, Logs und OTA
sim files Pictures --upload product.png
sim files Pictures
sim files Pictures/product.png --output downloaded.png
sim clipboard --file input.txt
sim clipboard
sim --json logcat --package com.example.myapp --limit 200
sim --json logcat --package com.example.myapp --after CURSOR --follow
sim updates com.example.myapp --channel preview --action reload \
--provider-uri content://com.example.myapp.updates \
--revision-probe-uri content://com.example.myapp.revision
Dateien liegen in Download, Pictures, DCIM oder Movies mit Unterordnern, maximal 50 MiB pro Datei. Uploads stoßen Androids Medienindex an, damit Bilder in Auswahlansichten erscheinen können. clipboard --file liest eine ausdrücklich gewählte UTF-8-Datei; ohne Datei wird die Zwischenablage ausgelesen. Grenze: 16.384 Zeichen und 65.536 UTF-8-Bytes.
logcat liefert lines, next_cursor und has_more, ohne den Logpuffer zu leeren. Ohne Cursor startet es bei den letzten Zeilen; --follow liefert JSON-Objekte pro Zeile. Ein Cursor gehört zu seiner Session und seinem Paketfilter. Das ist eine laufende Geräteabfrage und von den gespeicherten Job-Logcat-Artefakten getrennt. process_restarted, gap_detected, coverage und truncated zeigen Prozesswechsel oder fehlende Abdeckung an; Androids Ringpuffer ist kein unbegrenztes Archiv.
updates braucht einen von der App unterstützten Weg: genau einen --provider-uri oder --deep-link. Der Provider erhält die Methode sim_update mit Kanal und Aktion. --action check ist der Standard, reload fordert Neuladen an. Die API bestätigt die Zustellung; erst before, after, channel_verified und update_changed belegen den beobachteten Stand. Sie kann keine beliebige Release-App ohne deren Update-Schnittstelle auf einen anderen Kanal zwingen.
Ablaufhistorie und Quarantäne
sim update
sim test "Prüfe den Produktdialog" --test-key catalog/product-dialog
sim --json flakes --app fashion --environment main
sim --json flakes FLOW_KEY --app fashion --window 100 --kind maestro
sim --json flakes --app fashion --revision SOURCE_REVISION \
--since 2026-09-01T00:00:00Z --until 2026-10-01T00:00:00Z
sim quarantine FLOW_KEY --app fashion --reason 'Untersuchung zu #673' \
--until 2026-10-05T12:00:00Z
sim quarantine FLOW_KEY --app fashion --clear
flakes liest standardmäßig 20 abgeschlossene Jobs je Ablauf, wählbar 1–200 mit --window. App und Umgebung folgen der Projektauswahl; es wird kein Gerät gestartet. Mit dem zurückgegebenen flow_key liest du Details. Filter: --kind model|maestro, --model mit gespeicherter Modellkennung oder robot/qwen/astra/opus, --revision sowie --since/--until. Zeitangaben sind Unix-Sekunden oder ISO-8601 mit Zeitzone, beide Grenzen einschließlich.
Modelltests benötigen --test-key: eine stabile, ausdrücklich gewählte Identität für denselben fachlichen Test, unabhängig von Prompt-Wortlaut und Ticket-ID. Zulässig sind 1–200 ASCII-Zeichen, beginnend mit Buchstabe oder Ziffer; anschließend zusätzlich _ . : / -. Ohne Schlüssel wird ein Modelljob nicht in diese Historie einsortiert. Maestro verwendet immer den Einstiegspfad innerhalb des ZIPs, auch wenn sich die ZIP-ID ändert; dort beeinflusst test_key die Identität nicht.
quarantine verlangt beim Aktivieren eine Begründung. Ohne --until gilt die Markierung bis zum ausdrücklichen Aufheben; --clear entfernt die aktive Quarantäne. Änderungen werden mit Zeitpunkt und Bearbeiter protokolliert. Quarantäne überspringt keinen Lauf, verändert keine Job-Ergebnisse und wirkt nur in dieser App-Umgebung.
Die Antwort trennt failure_rate, mixed_job_rate und flip_rate. gate ist eine separate aktuelle Überwachungsentscheidung; historische Rohurteile bleiben maßgeblich, solange deine Pipeline Quarantäne nicht ausdrücklich berücksichtigt. Definitionen und Grenzen der Kennzahlen →
Benannte Snapshots und wiederverwendbare Tests (CLI 0.9.0)
sim update installiert diese Befehle. Standardmäßig speichert sim down die App-Daten wie bisher. Mit sim up --persistence discard gilt für diese Session stattdessen Verwerfen als Standard. sim down --discard oder --save überschreibt den Standard ausdrücklich. Verwerfen erhält den letzten gespeicherten Zustand der Umgebung; aktuelle lokale Änderungen werden verworfen. Job-Berichte bleiben.
sim snapshot --app fashion --environment main --name "Angemeldet vor Checkout"
sim snapshots --app fashion
# SNAPSHOT_ID ist die unveränderliche n_... ID aus der Liste.
sim up --app fashion --environment checkout-branch --from-snapshot "$SNAPSHOT_ID" --persistence discard
sim down --app fashion --environment checkout-branch --discard
sim snapshot-delete "$SNAPSHOT_ID" --app fashion
Ein aktiver Checkpoint hält Android für eine konsistente Sicherung kurzzeitig an und startet anschließend dieselbe Session wieder. Die Sicherung kann mehrere Minuten dauern; währenddessen kann das Gerät nicht bedient werden. Aktive Tests müssen vorher beendet werden. Standardmäßig wartet sim snapshot auf ready; --no-wait liefert sofort den Status, sim snapshots ID fragt ihn erneut ab. --from-saved erstellt einen Snapshot einer gestoppten, fertig gesicherten Umgebung. Namen dürfen mehrfach vorkommen; verwende die eindeutige ID.
Restore benötigt eine neue oder noch leere Zielumgebung und überschreibt keinen vorhandenen gespeicherten Stand. sim up --from-snapshot ID stellt die installierten Apps mit ihren lokalen Daten wieder her, ohne einen Build zu starten. Optional aktualisiert --apk app.apk danach die APK. Gleicher Paketname und Signatur sind für eine datenbewahrende Installation erforderlich. Snapshots sichern nur lokalen Android-Zustand: Änderungen in Supabase, anderen Backends oder Partner-Shops werden weder durch Restore noch durch Discard rückgängig.
Test einmal beschreiben, geprüft wiederverwenden
Eine Testdefinition gehört zur App und kann in verschiedenen Umgebungen laufen. Zum Beispiel enthält login-test.json:
{
"id": "login-home",
"name": "Anmelden und Startseite prüfen",
"task": "Melde dich mit {{email}} und {{password}} an. Prüfe anschließend die Startseite.",
"model": "robot",
"variables": [{"name": "email", "secret": true}, {"name": "password", "secret": true}],
"criteria": [{"id": "home", "kind": "text_visible", "description": "Explore ist sichtbar", "value": "Explore"}],
"options": {"capture_video": true}
}
sim test-create --app fashion --file login-test.json
sim tests --app fashion
sim test-run login-home --app fashion --mode learn --bindings-file /private/login-values.json
sim test-run login-home --app fashion --mode auto --bindings-file /private/login-values.json
sim tests login-home --app fashion
sim test-update login-home --app fashion --file test-patch.json --expected-version 1
sim test-delete login-home --app fashion
Die private Bindings-Datei enthält ein JSON-Objekt mit den Werten der deklarierten Variablen. Speichere sie außerhalb des Quellprojekts mit Dateirechten 600. Werte werden bei jedem Lauf bereitgestellt und dem gewählten Modell als privater Kontext übergeben; sie sind keine gespeicherten Defaults der Definition. Die CLI schreibt sie nicht in ihren Projektzustand. Tippeingaben müssen auf Bindings zurückführbar sein. Ausgenommen ist ausdrücklich im öffentlichen Testauftrag oder Abnahmekriterium genannter wörtlicher Testtext in einem Feld, das kein Passwortfeld ist. Passwortwerte und sonstige Eingaben benötigen Bindings. Screenshots und UI-Inhalte können trotzdem personenbezogene Informationen zeigen; verwende passende Artefakt-Aufbewahrung oder store_artifacts: false in den Optionen.
auto verwendet einen verfügbaren passenden Plan oder lernt über das Modell. learn führt den Modellpfad aus. replay benötigt einen bereits gespeicherten Plan (andernfalls HTTP 409). Pointer findet Ziele auf dem aktuellen Screenshot; UI-Prüfungen sichern die Schritte ab, bei Abweichungen übernimmt das Modell. Ein Ablauf ist nicht allein durch das Abspielen grün: Abnahmekriterien werden weiterhin geprüft. Eine KI-Prüfung bewertet Zielerfüllung und Effizienz beim Erstlernen sowie nach geänderten oder reparierten Wegen. Unverändertes Replay eines bereits geprüften Plans erhält keine zusätzliche Optimierungsprüfung; Abnahmekriterien bleiben verbindlich. Lehnt sie ab oder ist sie nicht verfügbar, wird ein beanspruchtes passed zu inconclusive; der Ablauf wird nicht als Plan übernommen. Zeit und Tokens dieser Prüfung zählen mit. Pointer liefert keinen verlässlichen Konfidenzwert; die Absicherung beruht auf beobachtetem UI-Zustand. Ein erfolgreicher Lauf garantiert nicht, dass ein wiederverwendbarer Plan gelernt werden konnte.
--options-file overrides.json überschreibt Laufoptionen (z. B. Wiederholungen, Retention, Video). --request-id dedupliziert erneutes Absenden; --no-wait liefert den Job sofort. Danach funktionieren sim watch, sim result, Übernahme und Artefakte wie bei gewöhnlichen Tests. Definitionsänderungen erhöhen version und verwerfen den bisherigen Plan; --expected-version verhindert veraltete Änderungen. Aktive Aufrufe verhindern Löschen der Definition. Die Monitoring-Identität ist automatisch e2e:<Test-ID>, unabhängig vom Prompt.
Erstlernen sowie geänderte oder reparierte Wege erhalten eine KI-Prüfung. Unveränderte geprüfte Pointer-Wege brauchen keine erneute Optimierungsprüfung. Eine erfolgreich reparierte und vollständig geprüfte Route aktualisiert den Plan für spätere Läufe automatisch. Frühere Versionen bleiben in plan_history mit Quell-Job und Review nachvollziehbar (sim tests ID). Vorschläge für unnötige Schritte werden protokolliert; eine ungeprüfte kürzere Route wird nicht übernommen. Explizites Stoppen beendet laufende Modellinferenz; Strg+C beim CLI-Warten beendet nur die Beobachtung.
Auch sim reserve --from-snapshot ID --persistence discard stellt eine neue Umgebung aus einem Snapshot in die Warteschlange. Aktive Checkpoints sichern keine Metro-Quelldateien oder Abhängigkeiten; ein laufender Remote-Dev-Server bleibt bestehen und wird nach dem Android-Neustart wieder verbunden.
Unverändertes Replay meldet review.status: reused; visuelle Kriterien können weiterhin Modellprüfung benötigen. Vorgeschlagene geschlossene Navigationsumwege können als optimization_candidate im nächsten Lauf geprüft werden. Erst nach UI-Prüfungen, Abnahmekriterien und KI-Prüfung wird der verkürzte Weg zum neuen Plan.
Beim Erstlernen sowie nach reparierten oder optimierten Wegen prüft Qwen die mit Robot gelernten Abläufe auf Zielerfüllung und Effizienz. Bei Qwen, Astra und Opus übernimmt jeweils das gewählte Modell selbst die Prüfung. Unveränderte geprüfte Wiederholungen erhalten keine zusätzliche Optimierungsprüfung. Zeit, Tokens und Kostenschätzung werden dem tatsächlich verwendeten Review-Modell zugeordnet; ein Robot-Lauf kann zusätzlich Qwen-Verbrauch enthalten.
Ein im Prüflauf nicht bestätigter optimization_candidate wird als anstehender Kandidat entfernt. Der bisher geprüfte Ablauf bleibt. Die öffentliche optimization_history dokumentiert den Versuch und sein Ergebnis (sim tests ID).
Ein Android-Gerät per HTTP.
Dieselbe API für deinen Agent, deine CLI und den Browser. JSON für Steuerung und Ergebnisse, direkte Datei-Uploads für Quellstand und APK.
Authentifizierung
Erstelle im Account einen API-Token. Er wird nur einmal angezeigt. Sende ihn bei API-Aufrufen als Bearer-Token. Ein Token greift ausschließlich auf den zugehörigen Account zu.
curl https://sim.davidhe.de/v1/apps \
-H "Authorization: Bearer $SIM_API_KEY"
Die folgenden Beispiele setzen voraus, dass dein Secret-Manager SIM_API_KEY bereitstellt. Die vollständigen Request- und Response-Schemas findest du in OpenAPI.
1. Session starten
curl -X POST https://sim.davidhe.de/v1/sessions \
-H "Authorization: Bearer $SIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"workspace":"meine-app","environment":"login-agent","name":"Login-Test","fresh":false,"request_id":"start-login-001"}'
Die Antwort enthält die Session-ID. Frage GET /v1/sessions/{id} ab, bis ready den Wert true hat. Nutze dieselbe request_id beim Wiederholen desselben Start-Aufrufs, um keine zusätzliche Session anzulegen.
Ein Workspace identifiziert deine App dauerhaft. environment wählt ihre Testumgebung; ohne Angabe ist es main. Verschiedene Umgebungen laufen unabhängig. Ohne fresh:true werden deren gespeicherte Android-Daten wiederhergestellt. Neue Umgebungen übernehmen einen vorhandenen gemeinsamen Ausgangszustand.
Umgebungen und Ausgangszustand
# Umgebungen einer App auflisten
curl "https://sim.davidhe.de/v1/apps/meine-app/environments" \
-H "Authorization: Bearer $SIM_API_KEY"
# Umgebung ohne laufendes Gerät anlegen
curl -X POST "https://sim.davidhe.de/v1/apps/meine-app/environments" \
-H "Authorization: Bearer $SIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"id":"checkout-agent","from_baseline":true}'
# Einen bereits gestoppten und gesicherten Stand als Vorlage veröffentlichen
curl -X POST "https://sim.davidhe.de/v1/apps/meine-app/baseline" \
-H "Authorization: Bearer $SIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"environment":"main"}'
Ein Ausgangszustand wird nur aus einer vollständig gesicherten Umgebung erstellt. Solange sie läuft oder gesichert wird, antwortet der Server mit 409. Neue Umgebungen bekommen eine Kopie; bestehende Umgebungen werden nicht überschrieben. Namen erlauben Buchstaben, Zahlen, Unterstrich und Bindestrich, maximal 80 Zeichen.
2. APK installieren
curl -X POST "https://sim.davidhe.de/v1/sessions/$SESSION_ID/apk?package=com.example.meineapp" \
-H "Authorization: Bearer $SIM_API_KEY" \
-H "Content-Type: application/octet-stream" \
--data-binary @app.apk
Der Request-Body enthält die APK direkt, kein Multipart-Formular. Die App wird installiert und geöffnet. Gib den Paketnamen an, wenn die App nicht eindeutig erkannt werden kann. Updates behalten bei passender Signatur ihre Daten.
3. Test beauftragen
curl -X POST "https://sim.davidhe.de/v1/sessions/$SESSION_ID/jobs" \
-H "Authorization: Bearer $SIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"task":"Öffne die Suche und prüfe, ob rote T-Shirts gefunden werden.",
"model":"robot",
"context":"Die Suche erreichst du im Tab Entdecken.",
"request_id":"search-test-001"
}'
Ein angenommener Auftrag liefert HTTP 202 und eine Job-ID. Frage den Job ab, um Status, Aktionen, Laufzeit, Token-Verbrauch, Kostenschätzung und Ergebnis zu lesen. Pro Session läuft ein Test gleichzeitig.
curl "https://sim.davidhe.de/v1/sessions/$SESSION_ID/jobs/$JOB_ID" \
-H "Authorization: Bearer $SIM_API_KEY"
curl "https://sim.davidhe.de/v1/sessions/$SESSION_ID/screenshot" \
-H "Authorization: Bearer $SIM_API_KEY" \
--output screenshot.jpg
Nutze die Artefakt-URLs aus der Job-Antwort für die zugehörigen Screenshots. Berichte und aufgezeichnete Screenshots bleiben nach dem Beenden einer Session verfügbar.
Abgeschlossen bedeutet nicht automatisch bestanden. status: completed bezeichnet den Abschluss des Modellauftrags. Prüfe outcome, strukturierte criteria_results, Wiederholungen und ihre Belege. Screenshots entstehen pro Modellschritt, der mehrere Geräteaktionen enthalten kann. Das Artefaktmanifest enthält außerdem UI-Baum, Logcat und verfügbare Videos; Erfassungsfehler werden ausdrücklich ausgewiesen.
context und source_files werden in der ausgewählten Testumgebung gespeichert und bei späteren Aufträgen ohne neuen Kontext wiederverwendet. Ein neuer nichtleerer Kontext ersetzt den bisherigen. Wiederhole bei Netzfehlern denselben Job-Request mit derselben request_id innerhalb derselben Session; für einen neuen Test verwende eine neue ID. Build-ID und Quellstand beschreiben die installierte APK, nicht ein später geladenes OTA-Bundle.
Remote-Builds
Ein Build besteht aus einem Auftrag und einem ZIP-Upload. Die CLI übernimmt die sichere Projektauswahl und Verpackung; über HTTP kannst du diesen Ablauf selbst implementieren.
# 1. Build anlegen; ID aus der Antwort verwenden
curl -X POST https://sim.davidhe.de/v1/builds \
-H "Authorization: Bearer $SIM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"workspace":"meine-app","environment":"checkout-agent","config":{"framework":"gradle"},"no_cache":false}'
# 2. Quellstand hochladen
curl -X PUT "https://sim.davidhe.de/v1/builds/$BUILD_ID/source" \
-H "Authorization: Bearer $SIM_API_KEY" \
-H "Content-Type: application/zip" \
--data-binary @source.zip
# 3. Status und Logs abfragen
curl "https://sim.davidhe.de/v1/builds/$BUILD_ID" \
-H "Authorization: Bearer $SIM_API_KEY"
# 4. Fertige APK direkt in die Session installieren
curl -X POST "https://sim.davidhe.de/v1/sessions/$SESSION_ID/builds/$BUILD_ID" \
-H "Authorization: Bearer $SIM_API_KEY"
Lege Projektdateien relativ zum Projektroot ins ZIP, ohne übergeordneten Archivordner, Symlinks oder Geheimnisse. Ein projektspezifischer Cache beschleunigt Folgebuilds. Mit no_cache:true wird eine neue APK gebaut, statt ein fertiges Build-Artefakt wiederzuverwenden. Der projektspezifische Abhängigkeits- und Gradle-Cache bleibt nutzbar.
Endpunkte im Überblick
¹ Tokens verwaltest du mit deiner angemeldeten Account-Sitzung, etwa im Browser oder beim CLI-Login. Ein Agent-Token kann keine weiteren Tokens erstellen.
Stoppen und wieder aufnehmen
# Laufenden Test abbrechen, Gerät behalten
curl -X POST "https://sim.davidhe.de/v1/sessions/$SESSION_ID/stop" \
-H "Authorization: Bearer $SIM_API_KEY"
# App-Daten sichern und Session beenden
curl -X DELETE "https://sim.davidhe.de/v1/sessions/$SESSION_ID" \
-H "Authorization: Bearer $SIM_API_KEY"
Aktive Tests halten die Session automatisch am Leben. Wenn dein Agent sie ohne Test weiter benötigt, sende regelmäßig einen Heartbeat. Zum Fortsetzen startest du später denselben Workspace.
Fehler behandeln
Prüfe immer den HTTP-Status und das JSON-Feld detail. 401 bedeutet fehlende oder ungültige Anmeldung, 403 fehlende Berechtigung und 404 eine nicht verfügbare Ressource. Bei einem belegten Gerät warte auf den laufenden Test oder stoppe ihn bewusst. Polling mit einigen Sekunden Abstand reicht für Build- und Testfortschritt.
Autonomous pipelines (CLI 0.9.0, MCP 0.7.0)
All operations below require the same account Bearer token. They use the same session/job IDs across HTTP, CLI and MCP. Artifacts stay private and remain available after releasing a device. Download /v1/connector again and restart its process for MCP updates; sim update updates the standalone CLI.
Persistent briefing
GET, PUT, DELETE /v1/apps/{app}/briefing manage private app-level context:
{
"context": "Fashion app. Explore contains product search; the partner shop opens in a browser.",
"credentials": {"email": "android-test@example.invalid", "password": "TEST_PASSWORD"},
"known_pitfalls": ["Onboarding: choose women, enter age and sizes, skip colors, like two products."]
}
PUT replaces the briefing. New jobs receive this default together with the selected environment's saved context/source excerpts and the new task. Updating the briefing does not change an already running job. Credentials are supplied to the selected inference provider as test context; use test accounts. Read/write through a private JSON file (chmod 600) rather than a shell-history argument. DELETE removes the app default; it does not erase older job records or separately saved environment context.
Criteria, repetitions and evidence
POST /v1/sessions/{sid}/jobs accepts these additional fields:
{
"task": "Open Explore and search red T-shirts. Inspect the result screen.",
"model": "robot",
"kind": "model",
"criteria": [
{"id": "results", "description": "Product cards are visible without clipped images", "kind": "visual"},
{"id": "title", "description": "Explore heading is present", "kind": "text_visible", "value": "Explore"},
{"id": "error", "description": "No error message is visible", "kind": "text_absent", "value": "Something went wrong"}
],
"repeat_count": 5,
"reset_between": "restart_app",
"package": "dev.example.app",
"recovery_after": 3,
"capture_video": true,
"request_id": "issue-412-revision-abc-test-1"
}
kind is model (default) or maestro. repeat_count accepts 1–1000 and defaults to 1; capture_video defaults to true. reset_between is none (keep the preceding run's Android state), restart_app (force-stop and launch the selected package) or clear_data (erase only that package's local data, then launch). Supply package for resets. Clear-data repetitions lose login and are not full fresh Android devices. No reset policy resets external backend data. For a fully fresh Android use a separate environment with fresh:true. Repetition counts describe requested trials, not a total model step/time limit.
Read the job with GET /v1/sessions/{sid}/jobs/{job}. Lifecycle status is separate from test outcome:
criteria_results contains id, description, status (passed, failed, not_verified), method, evidence and artifact names. Text checks match case-insensitive substrings in UI text/content descriptions, scoped to the selected package; empty trees are not_verified. The top-level criteria are the last repetition. repetitions records each run, and repeat_summary returns requested, completed, outcomes counts, varied and pass_rate (0–1). A mixed series must remain visible as mixed; inspect counts and individual failures rather than accepting the last successful run. Image/visual assertions are model judgments, not pixel-identical proofs. A UI hierarchy may omit custom-drawn content.
GET /v1/sessions/{sid}/jobs/{job}/artifacts returns the evidence manifest. Download names returned by that manifest at GET /v1/sessions/{sid}/jobs/{job}/artifacts/{filename} using your Bearer token. Evidence includes per-step screenshots, UI hierarchy XML, Logcat and recorded video when capture succeeds. A model step can contain multiple device actions. Capture failures are explicit in the report; a missing recording is not proof that nothing happened. Artifacts can contain entered test-account data.
GET /v1/sessions/{sid}/jobs/{job}/observe captures a current screenshot and UI hierarchy and returns artifact references. Use this while the job is paused or under caller control to understand the exact device state.
Questions and temporary caller control
When the device agent cannot infer the intended branch safely, the job can enter needs_input and expose a question with its ID. The device state is retained. Answer the current question with:
POST /v1/sessions/{sid}/jobs/{job}/answer
Content-Type: application/json
{"question_id":"ID_FROM_JOB","answer":"Choose the lower Continue button in the onboarding footer."}
After repeated unsuccessful navigation (recovery_after, default 3), the caller can intervene rather than losing the run. It can also request takeover explicitly:
POST .../jobs/{job}/takeover with {} pauses the inner agent at a safe action boundary.GET .../jobs/{job}/observe supplies screenshot and UI tree.POST .../jobs/{job}/actions executes a bounded list of native actions.POST .../jobs/{job}/resume with {"message":"Onboarding is complete. Continue the original checks."} returns control to the testing agent.
{"actions":[{"action":"tap","x":0.5,"y":0.85},{"action":"text","text":"red T-shirt"},{"action":"key","key":"ENTER"}]}
Supported action names: tap, swipe, text, key, keycombo, wait, launch. Coordinates x, y, x2, y2 use 0–1 relative to the original Android display, not the model's letterboxed image. duration is milliseconds. key/keys use Android names without KEYCODE_, e.g. BACK, ENTER; launch uses package. At most 10 native actions are accepted per request. No shell commands are accepted. Stale question IDs, actions without caller control or an incompatible lifecycle return a conflict; re-read the job before retrying. Stop a job with the existing session /stop.
An autonomous caller should loop over job state: answer needs_input, inspect and repair under caller control if useful, then resume. On terminal status, check outcome, every criterion, repetition distribution and evidence. An HTTP-successful GET or status: completed alone is never a test pass.
Maestro suites
Upload a ZIP of explicitly selected Maestro YAML flows and their relative assets with POST /v1/flows, raw bytes (application/octet-stream), at most 8 MiB ZIP, 32 MiB expanded and 256 entries. GET /v1/flows lists uploads; DELETE /v1/flows/{id} removes an upload after its jobs finish. The response contains id; use it as flow_id in a job with kind:"maestro". Files are relative to the selected flow directory, with no parent directory, path traversal or symlinks. The standalone clients package this directory without running any of its content on the caller's machine.
{"kind":"maestro","flow_id":"FLOW_ID","flow_paths":["smoke.yaml","search.yaml"],"task":"Run the Android regression suite","repeat_count":5,"reset_between":"clear_data","package":"dev.example.app","capture_video":true,"request_id":"suite-rev-abc-trial-1"}
Use optional flow_paths:["smoke.yaml","search.yaml"] to select ordered entrypoints. Referenced helper flows remain in the bundle. Ohne Auswahl starten nur YAML-Dateien direkt im ZIP-Hauptverzeichnis, ersatzweise direkt in .maestro/. Verschachtelte Helper starten nicht automatisch. Enthält das Paket config.yaml/config.yml oder nur tiefer verschachtelte Einstiegspunkte, sind explizite flow_paths erforderlich; sonst kommt HTTP 422 vor dem Jobstart. Config-Include/Exclude/Reihenfolge wird nicht automatisch übernommen.
Inspect each flow's result, execution logs, screenshots/recordings and Logcat, not just the process exit code. Maestro uses YAML assertions; separate model criteria are rejected. Repeated trials report the individual runs so flaky failures can be compared. Source files referencing external absolute paths are not portable; package referenced assets with the flows. ADB/device access stays inside the selected customer's test device.
Gesammelte Maestro-Artefakte sind auf insgesamt 512 MiB pro Job begrenzt; eine Überschreitung ist ein ausdrücklicher Erfassungsfehler. Das Manifest enthält Größe, SHA-256 und mime, etwa application/xml für JUnit, video/mp4 für Videos und image/png für Screenshots. Verwende den angegebenen MIME-Typ; nicht alle Dateien sind JPEG-Bilder. Maestro-Berichte enthalten flow_id, die ausgewählten flow_paths und den Archiv-Hash flow_sha256 als Ausführungsstand.
Device configuration and revision
POST /v1/sessions/{sid}/configure supports:
{
"permissions": [{"package":"dev.example.app","permission":"android.permission.POST_NOTIFICATIONS","grant":true}],
"deep_link": "exampleapp://explore",
"package": "dev.example.app",
"offline": false,
"timezone": "Europe/Berlin"
}
Optional time requests device wall-clock time; reset_clock:true restores network/automatic time. Device wall-clock changes do not move Supabase or any other backend's clock. Offline changes may affect app connections immediately; restore with offline:false. Android may reject undeclared/non-runtime permissions or unsupported clock changes; inspect the operation result.
GET /v1/sessions/{sid}/revision?package=dev.example.app returns installed package/version evidence. Jobs retain installed build/source/APK identity. An APK hash cannot prove which OTA JavaScript update is currently active. A job may supply revision_probe:{"uri":"content://dev.example.app.test/revision"} to read an app-provided test content provider. This requires instrumentation in the app, must use a content URI without query or fragment, and is recorded as app_reported, not independently verified. The provider can expose update ID, channel and runtime version; absent instrumentation means OTA identity remains unknown. The same optional probe is available on the revision GET as probe_uri=content://.... Do not infer a fresh OTA from a successful APK install alone.
Die Antwort enthält revision, update_channel, update_id, runtime_version und bundle_hash als Strings oder bei unbekannten Werten null. ota_verified bleibt false. Der Test-Content-Provider muss genau eine Zeile mit expliziten Spalten liefern:
Row: 0 revision=abc123, update_channel=preview, update_id=update-42, runtime_version=2.4.4, bundle_hash=abcd1234
Werte dürfen 1–256 Zeichen aus Buchstaben, Ziffern und . _ : + / @ - enthalten. Mehrere Zeilen, doppelte Spalten oder fehlerhafte Ausgaben ergeben keinen Revisionsnachweis. ota enthält source:"app_reported", uri, den Rohwert value, available und gegebenenfalls error. Ohne Probe bleibt ota:null. Providerfehler verhindern die APK-Versionsabfrage nicht. Die Werte sind App-Auskünfte, keine unabhängige Verifikation.
Capacity, reservations and callbacks
GET /v1/capacity reports customer-facing available capacity and queue state. POST /v1/reservations queues a device request with {workspace,environment,name?,request_id,ttl_seconds:1800,wait_timeout_seconds:3600,fresh:false}. List your reservations with GET /v1/reservations. Read GET /v1/reservations/{id} until status:allocated and use session_id; other statuses are queued, released, cancelled, expired, failed. Mit sim up --session-id SESSION_ID --app fashion --environment agent-4 kannst du anschließend auf genau diesem Gerät bauen und installieren. Die App/Umgebung muss zur Reservierung passen; --fresh ist mit einer vorhandenen Session-ID nicht möglich. DELETE /v1/reservations/{id} cancels and releases the reservation. Both time fields accept 60–86400 seconds. wait_timeout_seconds bounds queue waiting; ttl_seconds starts at allocation and produces absolute expires_at. Expiry stops even an active job, saves Android data and releases the device. Heartbeats do not extend this explicit hard lease. Normal /v1/sessions creation has no hard test time limit and active tests retain that session; it can return a capacity conflict instead of queuing.
GET /v1/webhooks, POST /v1/webhooks with {url,secret?} and DELETE /v1/webhooks/{id} manage signed completion callbacks. The creation response includes the secret once. Store it privately. Supply the returned webhook_id in the job POST. Treat callbacks as notifications: fetch the account-authorized job result to inspect evidence and make the release decision. Callbacks include id, type (job.completed or job.needs_input), session_id, job_id, status, outcome, result_url, without private briefing or screenshots. Headers: X-Sim-Event-Id, X-Sim-Timestamp (epoch seconds), X-Sim-Signature: sha256=HEX. Verify HMAC-SHA256 with the hook secret over timestamp + "." + raw_request_body; compare signatures in constant time and reject stale timestamps. Use the exact body bytes, not reserialized JSON.
import hashlib, hmac, time
stamp = request.headers["X-Sim-Timestamp"]
expected = "sha256=" + hmac.new(secret.encode(), stamp.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
valid = abs(time.time() - int(stamp)) < 300 and hmac.compare_digest(expected, request.headers["X-Sim-Signature"])
Handle duplicate deliveries using the event ID. Delivery is at-least-once with up to 10 attempts and exponential delay capped at one hour. Public HTTPS port 443 destinations only; private addresses and redirects are rejected. A custom secret must contain 32–200 characters. GET /v1/webhooks/{id}/deliveries exposes delivery status/errors. Registration does not send your sim API token to the recipient. Delivery errors do not change test outcomes.
Job creation request_id is scoped to the same session. Reuse it on network retries to obtain the same job; use a new key for a new trial/series. Reservation keys similarly distinguish retry from a new capacity request. HTTP 401 means missing/invalid authentication, 404 means inaccessible or missing resource, 409 means conflicting state or capacity, and 422 means invalid input. Inspect detail; do not convert every transport failure into an app failure.
Geräteprofile und Locale
GET /v1/device-profiles liefert unterstützte Profile mit Auflösung und Dichte. POST /v1/sessions und POST /v1/sessions/{sid}/configure akzeptieren device_profile, alternativ display:{width,height,density}, sowie locale als BCP-47-Code. Profile: compact, large, tablet. Die Konfiguration gehört zur Testumgebung und bleibt beim Speichern/Fortsetzen erhalten. Eigene Displays erlauben 320–3200 Pixel pro Achse, maximal 6 Millionen Pixel, 120–640 dpi und mindestens 240 dp pro Achse.
{"workspace":"fashion","environment":"english-tablet",
"request_id":"english-tablet-start-001","device_profile":"tablet","locale":"en-US"}
device_profile und display sind gegenseitig ausschließend. Nicht gesendete Werte werden beibehalten. Die Profile ersetzen keinen Test auf echter Herstellerhardware. Änderungen an einem belegten Gerät erfordern Caller-Übernahme; sonst HTTP 409. Der Konfigurationsbericht zeigt die tatsächlich angewandten Werte. Die Sprache einer App mit eigener Locale-Auswahl kann unabhängig vom Gerät sein.
Jobs suchen und den Agent live überprüfen
Zusätzliche Felder bei POST /v1/sessions/{sid}/jobs, für Modell- und Maestro-Jobs:
{"task":"Prüfe den Produktdialog","external_id":"#673",
"tags":{"branch":"fix/dialog","pipeline":"issues"},
"store_artifacts":true,"artifact_retention_days":30,
"needs_input_timeout_seconds":300}
GET /v1/jobs unterstützt q, external_id, request_id, workspace, environment, outcome und tag=KEY:VALUE; URL-Encoding verwenden, insbesondere für #. limit liegt zwischen 1 und 200, Standard 200; offset beginnt bei 0. Die Suche umfasst nur eigene Jobs, einschließlich beendeter Sessions. external_id ist ein Suchmerkmal, kein Idempotenzschlüssel.
GET /v1/jobs?external_id=%23673&tag=branch%3Afix%2Fdialog&limit=20&offset=0
GET /v1/sessions/{sid}/jobs/{jid}/live?after=0
GET /v1/sessions/{sid}/jobs/{jid}/events?after=0
live liefert status, outcome, terminal, cursor, has_more, neue events, question, metrics, artifact_policy und screenshot_url. Ereignis-IDs sind fortlaufend; setze beim nächsten Aufruf after=cursor. Auch bei einem abgeschlossenen Job weitere Seiten lesen, solange has_more=true. Die Screenshot-URL benötigt denselben Account-Token und liefert bei laufendem Job einen flüchtigen aktuellen Frame, danach den letzten noch gespeicherten Bildschirmbeleg oder null.
events ist Server-Sent Events mit event: update und demselben JSON-Inhalt. Last-Event-ID oder after erlaubt Wiederaufnahme. Eine Verbindung endet nach dem Abschluss und nach Auslieferung aller ausstehenden Ereignisse. Live-Ansicht ist lesend: kein Takeover, kein Geräte-Heartbeat und keine zusätzlichen Bildschirmdateien. Sie funktioniert auch mit store_artifacts:false; der aufrufende Agent kann aktuelle Bilder direkt prüfen und bei Bedarf die bestehenden Takeover-Werkzeuge verwenden.
needs_input_timeout_seconds begrenzt ausschließlich die Wartezeit auf eine Antwort: Standard 900 Sekunden, wählbar 60–86400 Sekunden; null deaktiviert sie ausdrücklich. Läuft sie ab, endet der Auftrag mit outcome: inconclusive und einer Begründung statt eines erfundenen App-Fehlers. Es gibt weiterhin kein allgemeines Zeit- oder Schrittlimit für die eigentliche Modellarbeit. Eine zugewiesene Reservierungsfrist kann den Job unabhängig davon beenden.
Private Belege: Fristen und Löschung
Bildschirmbelege, Videos, UI-Bäume und Logs sind ausschließlich über die authentifizierte API des besitzenden Accounts abrufbar. Die Standardfrist beträgt 30 Tage ab Jobende; artifact_retention_days wählt 1–365 Tage. Laufende Jobs werden nicht aufgrund dieser Frist bereinigt. artifact_policy enthält store_artifacts, retention_days, pinned, expires_at, deleted_at, deletion_reason und metadata_retained. Abgelaufene Dateien sind nicht mehr abrufbar; die Bereinigung läuft außerdem regelmäßig im Hintergrund. Die Standardfrist gilt auch für ältere Jobs ohne eigene Aufbewahrungsangabe.
PATCH /v1/sessions/{sid}/jobs/{jid}/retention
{"artifact_retention_days":90,"pinned":true}
DELETE /v1/sessions/{sid}/jobs/{jid}/artifacts
Anpinnen hebt das Ablaufdatum auf, bis pinned:false gesetzt wird. Danach gilt wieder die Frist ab dem ursprünglichen Jobende: ein bereits alter Job kann sofort ablaufen. Explizites Löschen entfernt auch angepinnte Dateien. Löschen aktiver Jobs liefert HTTP 409; erst den Test beenden. Bereits gelöschte oder nicht gespeicherte Belege lassen sich nicht wiederherstellen oder nachträglich anpinnen.
store_artifacts:false beim Jobstart verhindert persistente Screenshot-, Video-, UI-Baum-, Logcat- und Modell-Ein-/Ausgabedateien. Aktuelle Bilder können trotzdem flüchtig an den prüfenden Agent ausgeliefert werden. Jobmetadaten bleiben erhalten: Prompt, Zusammenfassung, Ereignistext, Ergebnisse, Token-/Zeitwerte und Suchmerkmale. Sie können selbst Inhalte aus der App enthalten. Der Löschendpunkt löscht Dateien, nicht diese Texte; er ist kein vollständiger Account-Löschauftrag. Keine sensiblen Daten in Auftragsbeschreibungen oder Tags schreiben, wenn auch diese nicht gespeichert werden sollen.
Build-APKs haben derzeit keinen automatischen Ablauf. Der hochgeladene Quell-ZIP wird nach dem Build entfernt; appbezogene Build-Caches bleiben bis zur ausdrücklichen Cache-Löschung erhalten. Gerätezustände und Logins folgen dem Speichern/Fortsetzen-Vertrag und sind von Job-Artefaktfristen unabhängig. Aktuelle Regeln sind auch maschinenlesbar unter GET /v1/limits.
Erste Abweichung und Bereichsvergleich
GET /v1/sessions/{sid}/jobs/{jid}/divergence?threshold=0.03 analysiert abgeschlossene Serien. Es vergleicht die erste bestandene Wiederholung mit den nicht bestandenen Wiederholungen, ordnet Screenshots nach Aufnahmefolge und liefert pro Paar first_difference mit beiden privaten Bildbelegen und Messwerten. Fehlende Bilder und unterschiedliche Folgen werden im Ergebnis offengelegt; ohne gespeicherte Bilder beider Ergebnisarten ist available:false.
Die erste sichtbare Abweichung ist ein Ansatz zur Fehlersuche, kein Beweis der Ursache. Abweichende Navigationswege, Uhrzeiten, Produktdaten und Animationen können Bilder verändern. Für präzise UI-Regressionsprüfung wähle denselben Zustand und nur den betroffenen Bereich:
POST /v1/sessions/{sid}/jobs/{jid}/compare
{"baseline_job_id":"GREEN_JOB_ID","baseline_session_id":"GREEN_SESSION_ID",
"current_filename":"step-current.jpg","baseline_filename":"step-green.jpg",
"region":{"x":0.1,"y":0.2,"width":0.8,"height":0.3},"threshold":0.03}
region ist erforderlich, normalisiert auf 0–1 und vollständig innerhalb des Bildes. Ohne Baseline-ID wird der letzte frühere bestandene Job derselben App und Testumgebung gewählt; ohne Dateinamen die letzten gespeicherten Screenshots. Ein ausdrücklich gewählter Vergleichsstand muss ebenfalls abgeschlossen und bestanden sein. Verschiedene Bildabmessungen ergeben comparable:false; Bilder werden nicht zur Passung gestreckt.
Die Auswertung liefert changed_fraction, mean_absolute_error, pixel_box, passed und diff_url mit markiertem Differenzbild. Ein Pixel zählt ab mehr als 16 Stufen Unterschied in einem RGB-Kanal als verändert; threshold ist der erlaubte Anteil veränderter Pixel, Standard 0,03. Der eigene Bereichsvergleich verändert das ursprüngliche Job-Ergebnis nicht. Vergleich und Abweichungsanalyse benötigen gespeicherte Belege; aktive Jobs liefern HTTP 409.
Kapazität und Rate-Limits
GET /v1/limits liefert die geltende Policy. Derzeit gibt es keine feste allgemeine Quote für API-Aufrufe pro Minute. Pro Session läuft höchstens ein Job, mehrere Sessions können gleichzeitig testen. Freie Kapazität steht in GET /v1/capacity; mit Reservierungen lassen sich Plätze in die Warteschlange stellen. Ein Build-Worker verarbeitet Builds nacheinander, weitere warten.
Anmeldung: höchstens 20 Versuche pro IP und 10 pro Account in einem 15-Minuten-Fenster; Registrierung: 8 pro IP. Drosselung liefert HTTP 429. Belegter Gerätezustand oder konkurrierende Steuerung liefert HTTP 409. Modellanbieter können eigene Limits setzen; deren Fehler erscheinen im Job. Zwei Sekunden Polling-Abstand sind empfohlen; SSE und Webhooks vermeiden unnötige Abfragen. Eine feste Obergrenze der Ausführungsschritte oder Gesamtdauer wird durch diese API-Policy nicht eingeführt.
Session-eigener Remote-Dev-Server
GET /v1/sessions/{sid}/dev-server liest den Zustand, POST konfiguriert einen Server und DELETE stoppt und bereinigt ihn. POST /v1/sessions/{sid}/dev-server/open öffnet den installierten kompatiblen Dev-Client am Remote-Server. Native Development-APK zuerst über die vorhandene Build-/APK-API installieren.
POST /v1/sessions/{sid}/dev-server
{"framework":"expo","package":"com.example.myapp","scheme":"myapp"}
PUT /v1/sessions/{sid}/dev-server/source?full=true
Content-Type: application/zip
<ZIP des gefilterten Projekts>
PUT /v1/sessions/{sid}/dev-server/source?full=false&base_revision=LAST_REVISION
Content-Type: application/zip
<ZIP mit geänderten Dateien und optionalem Löschmanifest>
Frameworks: expo, react-native und custom; optional command, install_command, package und scheme. custom benötigt command. Repo-Code und Paketinstallation werden nur im Container auf der exklusiv zugewiesenen Android-VM ausgeführt. Metro ist nicht öffentlich erreichbar: Android erreicht Port 8081 über die sessionspezifische ADB-Verbindung.
Ein Upload reserviert eine neue revision und liefert zunächst einen asynchronen Zustand. Mit GET warten, bis ready:true; vorher keine weiteren Änderungen senden. source_sha256 ist der tatsächlich verifizierte Quellstand, pending_revision ein noch anzuwendender Stand. Status enthält außerdem status, logs, error, url und gegebenenfalls deep_link. url ist die interne Geräteadresse, keine öffentlich aufrufbare Website.
Inkrementelle ZIPs enthalten geänderte Dateien und optional die reservierte Datei __sim_sync__.json mit {"delete_paths":["src/removed.tsx"]}. Das Manifest wird nicht als Projektdatei übernommen. base_revision muss zum letzten akzeptierten Stand passen; ein Konflikt gibt HTTP 409, statt die Änderungen eines anderen Agents zu überschreiben. Bei Fehlern Status prüfen, den Quellstand abgleichen und nötigenfalls bewusst einen vollständigen Neustart durchführen.
Grenzen: 100 MiB ZIP, 500 MiB entpackt, 20.000 Einträge; keine Pfadtraversierung oder Symlinks. Dateien und Caches des Dev-Servers gehören nur zu dieser Session und werden beim Stoppen/Freigeben entfernt. native_changed zeigt Änderungen an nativen Dateien, Projektkonfiguration oder Abhängigkeiten an; Fast Refresh ersetzt deren erforderlichen APK-Neubau nicht. Paketänderungen können den Dev-Server neu installieren/starten lassen. native_changed bleibt nach einer solchen Änderung bis zur Neukonfiguration des Dev-Servers gesetzt, auch wenn spätere Änderungen nur JavaScript betreffen. Wiederholtes Anlegen eines aktiven Servers liefert HTTP 409.
Ein Neustart des Dev-Server-Kontrolldienstes beendet laufende Dev-Server. Sie werden derzeit nicht automatisch mit ihrem Quellstand wiederhergestellt. Prüfe danach den Status, stoppe den alten Dev-Server ausdrücklich, warte auf stopped und starte sim dev erneut. Dabei wird der Quellstand erneut hochgeladen; die gespeicherten Android-App-Daten sind davon getrennt.
Konfiguration, Source-Upload, Stoppen und /open verändern den Geräte-/Quellzustand und liefern während eines laufenden Tests HTTP 409. Zuerst den Job übernehmen (takeover) oder stoppen; die CLI wartet bei diesem Konflikt mit ihrer Synchronisierung. Job-Erstellung und resume liefern ebenfalls HTTP 409, wenn ein konfigurierter Dev-Server noch synchronisiert, startet oder fehlerhaft ist. Erst nach ready:true erneut aufrufen. Für framework:custom gilt als Bereitschaftsprüfung: Der Server muss im Container auf 0.0.0.0:8081 lauschen und GET /status HTTP 2xx liefern. Der Antwortinhalt wird nicht ausgewertet.
Gerätedateien, Zwischenablage und Live-Logs
PUT /v1/sessions/{sid}/files?path=Pictures%2Fproduct.png
Content-Type: application/octet-stream
<Datei, maximal 50 MiB>
GET /v1/sessions/{sid}/files?path=Pictures%2Fproduct.png
GET /v1/sessions/{sid}/files/list?path=Pictures
PUT /v1/sessions/{sid}/clipboard
{"text":"Text für die App"}
GET /v1/sessions/{sid}/clipboard
GET /v1/sessions/{sid}/logcat?package=com.example.myapp&limit=200&after=CURSOR
Dateipfade müssen in Download, Pictures, DCIM oder Movies liegen; Unterordner sind erlaubt. Upload liefert path, bytes, mime und media_scan. Download liefert Bytes, Liste liefert files mit Pfad, Name, Typ und gegebenenfalls Größe sowie truncated. Das ist kein Zugriff auf private Verzeichnisse anderer Apps oder Kunden.
Zwischenablage GET/PUT liefert {"text":"…"}; eine leere Zeichenkette leert sie. Grenze: 16.384 Zeichen / 65.536 UTF-8-Bytes. Logcat liefert lines, next_cursor, has_more, truncated und gegebenenfalls pid. limit ist 1–1000, Standard 200. Ohne Cursor werden die letzten Zeilen gelesen. Einen Cursor ausschließlich für dieselbe Session und denselben Paketfilter weiterverwenden; den Puffer löscht dieser Aufruf nicht. Weitere Zustandsfelder sind process_running, current_pid, process_restarted, gap_detected und coverage (tail, incremental, process_unavailable). Androids Ringpuffer kann überlaufen; die Antwort und der ADB-Lesevorgang sind begrenzt. truncated oder gap_detected dürfen nicht als vollständige forensische Aufzeichnung gewertet werden.
App-Updates gezielt anfordern
POST /v1/sessions/{sid}/updates
{"package":"com.example.myapp","channel":"preview","action":"reload",
"provider_uri":"content://com.example.myapp.updates",
"revision_probe":{"uri":"content://com.example.myapp.revision"}}
action ist check (Standard) oder reload. Genau einer der transportspezifischen Werte ist erforderlich: provider_uri oder deep_link. Der Content-Provider muss die Methode sim_update unterstützen; ihr Argument ist ein JSON-Objekt mit channel und action. Ein Deep Link muss den gewünschten Vorgang appseitig unterstützen; der Dienst erfindet keine universelle Update-Route. Der gewünschte Kanal umfasst 1–100 Zeichen.
Antwort: package, requested_channel, action, transport, before, after, channel_verified und update_changed. Ein erfolgreich zugestellter Aufruf beweist noch keinen geladenen OTA-Stand. Verwende einen Revisions-Provider und prüfe die tatsächlichen Werte; ein Download kann nach dem Aufruf noch laufen. Die APK-Installation bleibt ein separater Vorgang und verwendet datenerhaltenden Ersatz, sofern Paketname und Signatur passen.
Historie über Jobs hinweg und Quarantäne
GET /v1/apps/{slug}/flakes?environment=main&window=20
GET /v1/apps/{slug}/flakes/{flow_key}?environment=main&window=20
PATCH /v1/apps/{slug}/flakes/{flow_key}/quarantine?environment=main
{"quarantined":true,"reason":"Untersuchung zu #673","expires_at":null}
environment ist standardmäßig main; window liegt bei 1–200, Standard 20. Das Fenster zählt abgeschlossene Jobs pro Ablauf, nicht einzelne Wiederholungen. Optional: kind (maestro/model), model (gespeicherte Kennung, Modus oder Alias robot/qwen/astra/opus), since/until als nichtnegative Unix-Sekunden und revision. Zeitfilter sind einschließlich und beziehen sich auf das Jobende, ersatzweise den Start. Filter werden vor der Fensterauswahl angewendet. Die Historie ist auf den eigenen Account, die App und die Umgebung beschränkt.
Die Liste liefert workspace, environment, window, filters und flows. Ein Flow enthält flow_key, kind, identity, metrics, history, latest, quarantine, gate, contexts, context_mixed und context_warning. Der Detailendpunkt liefert denselben einzelnen Flow mit Kontextfeldern. history ist neueste zuerst und enthält Job-/Session-ID, result_url, einzelne attempts, outcome_counts, raw_job_outcome, expected_attempts, incomplete und Build-/Quell-/Gerätemetadaten. Fehlende angeforderte Wiederholungen sind ausgeschlossene Einträge mit not_executed:true; sie sind keine tatsächlich ausgeführten Tests.
Die stabile Maestro-Identität ist der YAML-Einstiegspfad innerhalb des ZIPs. Bundle-ID und Bundle-Hash verändern den Schlüssel nicht; ein umbenannter Einstiegspfad erzeugt eine neue Identität. Modelltests benötigen test_key im Job-POST: ^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,199}$. Es wird kein Schlüssel aus wechselnden Prompts erraten. Bei Maestro bleibt ein gegebenenfalls übergebenes test_key nur Metadatum. flow_key ist ein 64-stelliger kleingeschriebener SHA-256-Schlüssel, abgeleitet aus Art und Identität; verwende den Wert aus der Liste.
Beispiel: vier reine Ergebnisse Grün–Rot–Rot–Grün ergeben 50 % Fehlerquote, keine gemischte Serie und zwei Wechsel in drei Vergleichspaaren. Vier rote Ergebnisse ergeben 100 % Fehlerquote, aber is_flaky:false. Ein bestandener Versuch neben einem Infrastrukturfehler ist kein vollständig bestätigter grüner Lauf; die aktuelle Überwachungsentscheidung bleibt ohne Ausnahme unknown.
revision filtert exakt die kanonische Revision: zuerst den abschließend von der App gemeldeten bundle_hash, update_id oder revision; ersatzweise dev_server.source_sha256, source.commit, source.source_sha256 oder archive_sha256. revision_source nennt die Herkunft. Ohne App-Nachweis beweist ein Quell-/Archivhash nicht den tatsächlich geladenen OTA-Stand; unbekannte Versionen werden nicht als identischer Code gewertet. runtime_revision, revision_observations und die Revisionswerte einzelner Versuche bleiben zur Prüfung erhalten. Build-, Bundle-, Modell-, Geräte- und Quellwechsel sowie runtime_revisions, update_channels und runtime_versions sind in contexts sichtbar; context_mixed warnt vor gemischten Bedingungen. Beobachtete Variation kann eine absichtliche Änderung zwischen Versionen sein und beweist keine Zufälligkeit.
Quarantäne-POST gibt es nicht: Verwende PATCH mit quarantined, einer beim Aktivieren nichtleeren reason (maximal 2000 Zeichen) und optional expires_at als künftigem Unix-Zeitpunkt oder null. quarantined:false hebt sie auf und entfernt die Ablaufzeit. Die Antwort zeigt den aktualisierten Flow; quarantine.history hält manuelle Änderungen mit Zeitpunkt/Bearbeiter fest. quarantine.quarantined berücksichtigt ein bereits abgelaufenes Datum, configured zeigt die gespeicherte Konfiguration.
Keine Tests werden übersprungen und keine Rohurteile überschrieben. gate zeigt die aktuelle Entscheidung für den jüngsten beobachteten Lauf: passing, failing, unknown oder bei aktiver manueller Quarantäne non_blocking. Schon ein eindeutiger App-Fehler ist failing, auch wenn die Stichprobe noch klein ist. Diese Entscheidung ist eine separate Überwachungsregel. Nur ein Aufrufer, der ausdrücklich Quarantäne-Ausnahmen zulässt, darf non_blocking als nicht blockierend behandeln. Die normale Job-Abnahme, historische Ergebnisse und die weitere Testausführung ändern sich dadurch nicht.
Named snapshots and reusable model tests (CLI 0.9.0, MCP 0.7.0)
All routes require the caller's account/API key. Snapshots and test definitions are scoped to an owned app. Snapshots contain local Android/app state only; remote backend changes are never rolled back.
Snapshot IDs are n_ plus 32 lowercase hex digits. Names are nonblank, at most 100 characters, and not unique. Descriptor fields include id, name, workspace, environment, created, status, bytes, saved, error, and optionally session_id. Poll status creating / resuming until ready or error. Active checkpoints reject active jobs; Android is unavailable during the consistent cold backup, which can take minutes.
Session creation adds snapshot_id and persistence: "save" | "discard" (default save). Restore only targets a new/empty environment; existing saved data is not overwritten. Creating an environment can use from_snapshot instead of an explicit baseline. DELETE /v1/sessions/{sid}?disposition=save|discard overrides the session policy for release; omitting it uses that policy. Discard keeps the previous saved environment and drops current local changes. Named snapshots are immutable independent checkpoints. Restore itself needs no build.
Create a saved test with {id,name,task,model,criteria,package?,variables,options}. id matches [A-Za-z0-9_-]{1,80}, name has 1–100 characters, task has 1–10000. model is robot (default), qwen, astra, or opus. criteria uses the normal criterion schema. variables is a list of {name,secret:true}; names match [A-Za-z][A-Za-z0-9_]{0,63}. Declare variables used as {{name}} in the task or criteria. There are no stored default variable values. Bindings belong to a run, are supplied to the inference provider as private context, and must not be embedded as literal secrets in the saved task.
Definition options and per-run overrides accept repeat_count, reset_between, recovery_after, capture_video, revision_probe, webhook_id, store_artifacts, artifact_retention_days, needs_input_timeout_seconds, external_id, and tags. They do not accept task/model/criteria/package, test_key, kind, or Maestro flow IDs. Criteria and package belong to the definition's top level. PATCH accepts partial definition fields except id, plus optional expected_version; updates increment version, invalidate plan, and increment plan_revision. Stale versions return 409. Public detail includes version, plan_revision, plan (or null), and optional last_run. A plan includes steps, learned_at, and source_job_id.
{
"session_id": "SESSION_ID",
"mode": "auto",
"bindings": {"email": "test@example.invalid", "password": "TEST_ACCOUNT_VALUE"},
"options": {"store_artifacts": false},
"request_id": "pipeline-login-0001"
}
auto reuses an available compatible plan or learns, learn uses the model, replay requires an existing plan (otherwise 409). Pointer locates targets on current screenshots, UI guards verify expected states, and the model resumes when replay cannot safely continue. Final criteria must still be verified; an AI reviewer evaluates task fulfillment and efficiency on first learning and after changed/repaired paths. Unchanged replay of an approved plan has no additional optimization review; final acceptance criteria remain mandatory. Rejected/unavailable review changes a claimed pass to inconclusive and prevents plan promotion; reviewer time and tokens count toward job usage. No numeric Pointer confidence is promised. Only verified successful and safely parameterized traces can become a learned plan; a passed test may still have no reusable plan. Do not assume replay always avoids model calls.
The response is an ordinary job with saved_test metadata (id, mode, strategy: learning/replay/fallback, replayed_steps, learned_steps, fallback_reason, learning_unavailable_reason, plan_saved, plan_revision, promotion_reason, review) and stable test_key: "e2e:<id>"; all existing result, live, artifacts, clarification and caller-takeover routes apply. Delete returns 409 while the definition has an active invocation. Job evidence retention concerns media/artifact files; definitions and learned plans are separately managed through test CRUD.
MCP 0.7.0 adds android_snapshots, android_create_snapshot, android_delete_snapshot, android_saved_tests, android_save_test, android_delete_saved_test, and android_run_saved_test. android_start_session accepts snapshot/persistence, and android_release_session accepts disposition. android_save_test takes a definition object OR explicit JSON file; test_id selects PATCH instead of POST. android_run_saved_test takes bindings OR a private bindings_file. There are 51 MCP tools; saved invocations return immediately and can be observed through android_watch and android_test_result.
First learning and changed/repaired paths receive AI review; unchanged approved replay does not receive an extra optimization review. A repaired, successful and reviewed path automatically updates the next plan. Definition detail exposes plan_history with previous plan versions, source jobs and reviews. Proposed unnecessary steps are recorded; an unvalidated shorter route is never silently promoted. Explicit cancellation stops pending model inference; disconnecting the observer does not cancel a job.
POST /v1/reservations and MCP android_reserve accept snapshot_id and persistence; fresh cannot be combined with a snapshot. An active checkpoint excludes Metro source/dependencies; running remote dev servers remain and regain their Android reverse connection.
Unchanged replay reports review.status: reused; visual acceptance criteria may still require model verification. Reviewer-proposed closed navigation detours can become a separate optimization_candidate. The next run validates the shortened path with guards, criteria and review before promotion.
Review model and optimization lifecycle
On first learning and repaired/optimized paths, Robot uses Qwen as its intent/efficiency reviewer. Qwen, Astra and Opus use their own selected model. Unchanged approved replay has no extra optimization review. Review duration, tokens and estimated cost are attributed to the actual review model; a Robot job can include Qwen usage.
An optimization_candidate not verified in its test run is retired. The previous approved path remains, and public definition optimization_history records the attempt and result. Learned typed text requires declared bindings, except literal test text explicitly present in the public task or an acceptance criterion and entered into a non-password field. Password fields and other typed values require bindings.
Ein Werkzeug für deinen Agent.
Über MCP kann dein Coding-Agent Sessions starten, APKs installieren, Testaufträge delegieren und Screenshots direkt als Bild erhalten.
Connector herunterladen
Der Connector ist ein eigenständiges Python-Skript für Python 3.10 oder neuer. Er spricht MCP über stdio und nutzt im Hintergrund dieselbe HTTP API wie die CLI.
mkdir -p "$HOME/.local/share/sim"
curl -fSL https://sim.davidhe.de/v1/connector \
-o "$HOME/.local/share/sim/mcp.py"
Für ein Connector-Update wiederhole den Download und starte den MCP-Prozess in deinem Agent-Client neu. sim update aktualisiert nur die CLI.
Erstelle einen API-Token im Account. Stelle ihn dem MCP-Prozess über SIM_API_KEY bereit. Nutze die Geheimnisverwaltung deines Agent-Clients, wenn sie verfügbar ist.
Im Agent-Client eintragen
Für Clients mit einer mcpServers-Konfiguration. Ersetze den Skriptpfad durch einen absoluten Pfad auf deinem Rechner. Der API-Token wird aus der geschützten Prozessumgebung übernommen.
{
"mcpServers": {
"sim": {
"command": "python3",
"args": ["/absoluter/pfad/zu/mcp.py"],
"env": {
"SIM_URL": "https://sim.davidhe.de"
}
}
}
}
Wie Umgebungsvariablen an MCP-Prozesse weitergegeben werden, hängt vom Client ab. Falls dein Client sie nicht übernimmt, hinterlege SIM_API_KEY in seiner lokalen, privaten MCP-Konfiguration. Committe diese Konfiguration mit Token nicht ins Projekt.
Ein Auftrag an deinen Coding-Agent
Nutze sim, um meine Android-App zu testen.
Starte die App (workspace) "meine-app" in der Umgebung (environment) "checkout-agent".
Warte, bis das Gerät bereit ist, und installiere ./app.apk.
Prüfe, ob die Suche nach "rotes T-Shirt" passende Ergebnisse zeigt.
Gib mir das Ergebnis und einen Screenshot als Beleg zurück.
Stoppe anschließend die Session und behalte die App-Daten.
Der MCP-Connector liest nur explizit ausgewählte APKs und Kontextdateien. Er baut dein Projekt nicht selbst. Für Remote-Builds kann dein Agent zuerst sim up über die CLI verwenden oder die Build-API aufrufen.
Kontext gezielt mitgeben
Beschreibe das Ziel und die sichtbare Erfolgserwartung. Relevante Navigationsdateien, Routen oder UI-Texte können dem Testmodell helfen. Übergib nur ausgewählte Dateien über source_paths; ein vollständiges Repository ist für einen Testauftrag meist unnötig.
Guter Auftrag: „Öffne Entdecken, suche nach einem roten T-Shirt und prüfe, ob der Partner-Shop geöffnet wird.“ Falls die App vorher eingerichtet werden muss, gib den vorgesehenen Testablauf als Kontext mit.
Autonome Pipeline und Übernahme
Connector 0.7.0 enthält Briefing, Kriterien, Belege, Rückfragen, Geräteübernahme, Maestro, Serien, Revisionen, Webhooks und Reservierungen. Lade den Connector erneut herunter und starte seinen Prozess im Agent-Client neu. sim update aktualisiert nur die CLI.
- Mit
android_briefing die App erklären. android_test mit Kriterien oder android_maestro mit Flow-ID und repeat_count starten. - Bei
needs_input die Frage aus android_test_result mit android_answer beantworten. - Bei Bedarf
android_takeover, android_observe, android_actions und android_resume verwenden. Die ursprüngliche Aufgabe bleibt erhalten. - Ergebnis, Kriterien und Wiederholungen prüfen; mit
android_artifacts oder android_screenshot Belege abrufen. - Session freigeben.
android_webhooks kann über Abschluss und Rückfragen benachrichtigen.
Alle Werkzeuge verwenden dieselben IDs wie die API und CLI. Vollständiger Vertrag mit Beispielen und Fehlerbehandlung →
Live prüfen, suchen und Belege verwalten
Connector 0.7.0 ergänzt android_device_profiles, android_limits, android_jobs, android_watch, android_artifact_retention, android_delete_artifacts, android_divergence und android_compare. Neu herunterladen und den Connector-Prozess neu starten.
android_start_session mit device_profile:"compact" oder display:{width:1080,height:2400,density:420} und locale:"en-US". Später ändert android_configure dieselben Einstellungen.android_test oder android_maestro mit external_id, tags, artifact_retention_days, store_artifacts und needs_input_timeout_seconds starten. Rückfragen warten standardmäßig 900 Sekunden, dann ist das Ergebnis inconclusive; null deaktiviert diese Wartefrist.android_watch mit Session- und Job-ID liefert neue Ereignisse und standardmäßig den aktuellen Screenshot direkt als Bild. Mit dem gelieferten cursor als after wieder aufrufen, solange terminal:false oder has_more:true. include_screenshot:false liefert nur Metadaten. Zuschauen übernimmt das Gerät nicht und verlängert keine Leihfrist.android_jobs findet alle eigenen Läufe beispielsweise mit external_id:"#673" oder tag:"branch:fix/dialog", auch nach Freigabe der Geräte.android_divergence sucht die erste sichtbare Abweichung zwischen grünen und roten Wiederholungen. android_compare prüft einen normalisierten region-Bereich gegen einen bestandenen Vergleichsstand. Beide benötigen gespeicherte Bilder abgeschlossener Jobs.android_artifact_retention pinnt mit pinned:true oder setzt die Frist, android_delete_artifacts löscht Dateien eines abgeschlossenen Jobs. Die Standardfrist ist 30 Tage ab Jobende. Jobtexte und Kennzahlen bleiben gespeichert; store_artifacts:false unterbindet die persistenten Bildschirm-/Logdateien, nicht sämtliche Jobmetadaten.
Live- und Suchvertrag · Aufbewahrung und Datenschutzgrenzen · Bildvergleich · Rate-Limits
Remote-Entwicklung und Gerätewerkzeuge
Connector 0.7.0 bietet android_dev_server mit operation:start|status|open|stop, android_dev_sync für ausdrücklich ausgewählte Quell-ZIPs, android_files, android_clipboard, android_logcat und android_updates. Für automatisches Packen und Dateibeobachtung im Projektordner verwendet ein Coding-Agent am einfachsten sim dev.
Dev-Ablauf: kompatible Development-APK installieren, Server mit Framework und gegebenenfalls Scheme konfigurieren, erstes ZIP mit full:true hochladen, bis ready:true warten und mit operation:open öffnen. Weitere ZIPs enthalten nur Änderungen und das optionale Löschmanifest; bei full:false ist base_revision erforderlich. Es wird niemals ein lokaler Metro-Prozess gestartet. android_dev_sync lädt das gewählte ZIP unverändert hoch; Geheimnisse vor dem Erstellen ausschließen.
android_files verwendet operation:list|upload|download, path, bei Upload local_path und bei Download output. android_clipboard liest ohne text oder setzt den übergebenen Text. android_logcat übernimmt next_cursor als after und optional Paketfilter/Zeilenlimit. android_updates verlangt einen appseitig unterstützten Transport und liefert beobachtete Revisionswerte statt eines ungeprüften Updateversprechens.
CLI-Workflow · Remote-Dev-Vertrag · Dateien, Zwischenablage und Logs · OTA-Vertrag
Ablaufhistorie und manuelle Quarantäne
Connector 0.7.0 ergänzt android_flakes und android_quarantine. Modellaufträge erhalten mit android_test einen ausdrücklich gewählten test_key. Maestro wird unabhängig von ZIP-Versionen nach Einstiegspfad gruppiert.
android_flakes benötigt workspace, optional environment (Standard main), window (Standard 20, maximal 200), flow_key für Details sowie kind, model, since, until und revision. Zeitwerte sind Unix-Sekunden. Der Aufruf liest nur Historie und startet kein Gerät.
android_quarantine benötigt App, Flow-Key und quarantined:true|false. Beim Aktivieren zusätzlich eine nichtleere reason; expires_at ist ein zukünftiger Unix-Zeitpunkt oder null. Quarantäne wirkt nur in der gewählten App-Umgebung, verändert keine Job-Ergebnisse und überspringt keine Ausführung. Ein Agent darf die aktuelle Markierung nur für eine ausdrücklich gewählte Überwachungsregel verwenden, nicht als stillschweigende Erfolgsmeldung.
Prüfe Fehlerquote, gemischte Wiederholungen und Wechsel zwischen Jobs getrennt. Infrastruktur-/Navigationsfehler sind keine App-Fehler; gemischte Revisionen oder Geräte können wechselnde Ergebnisse erklären. Exakter Vertrag, Kennzahlen und Grenzen →
Snapshots und wiederverwendbare Tests
Connector 0.7.0 enthält 51 Werkzeuge. Nutze android_snapshots zum Auflisten und Prüfen, android_create_snapshot zum Sichern und android_delete_snapshot zum Löschen. android_start_session akzeptiert snapshot_id für eine neue/leere Umgebung sowie persistence: discard; android_release_session kann mit disposition überschreiben. Aktive Checkpoints pausieren Android bis zur konsistenten Sicherung und setzen dieselbe Session fort. Remote-Backends werden nie zurückgesetzt.
android_saved_tests liest Definitionen, android_save_test erstellt sie oder ändert mit test_id eine Definition. android_delete_saved_test löscht sie. android_run_saved_test startet mit mode: auto|learn|replay, session_id und bindings oder privater bindings_file einen gewöhnlichen Job. Es gibt keine gespeicherten Geheimnis-Defaults. Der Agent beobachtet über android_watch, liest über android_test_result und kann wie bisher übernehmen.
Replay verlangt einen Plan, prüft Pointer-Ziele und UI-Zustände und fällt bei Abweichungen auf das Modell zurück. Ein grünes Ergebnis erfordert überprüfte Kriterien. Erstlernen sowie geänderte oder reparierte Wege erhalten zusätzlich eine KI-Prüfung von Zielerfüllung und Effizienz; unveränderte geprüfte Wege brauchen keine erneute Optimierungsprüfung. Eine erforderliche, aber abgelehnte oder ausgefallene Prüfung ergibt inconclusive statt passed. Die Definition identifiziert Läufe im Monitoring als e2e:<id>. Vollständiger Vertrag und Grenzen.
android_saved_tests mit test_id zeigt auch plan_history mit früheren Versionen, Quell-Jobs und Reviews. Reparierte erfolgreiche und geprüfte Wege werden für spätere Läufe übernommen. Vorschläge zu unnötigen Schritten bleiben nachvollziehbar, ungeprüfte Kürzungen werden nicht übernommen. android_stop_test beendet laufende Modellinferenz.
Robot erhält bei Erstlernen und reparierten/optimierten Wegen eine Qwen-Prüfung; Qwen, Astra und Opus prüfen mit ihrem jeweils gewählten Modell. Unverändertes Replay benötigt keine zusätzliche Optimierungsprüfung. Verbrauch und Kostenschätzung zählen das tatsächliche Review-Modell. android_saved_tests zeigt in optimization_history auch verworfene Optimierungsversuche; ein nicht bestätigter Kandidat wird entfernt und der bisherige geprüfte Weg bleibt.
Wörtlicher Testtext aus öffentlichem Auftrag oder Kriterium darf in einem Nicht-Passwortfeld im Plan stehen. Passwortwerte und sonstige Eingaben benötigen deklarierte Bindings.