Highlights
✨ remote start-tunnel and remote browse go native on macOS — still no root
v11.0.0 made the native remoted piggyback the default for commands that establish their own RSD tunnel. It now covers the two commands that still had no rootless option on macOS, where --native is the default:
# Publishes Apple's existing kernel-routable tunnel — no sudo. Other processes can use the printed --rsd
pymobiledevice3 remote start-tunnel
# Lists what remotepairingd reports, instead of the bonjour browse that needs root to suspend remoted
pymobiledevice3 remote browsePassing a classic-tunnel-only option (-t wifi, --secrets, --protocol, --max-idle-timeout) or --no-native routes to the classic root tunnel and logs why, so existing workflows keep working. Those options are now detected by an explicit sentinel rather than by comparing against their default, which fixes --protocol quic being silently ignored on Python < 3.13 (and -p tcp on 3.13+), where TunnelProtocol.DEFAULT is version-dependent.
The native RSD handshake is also hardened: right after the tunnel comes up the device may reset the first RSD connection while remoted transparently redials onto a new port. That is now retried with a fresh pcblist scan instead of failing on the first RST_STREAM.
✨ Device auxiliary metadata (deviceKVSData) over RSD
The binary-plist key-value store the pairing layer advertises is now exposed on RemoteServiceDiscoveryService.auxiliary_metadata, with get_auxiliary_metadata(domain) and a typed is_remote_web_inspector_enabled(). Among other things it answers whether Safari/WebKit remote inspection is enabled — without opening a single service:
pymobiledevice3 remote auxiliary-metadatarsd.is_remote_web_inspector_enabled() # True / False, or None when the domain wasn't advertisedThis metadata is not part of RSD peer_info — it rides the RemotePairing handshake, so availability depends on the transport. It is reliably populated on the macOS native transport (remotepairingd's merged, persisted KVS), partial over tunneld/RemotePairing-over-bonjour, and empty on the userspace no-root default, which establishes its tunnel without a pair-verify handshake. Documented per-transport in the network-stacks guide.
🐛 sysmon process monitor process no longer quits on a relaunch or a single missed sample
monitor process locked onto the identity of the process resolved from the first snapshot, and the first sample missing that identity ended the command. That truncated collection whenever an app under test was relaunched, and occasionally when a single sysmon sample transiently omitted a process that was very much alive.
--keep-monitoring never locks in an identity. Every snapshot re-applies the --filter expressions and resolves the match with --choose, so a snapshot with no match is skipped instead of ending the command, and a relaunched process is picked up on its next sample:
pymobiledevice3 developer dvt sysmon process monitor process \
--filter name=MyApp --choose last --keep-monitoringA fresh Monitoring pid=..., ppid=..., name=... line is emitted whenever the tracked instance changes. Without the flag, behavior is unchanged.
Reported in fine detail — with the regression bisected to the commit that introduced it — by @luka-vladika-happening-xyz (#1875). Thank you!
What's Changed
- 258cd82 remote: add --native to start-tunnel/browse and default to it on macOS (#1876) (@doronz88)
- 17c6486 remote: surface start-tunnel native->classic reroute, and fix stale "userspace default" docs (#1876) (@doronz88)
- a2c2d40 remote: detect classic-tunnel options by sentinel default, not value (#1876) (@doronz88)
- e5c9602 remote: expose device auxiliary metadata (deviceKVSData) over RSD (#1877) (@doronz88)
- f519470 sysmon: Add --keep-monitoring to survive relaunches and transient misses (#1878) (@doronz88)
Full Changelog: v11.0.0...v11.1.0