How to Automate iOS VM Creation with vphone-cli: Complete Orchestration Guide

vphone-cli automates the entire iOS virtual machine provisioning workflow through a single vm create command, orchestrated by VPhoneCreateOrchestrator to execute eight distinct stages from firmware preparation to first-boot verification without manual shell scripting.

The Lakr233/vphone-cli repository provides a native Swift implementation that replaces the historic scripts/setup_machine.sh approach. By invoking the vm create subcommand defined in VPhoneVMCreateCLI.swift, developers trigger a fully-typed pipeline that downloads IPSWs, patches firmware, and restores the system using the VPhoneCreateOrchestrator class.

The vphone-cli VM Creation Architecture

The automation layer centers on two primary components. The VPhoneVMCreateCommand struct parses command-line arguments—including variant selection (regular, dev, jb, exp, or less), disk sizing, and IPSW sources—and delegates execution to the VPhoneCreateOrchestrator. This orchestrator implements the complete workflow previously distributed across multiple bash scripts, now unified within sources/vphone-cli/VPhoneCreateOrchestrator.swift.

Eight-Stage Automation Pipeline

When you execute vphone-cli vm create, the orchestrator proceeds through the following sequential stages:

1. Pre-flight Validation

Before allocating resources, the orchestrator detects nested virtualization environments. The isNestedVMHost() method (located at lines 76–82 in VPhoneCreateOrchestrator.swift) checks if the host is itself a virtual machine, aborting immediately because PV=3 guests cannot run inside another VM. This prevents wasted compute cycles on incompatible infrastructure.

2. Bundle Creation

The orchestrator initializes the VM container using VPhoneBundleOps.NewBundleSpec. During this stage, the run() method (lines 72–79) creates the bundle directory structure with specified CPU, memory, and disk parameters, establishing the virtualized hardware profile that subsequent stages will populate.

3. Firmware Preparation

This stage downloads and merges the iPhone IPSW and cloudOS IPSW archives. The runFWPrepare() function (lines 10–12) invokes the bundled scripts/fw_prepare.sh helper, passing environment variables including IPHONE_SOURCE, CLOUDOS_SOURCE, and VPHONE_PYTHON to manage the Python interpreter path and IPSW URLs. The script caches the merged result in a seal-volume directory for subsequent patching operations.

4. Firmware Patching

With the base firmware cached, runFWPatch() (lines 33–36) executes the in-process FirmwarePipeline.patchAll method from FirmwarePatcher/FirmwarePipeline.swift. This pipeline applies variant-specific modifications (regular, dev, jb, exp, or less) to the seal-volume image, preparing the custom firmware without intermediate shell calls.

5. Restore Phase

The orchestrator launches the VM in DFU mode and initiates the restore sequence via runRestorePhase() (lines 58–78). This function fetches a signed SHSH blob through the pmd3 bridge, executes the restore-update process, and records the restored iOS and cloudOS version strings. It also monitors for post-restore panic markers to detect early boot failures before proceeding.

6. Custom Firmware Installation (Non-less Variants)

For all variants except less, runCFWInstall() (lines 84–92) mounts the host disk image and copies the patched firmware into Disk.img. This stage handles privilege escalation using makeSudoAskpassScript(), which generates a non-interactive authentication helper when the --sudo-password flag is provided, enabling automated installation in CI environments.

7. First-Boot Initialization

The runFirstBoot() method (lines 100–112) boots the patched VM and injects configuration commands defined in VPhoneBootPatterns.firstBootCommands. This sequence completes system setup inside the guest, with optional interactive pauses for manual verification if the --confirm flag is specified.

8. Boot Analysis and Cleanup

Finally, runBootAnalysis() (lines 118–126) launches a headless VM instance to verify that the bash prompt appears correctly, or detects panic states using regex patterns from VPhoneBootPatterns.swift. The orchestrator then optionally removes intermediate build artifacts via cleanup logic in run() (lines 31–34) to conserve disk space.

Practical Command-Line Usage

Basic Non-Interactive Creation

Create a regular variant VM named myVM with a 64 GB virtual disk:

vphone-cli vm create myVM \
  --variant regular \
  --iphone-source https://example.com/iPhone13,14.5.ipsw \
  --cloudos-source https://example.com/cloudOS13.7.ipsw \
  --disk-size 64

Debugging with Verbose Output

Enable internal trace logging using the -vvv flag:

vphone-cli -vvv vm create myVM \
  --variant jb \
  --iphone-source /path/to/iPhone13.5.ipsw \
  --cloudos-source /path/to/cloudOS13.3.ipsw

Patch-Less Variant (Requires Root)

The less variant skips CFW installation and must run with elevated privileges:

sudo vphone-cli vm create myVM \
  --variant less \
  --iphone-source /path/to/iPhone13.5.ipsw \
  --cloudos-source /path/to/cloudOS13.3.ipsw

Automated Sudo Authentication

Pass credentials non-interactively for CI pipelines:

vphone-cli vm create myVM \
  --variant dev \
  --iphone-source https://example.com/iPhone13.5.ipsw \
  --cloudos-source https://example.com/cloudOS13.3.ipsw \
  --sudo-password "$MY_SUDO_PWD"

Preserving Build Artifacts

Retain intermediate files for forensic analysis:

vphone-cli vm create myVM \
  --keep-artifacts \
  --variant exp

Core Implementation Files

Summary

  • Single-command automation via vphone-cli vm create eliminates manual shell scripting.
  • Native Swift orchestration through VPhoneCreateOrchestrator provides type-safe error handling and reproducibility.
  • Eight-stage pipeline covers validation, firmware preparation, patching, restoration, and verification.
  • Variant flexibility supports regular, dev, jb, exp, and less firmware configurations.
  • CI/CD compatibility via --sudo-password and non-interactive authentication hooks.

Frequently Asked Questions

What is the difference between the "less" variant and other variants?

The less variant skips the custom firmware installation stage entirely, requiring the user to manually manage the root filesystem, and must execute with sudo privileges. Other variants (regular, dev, jb, exp) proceed through the full pipeline including automatic CFW installation via runCFWInstall().

Can vphone-cli create VMs inside a virtual machine?

No. The isNestedVMHost() function explicitly detects when the host environment is itself a virtual machine and aborts the creation process because the virtualization architecture (PV=3) used for these iOS guests cannot operate within nested hypervisors.

How does the tool handle Python dependencies for firmware operations?

The orchestrator locates the bundled Python interpreter through VPhoneResources.swift, setting the VPHONE_PYTHON environment variable when invoking scripts/fw_prepare.sh. This ensures consistent script execution regardless of system Python configurations.

Where are downloaded IPSW files cached?

The VPhoneResources module manages dedicated cache directories for IPSW archives, seal-volume images, and DEB packages within the application support directory, preventing redundant downloads across multiple VM creation runs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →