Dokumentation
Mobdev
Mobdev bringt deine iPhones, iOS-Simulatoren und Android-Geräte in einer Mac-App zusammen, für dich und deinen KI-Agenten. Es liest den iPhone-Bildschirm über USB und tippt und schreibt als Bluetooth-Tastatur und -Zeiger; Simulatoren und Android brauchen nur Xcode oder adb. Agenten nutzen es über MCP oder HTTP.
Installation
Du brauchst einen Mac mit Bluetooth LE und macOS 26 oder neuer, ein iPhone und ein USB-Datenkabel. Lade die App herunter, öffne das Disk-Image und ziehe Mobdev in den Ordner „Programme“. Sie ist von Apple signiert und notarisiert und aktualisiert sich selbst.
Erlaube Bluetooth und Kamera, wenn macOS fragt. macOS behandelt den iPhone-Bildschirm wie eine Kamera, deshalb fragt es nach dem Kamerazugriff. Selbst bauen kannst du die App mit Xcode 26 oder neuer:
git clone https://github.com/niklas-schmidt-dev/mobdev
cd mobdev/macos
scripts/build-app.sh
open build/Mobdev.appiPhone einrichten
- Schließe das iPhone an, entsperre es und tippe auf Vertrauen. Fragt der Mac, ob er das Zubehör erlauben soll, klicke auf „Erlauben“.
- Öffne auf dem iPhone Einstellungen › Bluetooth und tippe unter „Andere Geräte“ auf deinen Mac. iOS zeigt ihn unter dem Namen des Macs an. Fehlt er, warte einen Moment oder klicke in Mobdev auf Show on iPhone Again: Ein iPhone mit demselben Apple Account übersieht den Mac womöglich, bis Mobdev ihn erneut anbietet.
- Aktiviere Einstellungen › Bedienungshilfen › Tippen › AssistiveTouch. AssistiveTouch macht aus dem Zeiger Tippgesten. Deaktiviere auf derselben Seite Am Objekt einrasten und lass Berührungsgesten ausführen eingeschaltet, sonst wird jedes Wischen zum Tippen.
- Wähle in Mobdev das Tastaturlayout, das auf dem iPhone unter Einstellungen › Allgemein › Tastatur › Hardwaretastatur eingestellt ist.
- Stelle „Automatische Sperre“ auf „Nie“, solange Agenten arbeiten. Das iPhone muss entsperrt bleiben.
Agenten verbinden
Die App zeigt diese Konfigurationen mit den richtigen Pfaden unter „Connect“. Sie enthalten keine Geheimnisse.
Claude Code
claude mcp add --scope user mobdev -- /Applications/Mobdev.app/Contents/MacOS/Mobdev mcpCodex (~/.codex/config.toml)
[mcp_servers.mobdev]
command = "/Applications/Mobdev.app/Contents/MacOS/Mobdev"
args = ["mcp"]Claude Desktop, Cursor und andere
{
"mcpServers": {
"mobdev": {
"command": "/Applications/Mobdev.app/Contents/MacOS/Mobdev",
"args": ["mcp"]
}
}
}HTTP-Clients können http://127.0.0.1:4686/mcp mit dem Token aus „Settings › API“ in der App nutzen. Der Server spricht MCP 2026-07-28 und ältere Versionen bis zurück zu 2024-11-05.
Tools
Koordinaten sind Pixel des Bildes, das screenshot zurückgibt (lange Kante 1280 px). Aktionen liefern einen neuen Screenshot, außer du übergibst "screenshot": false. Bei mehr als einem Gerät wählst du mit device (eine ID oder ein Name aus list_devices) eines aus. Ohne diese Angabe nimmt Mobdev das einzige Gerät oder, wenn daneben Simulatoren oder Android-Geräte laufen, das angeschlossene iPhone.
| Tool | Argumente | Was es tut |
|---|---|---|
| list_devices | iPhones, Simulatoren und Android-Geräte: ID, Name, Modell, Systemversion, bereit | |
| status | Bereitschaft von Bildschirm und Eingabe, Größe des Screenshots | |
| screenshot | JPEG des Bildschirms | |
| tap | x, y | Auf einen Punkt des Screenshots tippen |
| long_press | x, y, seconds | Berühren und halten |
| swipe | from_x, from_y, to_x, to_y, duration | Ziehen, z. B. zum Scrollen |
| scroll | direction, amount, x, y | Mausrad |
| type_text | text, submit | Text in das fokussierte Feld eingeben (bis zu 1000 Zeichen pro Aufruf) |
| press_key | key, modifiers | z. B. space + cmd für Spotlight |
| home | Zum Home-Bildschirm wechseln | |
| open_app | name | Eine App über ihren Namen öffnen (auf dem iPhone per Spotlight) |
| read_screen | Gesamter sichtbarer Text mit Positionen (lokale Texterkennung) | |
| find_text | text | Wo eine Beschriftung steht |
| tap_text | text, index | Auf eine sichtbare Beschriftung tippen |
| wait_for_text | text, timeout, gone | Warten, bis ein Text erscheint oder verschwindet |
| ui_tree | contains, all | Elemente aus dem Accessibility-Baum (Simulatoren und Android) |
| tap_element | id, text, index, timeout | Auf ein Element per Identifier oder Label tippen |
| wait_for_element | id, text, timeout, gone | Warten, bis ein Element erscheint oder verschwindet |
| run_flow | path, steps | Einen Flow abspielen; stoppt beim ersten fehlgeschlagenen Schritt |
Simulatoren und Android
Gestartete iOS-Simulatoren sowie Android-Emulatoren und -Smartphones erscheinen neben deinen iPhones, in der App und in list_devices, und lassen sich mit denselben Tools steuern. Auf ihnen musst du nichts einrichten: kein Kabel, kein Bluetooth, kein Entwicklermodus.
- Der iOS-Simulator braucht Xcode. Mobdev liest den Bildschirm direkt aus dem Simulator und sendet Berührungen und Tastendrücke wie Simulator.app, daher muss kein Fenster offen bleiben. Installiere Builds für den Simulator (
Debug-iphonesimulator); Crash-Reports kommen vom Mac. - Android braucht adb aus dem Android SDK, zum Beispiel über Android Studio. Emulatoren und Smartphones mit USB-Debugging erscheinen, solange adb läuft. Installiert wird eine
.apk,logsfolgt logcat, undpress_keymitescapewirkt als Zurück-Taste. Text wird als ASCII eingegeben, undopen_appvergleicht mit Paketnamen: „Settings“ öffnet com.android.settings.
xcodebuild -scheme MyApp -destination 'generic/platform=iOS Simulator' \
-derivedDataPath build build
# install_app {"device": "iPhone 17", "path": "…/Debug-iphonesimulator/MyApp.app"}
# install_app {"device": "emulator-5554", "path": "…/app-debug.apk"}Auf beiden listet ui_tree die Elemente auf dem Bildschirm mit Rolle, Label und Accessibility Identifier auf, und tap_element und wait_for_element finden sie über Identifier oder Label: zuverlässiger als die Texterkennung, und sie finden auch Buttons, die nur ein Symbol zeigen. Ein iPhone hat ohne Test-Runner auf dem Gerät keinen solchen Baum, deshalb nutzen Agenten dort tap_text.
Wenn du nur iPhones willst, schalte sie in der App unter „Settings › General“ aus.
Bauen, starten und debuggen
Für Apps, die du selbst entwickelst, installiert Mobdev auch Builds, startet sie und liest ihre Ausgabe und Crash-Reports. Der Agent baut mit xcodebuild, installiert, steuert die App mit den Tools oben und liest die Logs. Diese Tools nutzen devicectl aus Xcode und brauchen deshalb Xcode auf dem Mac und den Entwicklermodus auf dem iPhone (Einstellungen › Datenschutz & Sicherheit › Entwicklermodus). Alles andere funktioniert auch ohne. Simulatoren und Android brauchen beides nicht.
| Tool | Argumente | Was es tut |
|---|---|---|
| list_apps | all | Zur Entwicklung installierte Apps oder alle Apps |
| install_app | path | Einen Build vom Mac installieren: .app/.ipa, Simulator-.app oder .apk |
| uninstall_app | bundle_id | Eine zur Entwicklung installierte App entfernen |
| launch_app | bundle_id, arguments, environment, restart | Eine App starten und ihre Ausgabe mitschneiden |
| stop_app | bundle_id | Eine laufende App beenden |
| open_url | url | Einen Deep Link, Universal Link oder eine Webseite öffnen |
| logs | bundle_id, after, lines, contains | Ausgabe von print, NSLog und os_log und wie die App beendet wurde |
| crash_reports | app, name, limit | Crash-Reports auflisten oder einen lesen: Exception, Grund, abgestürzter Thread |
xcodebuild -scheme MyApp -destination 'generic/platform=iOS' \
-derivedDataPath build -allowProvisioningUpdates build
# install_app {"path": "…/build/Build/Products/Debug-iphoneos/MyApp.app"}
# launch_app {"bundle_id": "com.example.MyApp"}
# logs {"bundle_id": "com.example.MyApp"}logs gibt einen Cursor zurück; übergib ihn als after, um nur neue Zeilen zu bekommen. Stürzt die App ab, meldet logs das, und crash_reports zeigt den Crash-Report. Pfade für install_app beziehen sich auf den Mac, auf dem Mobdev läuft, auch über ein Relay. Mobdev entfernt nie Apps aus dem App Store oder System-Apps.
Flows und CI
Ein Flow ist eine Liste von Tool-Aufrufen, gespeichert als JSON. Klicke in der Ansicht „Activity“ eines Geräts auf Record, dann zeichnet Mobdev alle Aktionen auf dem Gerät auf, deine und die eines Agenten; auf Simulatoren und Android werden Klicks auf benannte Elemente zu tap_element, sodass der Flow Layoutänderungen übersteht. Abspielen kannst du ihn mit Run Flow…, dem Tool run_flow oder ohne App mit Mobdev flow. Jeder Lauf stoppt beim ersten fehlgeschlagenen Schritt und nennt ihn.
{
"name": "Sign in",
"steps": [
{"launch_app": {"bundle_id": "com.example.MyApp", "restart": true}},
{"tap_element": {"id": "email"}},
{"type_text": {"text": "me@example.com", "submit": true}},
{"wait_for_element": {"text": "Welcome"}}
]
}Mobdev flow läuft auf gestarteten Simulatoren und Android-Geräten, für Skripte und CI. Es endet mit Exit-Code 0, wenn alle Schritte erfolgreich waren, und mit 1, wenn einer fehlgeschlagen ist; --artifacts sichert das Aktivitätsprotokoll, Crash-Reports und einen Screenshot des Fehlers. Nutze in CI lieber tap_element als die Tools mit Texterkennung, denn die funktionieren auf den virtualisierten Macs von GitHub nicht.
/Applications/Mobdev.app/Contents/MacOS/Mobdev flow sign-in.json \
--device "$UDID" --artifacts flow-artifactsSkills
Skills geben deinem Agenten ganze Arbeitsabläufe auf Basis der Tools: den Kreislauf aus Bauen und Debuggen, Smoke-Tests, Onboarding-Audits und Konkurrenzanalysen. Sie funktionieren mit Claude Code, Codex, Cursor und anderen Agenten, die SKILL.md-Dateien lesen.
npx skills add niklas-schmidt-dev/mobdevOder kopiere einen Ordner aus skills/ in das Skills-Verzeichnis deines Agenten.
Fernzugriff
Damit du deine Geräte von einem anderen Computer aus erreichst, hält der Mac eine ausgehende WebSocket-Verbindung zu einem Relay. Auf dem Mac wird kein Port geöffnet, und das Relay speichert nichts.
- Melde dich im Dashboard an und erstelle ein Zugangstoken.
- Klicke auf „In Mobdev öffnen“ oder füge das Token in der App unter „Remote Access“ ein.
- Kopiere den Remote-Befehl aus der App und führe ihn auf dem anderen Computer aus:
claude mcp add --transport http mobdev-remote \
https://relay.mobdev.sh/h/<mac-name>/mcp \
--header "Authorization: Bearer mdc_…"Der Client-Schlüssel (mdc_…) wird aus einem Geheimnis abgeleitet, das deinen Mac nie verlässt. Wer ihn hat, kann deine Geräte steuern; „New Client Key“ in der App widerruft ihn. Widerrufst du das Zugangstoken im Dashboard, wird der Mac getrennt.
Limits des gehosteten Relays
Der Tarif Free verbindet 1 Mac und enthält 20.000 Anfragen und 10 aktive Stunden pro Monat. Der Tarif Pro (9 US-Dollar pro Monat zzgl. anfallender Steuern) verbindet 3 Macs und enthält 1.000.000 Anfragen und 300 aktive Stunden pro Monat. Aktive Zeit zählt, während ein Mac an einer Anfrage arbeitet; ein verbundener Mac, der wartet, kostet nichts. Das Dashboard zeigt, was du verbraucht hast. Mobdev auf dem Mac und ein selbst gehostetes Relay haben keine Limits.
Ist ein Limit erreicht, antwortet das Relay mit HTTP 429 und einem Retry-After-Header:
- Mehr als 50 Anfragen in 10 Sekunden mit einem Client-Schlüssel.
- Mehr als 4 Anfragen warten auf denselben Mac.
- Die Anfragen oder die aktive Zeit des Monats sind aufgebraucht. Retry-After nennt den Zeitpunkt, an dem sie sich erneuern.
Eigenes Relay betreiben
Das Relay im Repository spricht dasselbe Protokoll. Es ist ein einzelnes Go-Binary oder ein kleines Docker-Image:
cd relay
RELAY_HOST_ACCESS_TOKEN=choose-one go run .
# or
docker build -t mobdev-relay . && docker run -p 8080:8080 mobdev-relayBetreibe es hinter HTTPS und trage seine URL in der App ein. Ist RELAY_HOST_ACCESS_TOKEN gesetzt, dürfen sich nur Macs verbinden, die das Token kennen.
Sicherheit und Datenschutz
- Die lokale API lauscht nur auf 127.0.0.1, verlangt ein Bearer-Token und lehnt Anfragen aus dem Browser ab.
- Die Texterkennung läuft auf dem Mac. Kein Bildschirminhalt verlässt ihn, außer dein Agent schickt ihn an sein Modell.
- Das gehostete Relay speichert deine E-Mail-Adresse, gehashte Zugangstokens, welche Macs verbunden sind und die iPhones, die sie melden. Anfragen und Screenshots laufen nur durch den Arbeitsspeicher. Mehr dazu unter Datenschutz.
- Agenten handeln auf deinem echten Smartphone mit deinen Konten. Lass bei allem, was Nachrichten sendet, bezahlt oder löscht, einen Menschen mitentscheiden.