Many of the nominally shared system pieces between Mac and iPhone (like Foundation) actually had many subtle compile-time differences.
> At WWDC, Apple announced that starting in the 27.x versions of iOS, macOS, etc., devs would be able to call Private Cloud Compute directly from Swift with no additional API configuration. Presently, the only way to get free cloud inference is by joining the App Store Small Business Program.
https://www.reddit.com/r/appledevelopers/comments/1vztibh/re...
I'm curious what are these checks
> In a support document about alternative app marketplaces in the EU, Apple explained that “device eligibility for alternative app marketplaces is determined using on-device processing with only an indicator of eligibility sent to Apple.” In practice, iOS users in the EU who want to install alternative marketplaces will need to set the country or region of their Apple ID to an eligible country or region. Moreover, they will also need to be physically located in supported EU countries.
> In the case iOS users in the EU leave eligible regions, Apple will offer a “grace period” until apps downloaded from alternative app stores can no longer be updated. “If you’re gone for too long, you’ll lose access to some features, including installing new alternative app marketplaces. Apps you installed from alternative app marketplaces will continue to function, but they can’t be updated by the marketplace you downloaded it from,” the company explained.
https://www.thurrott.com/apple/298862/apple-adds-some-condit...
You have to compile completely independently for it, and depending on your dependencies they may not compile for the simulator.
Additionally the simulator runs a really ancient and feature restricted version of Metal. That means you can’t test a lot of graphical things that the hardware actually supports.
I always figured that Apple never set up a true emulator (like what Android does), because they didn't want people exploring their OS with a debugger.
I am vaguely aware that some phone manufacturers silently remove certain NFC hardware (or disable some driver) in order to avoid paying Sony patent fees. Apple doesn't seem to do that, though.
They do not live in a VM and are certainly not emulated at an instruction set level. They are Mac apps.
Boot a virtual iPhone via Apple's Virtualization.framework using PCC research VM infrastructure.

Host:
Dependencies:
brew install python@3.13 aria2 wget gnu-tar openssl@3 ldid-procursus sshpass keystone cmake libusb ipsw zstd
brew install zqxwce/tap/vphone-cli
git clone --recurse-submodules https://github.com/Lakr233/vphone-cli.git
./scripts/setup_tools.sh # install deps, build toolchain submodules, create the Python venv
./scripts/build.sh # build + sign vphone-cli, bundle the .app, cross-compile vphoned
cd .build/vphone-cli.app/Contents/MacOS/
vphone-cli --help
One command creates a VM end-to-end (download → patch → DFU restore → CFW install → first boot):
vphone-cli vm create myphone -V jb # -V / --variant
vphone-cli vm launch myphone
vphone-cli vm create runs the whole pipeline; the individual steps below let you drive it manually or re-run one stage.
vphone-cli vm list # list VMs (--json for scripting)
vphone-cli vm info myphone # show one VM
vphone-cli vm new myphone # create an empty bundle (cpu/mem/disk options)
vphone-cli vm config myphone --cpu 8 --memory 8192
vphone-cli vm clone myphone myphone-2 # fast APFS clone, fresh device identity
vphone-cli vm export myphone --out myphone.tzst # zstd fast by default (--max = xz -9); --out may be a dir (auto-names <vm>.tzst/.txz); skips restore dir + staging files
vphone-cli vm import myphone.tzst --name restored
vphone-cli vm rename myphone iphone16
vphone-cli vm delete iphone16
vm create automates)vphone-cli vm new myphone # 1. empty bundle
vphone-cli fw prepare myphone --iphone-version 26.1 # 2. download + merge IPSWs
vphone-cli fw patch myphone --variant jb # 3. patch the boot chain
vphone-cli vm launch myphone --dfu & # 4. boot into DFU (background)
vphone-cli restore myphone --get-shsh # fetch SHSH
vphone-cli restore myphone # DFU restore
vphone-cli vm stop myphone # stop the DFU boot
vphone-cli cfw install myphone --variant jb # 5. install CFW (host-mount; asks for sudo)
vphone-cli vm launch myphone # 6. first boot
Update to a newer iOS by pointing fw prepare at an IPSW: --iphone-source /path/to.ipsw --cloudos-source /path/to.ipsw.
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.
ssh -p 22222 mobile@<vm-ip> (password alpine)ssh -p 22222 root@<vm-ip>vnc://<vm-ip>:5901Everything 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.
Option A — fully disable SIP, then disable AMFI via boot-arg (most permissive).
In Recovery (long-press power → Terminal):
csrutil disable
csrutil allow-research-guests enable
Then reboot into macOS and set the AMFI boot-arg (needs SIP fully off to take effect):
sudo nvram boot-args="amfi_get_out_of_my_way=1 -v" # reboot after
Option B — keep SIP on (debug-only relaxed), then allowlist the binary with amfidont (leaves AMFI enabled system-wide).
In Recovery:
csrutil enable --without debug
csrutil allow-research-guests enable
Then reboot into macOS and:
vphone-amfidont # .build/vphone-cli.app/Contents/Resources/vphone-amfidont for local builds
| 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 |
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.
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.
I would think that "Mac apps," means that they are, actually, a different OS (I actually already knew that, which was why I said what I said. The Intel thing was a spitball).
But one of the few joys geeks get, these days, is telling other geeks they are wrong, so I feel as if I’ve done my bit to make this a happier place.
its the least of their problems
And then there is additional discouragement and pressure in the form of sanction and trade deal threats for regulating American tech platforms.
What people don't realise is that local companies aren't just competing with each other, they're competing against the US military.
That really matters, sometimes.
But not the vast majority of the time.
(source: been coding iOS since pre-SDK iPhone OS 1.0)