| name | ios-device-toolkit |
| description | Use when interacting with USB-attached iOS devices via pymobiledevice3 — screenshots, syslog, crash reports, app install/launch/pull, file transfer, sysmon perf, TCP port forwarding, WebInspector/CDP, and device diagnostics. |
iOS Device Toolkit
Drive a physical iOS device over USB with pymobiledevice3. This skill covers the high-value workflows; deep reference per area is in references/.
- Capture, logs, crashes →
references/capture.md
- Apps, app sandbox files, AFC media, debugserver →
references/apps-files.md
- Device info, perf, springboard, webinspector, tunneling →
references/diagnostics-perf.md
Install
uv tool install pymobiledevice3
pipx install pymobiledevice3
pymobiledevice3 version
Prerequisites
- Physical iOS device attached via USB (or Wi-Fi-paired through usbmuxd).
- Developer Mode enabled on device (Settings → Privacy & Security → Developer Mode). Verify with
pymobiledevice3 mounter query-developer-mode-status.
- Trusted computer — accept "Trust This Computer" prompt on the device after first connect.
- iOS 17+ only: a long-running
tunneld daemon is required for any developer-mode service (screenshots, DVT instruments, debugserver, pcap-with-process, etc.). Start it once per boot:
sudo pymobiledevice3 remote tunneld
The CLI auto-retries developer commands through tunneld; you no longer need --tunnel "" on every call in 7.x, though it still works.
Device selection
For a single attached device, no flag is needed. For multiple, scope every call with one of:
--udid <UDID> — usbmux-discovered device
--tunnel <UDID> — tunneld-discovered device (developer services on iOS 17+)
PYMOBILEDEVICE3_UDID=<UDID> / PYMOBILEDEVICE3_TUNNEL=<UDID> env vars — set once, all subsequent invocations inherit
Discover UDIDs:
pymobiledevice3 usbmux list
xcrun devicectl list devices
pymobiledevice3 lockdown info | head
Caveat: --tunnel "" (empty string) prompts interactively. In non-interactive shells, pass the UDID directly.
Quick reference
pymobiledevice3 usbmux list
pymobiledevice3 lockdown info
pymobiledevice3 diagnostics battery
pymobiledevice3 mounter list
pymobiledevice3 developer dvt screenshot ~/Desktop/shot.png
pymobiledevice3 syslog live
pymobiledevice3 crash ls
pymobiledevice3 crash pull ~/ios-crashes
pymobiledevice3 pcap --out trace.pcap --process Safari
pymobiledevice3 apps list --user
pymobiledevice3 apps install ./MyApp.ipa
pymobiledevice3 apps uninstall com.example.MyApp
pymobiledevice3 developer dvt launch com.example.MyApp
pymobiledevice3 developer dvt process-id-for-bundle-id com.example.MyApp
pymobiledevice3 developer dvt kill <PID>
pymobiledevice3 apps pull com.example.MyApp Documents/log.txt ./log.txt
pymobiledevice3 apps push com.example.MyApp ./seed.json Documents/seed.json
pymobiledevice3 afc pull DCIM/100APPLE/IMG_0001.HEIC ./
pymobiledevice3 afc ls -r DCIM
pymobiledevice3 developer dvt sysmon system
pymobiledevice3 developer dvt sysmon process
pymobiledevice3 developer dvt proclist
pymobiledevice3 developer dvt energy <PID> [<PID>...]
pymobiledevice3 usbmux forward 8080 8080
pymobiledevice3 webinspector opened-tabs
pymobiledevice3 webinspector cdp
Common gotchas
- "InvalidServiceError" / "Failed to start service" on iOS 17+ → tunneld is not running. Start
sudo pymobiledevice3 remote tunneld and retry. Confirm with ps aux | grep tunneld.
- "DeveloperDiskImage not mounted" →
pymobiledevice3 mounter auto-mount.
- Deprecated screenshot API hangs on iOS 17+ → use the DVT variant:
developer dvt screenshot (not developer screenshot).
--tunnel "" hangs in scripts → empty string means interactive picker; pass the UDID explicitly.
- Permissions on Linux → usbmuxd typically needs to be running; on macOS it's built in.
- Pairing lost after iOS update →
pymobiledevice3 lockdown unpair && pymobiledevice3 lockdown pair.
Scripting tips
- Set
PYMOBILEDEVICE3_UDID (and PYMOBILEDEVICE3_TUNNEL for developer services) once at the top of a script to avoid repeating flags.
- For capture-and-open recipes (screenshot +
open, syslog tail + grep, etc.), wrap in a shell function rather than re-typing the full path each time.
- Most subcommands accept
--rsd HOST PORT as an alternative to --tunnel, useful when you already have an RSD address from a manual pymobiledevice3 remote start-tunnel.