Lakr233/vphone-cli
vphone-cli
Boot a virtual iPhone via Apple’s Virtualization.framework using PCC research VM infrastructure.
Prerequisites
Host:
- Apple Silicon
- macOS 15+ (Sequoia)
- Xcode + iOS SDK (cross-compiles the guest daemon)
- SIP/AMFI relaxation to allow private PV=3 entitlements with unsigned-binary
Dependencies:
|
|
Install
|
|
Build
|
|
Quick Start
One command creates a VM end-to-end (download β patch β DFU restore β CFW install β first boot):
|
|
Commands
vphone-cli vm create runs the whole pipeline; the individual steps below let you drive it manually or re-run one stage.
Manage
|
|
Build a VM manually (what vm create automates)
|
|
Update to a newer iOS by pointing fw prepare at an IPSW: --iphone-source /path/to.ipsw --cloudos-source /path/to.ipsw.
Firmware Variants
Five patch variants with increasing security bypass β pass one to --variant:
| Variant | Boot Chain | CFW | Notes |
|---|---|---|---|
less |
4 patches | 2 phases | Patchless β keeps iOS mitigations enabled |
regular |
42 patches | 10 phases | AMFI/SSV/Img4/TXM bypass |
dev |
53 patches | 12 phases | + TXM entitlement/debug bypass |
jb |
113 patches | 14 phases | + full jailbreak (Sileo, TrollStore auto-install on first boot) |
exp |
141 patches | 18 phases | JB superset + anti-VM-detection research patches |
See research/0_binary_patch_comparison.md for the per-component breakdown.
Running & Connecting
- SSH (jailbreak):
ssh -p 22222 mobile@<vm-ip>(passwordalpine) - SSH (regular/dev):
ssh -p 22222 root@<vm-ip> - VNC:
vnc://<vm-ip>:5901
Locations
Everything vphone-cli creates lives under ~/.vphone/ β kept outside the repo and the .app so the signed bundle stays portable. Redirect the whole tree with $VPHONE_ROOT:
| Path | Contents |
|---|---|
~/.vphone/ |
The per-user data root β override the entire location with $VPHONE_ROOT. |
~/.vphone/VMs/ |
VM bundles β one directory per VM. This is the library; override with $VPHONE_LIBRARY_ROOT. |
~/.vphone/ipsws/ |
Downloaded iPhone + cloudOS IPSWs, cached and reused across VMs. |
~/.vphone/tools/ |
Cached APFS seal-volume artifacts (apfs_sealvolume_<version>) fetched during fw prepare. |
~/.vphone/debs/ |
Cached .deb packages the jb/exp CFW install lays into the guest (Sileo, apt, β¦). |
~/.vphone/venv/ |
Auto-provisioned Python environment (see Python runtime; override with $VPHONE_VENV_DIR). |
Precedence: the per-item overrides ($VPHONE_LIBRARY_ROOT, $VPHONE_VENV_DIR) win over $VPHONE_ROOT, which wins over the ~/.vphone default. The ipsws/, tools/, and debs/ caches always sit directly under whichever root is active.
SIP/AMFI Relaxation
Option A β fully disable SIP, then disable AMFI via boot-arg (most permissive).
In Recovery (long-press power β Terminal):
|
|
Then reboot into macOS and set the AMFI boot-arg (needs SIP fully off to take effect):
|
|
Option B β keep SIP on (debug-only relaxed), then allowlist the binary with amfidont (leaves AMFI enabled system-wide).
In Recovery:
|
|
Then reboot into macOS and:
|
|
Tested Environments
| Host | iPhone | CloudOS |
|---|---|---|
| Mac16,11 27.0b2 | 17,3_18.6.2_22G100 |
26.1-23B85 |
| Mac16,8 26.5.1 | 17,3_26.0_23A341 |
26.1-23B85 |
| Mac16,8 26.5.1 | 17,3_26.0.1_23A355 |
26.1-23B85 |
| Mac16,12 26.3 | 17,3_26.1_23B85 |
26.1-23B85 |
| Mac16,12 26.3 | 17,3_26.3_23D127 |
26.1-23B85 |
| Mac16,12 26.3 | 17,3_26.3_23D127 |
26.3-23D128 |
| Mac16,12 26.3 | 17,3_26.3.1_23D8133 |
26.3-23D128 |
| Mac16,11 26.2 | 17,3_26.4_23E246 |
26.4-23E5207q |
| Mac16,11 26.2 | 17,3_26.5_23F77 |
26.4-23E5207q |
| Mac16,11 27.0b2 | 17,3_26.5.2_23F84 |
26.4-23E5207q |
| Mac16,6 26.4.1 | 17,3_26.6_23G71 |
26.4-23E5207q |
| Mac16,11 27.0b2 | 17,3_26.6.1_23G83 |
26.4-23E5207q |
| Mac16,11 27.0b2 | 17,3_27.0_24A5380h |
26.4-23E5207q |
| Mac16,6 26.4.1 | 17,3_27.0_24A5390f |
26.4-23E5207q |
| Mac16,6 26.6.1 | 17,3_27.0_24A5408d |
26.4-23E5207q |
| Mac16,11 27.0b2 | 17,3_27.0_24A5418b |
26.4-23E5207q |
| Mac16,11 27.0b2 | 17,3_27.0_24A5424a |
26.4-23E5207q |
FAQ
zsh: killed ./vphone-cli β AMFI/debug restrictions aren’t bypassed; see Prerequisites (amfi_get_out_of_my_way=1 or amfidont).
Virtualization is not available on this hardware β your Mac is itself a VM; PV=3 guest boot can’t nest. Use a non-nested macOS 15+ host.
Stuck on “Press home to continue” β connect via VNC and right-click (two-finger click) to simulate the home button.
System apps won’t install β during iOS setup, don’t pick Japan or the EU as your region (extra regulatory checks the VM can’t satisfy); pick e.g. United States.
App crashes on launch with EXC_GUARD / GUARD_TYPE_MACH_PORT β re-patch with vphone-cli fw patch <name> --variant <v> --force-exc-guard, then re-restore/install (#291). Always on for iOS 18 bases.
Install a .ipa/.tipa β use the running VM’s Install menu (drag-drop or file picker).
cfw install hangs re-signing a system binary (e.g. Campo), memory climbing unbounded β known bug in ldid-procursus up to 2.1.5-procursus7 (the current Homebrew stable): bytes(uint64_t) calls __builtin_clzll(0) with no zero-guard, which is undefined behavior, and on this build resolves to a 0-length that underflows an unsigned loop counter β ldid spins writing one byte at a time into a growing buffer instead of terminating. Triggered by any entitlements plist containing an integer value of exactly 0 (some real Apple system binaries have these). Fixed upstream but not yet in a tagged release; rebuild from source: brew install --HEAD ldid-procursus && brew link --overwrite ldid-procursus. Kill the hung ldid process first (sudo kill -9 <pid>) if you already hit it.
Automation
vphone-cli exposes a host control socket (<bundle>/vphone.sock) for programmatic control β screenshots, touch, swipes, hardware keys, clipboard β each action returning an inline screenshot for AI-driven E2E testing. See vphone-mcp for an MCP server wrapping it.