What Is a VM Bundle in vphone-cli? The Directory Structure Explained

A VM bundle in vphone-cli is a self-contained directory that packages all configuration files, APFS disk images, and firmware blobs required to boot and run a virtual iPhone instance on macOS.

In the Lakr233/vphone-cli ecosystem, the VM bundle serves as the fundamental unit of storage and portability for virtual iOS devices. Each bundle represents a complete virtual machine state—from CPU allocation to filesystem contents—organized as a single directory that the Virtualization.framework consumes to emulate iPhone hardware.

Core Components of a VM Bundle

A VM bundle is simply a directory on disk containing several mandatory and optional items. According to the source code in sources/VPhoneCore/VPhoneBundle.swift, the directory name itself becomes the bundle name (e.g., my-iPhone-vm), while the contents define the virtual hardware.

Configuration and Manifest

Every bundle contains a config.plist file at its root. This property list stores a serialized VPhoneVirtualMachineManifest that describes the virtual hardware configuration, including CPU count, memory size in megabytes, network settings, and the filename of the disk image. The CLI loads this manifest via VPhoneVirtualMachineManifest.load when initializing the bundle object.

Disk Images and Firmware

The bundle houses the actual storage and boot components required by the guest OS:

  • Disk.img: A raw APFS disk image containing the iOS filesystem. The bundle exposes the image size through the VPhoneBundle.diskSizeBytes property.
  • SEPStorage and AVPBooter.vresearch1.bin: Firmware blobs required for Secure Enclave and virtual hardware emulation.
  • .vphoned.signed: The signed host-side daemon binary that communicates with the guest iOS over a vsock transport channel.

Snapshots and Resources

Additional files support state management and UI integration:

  • .snapshot files: APFS snapshots used by the export and import commands to preserve exact VM state across transfers.
  • Resource bundles: Optional application bundles (such as the bundled vphone-cli.app itself) and UI assets that can be staged into the VM environment.

The VPhoneBundle Data Model

The VPhoneBundle struct in sources/VPhoneCore/VPhoneBundle.swift provides the programmatic interface to these directories. It is a Sendable value type that encapsulates the bundle's location and configuration:

public struct VPhoneBundle: Sendable {
    public let url: URL                         // bundle directory
    public let manifest: VPhoneVirtualMachineManifest
    public var name: String { url.lastPathComponent }
    public var configURL: URL { url.appendingPathComponent("config.plist") }
}

This structure exposes the filesystem URL, the parsed hardware manifest, and computed properties for the bundle name and configuration file path.

Creating VM Bundles with VPhoneBundleOps

The VPhoneBundleOps API in sources/VPhoneCore/VPhoneBundleOps.swift provides factory methods for bundle lifecycle management. Creating a new VM requires specifying a NewBundleSpec with hardware parameters and firmware sources:

let spec = VPhoneBundleOps.NewBundleSpec(
    name: "my-iPhone-vm",
    romSource: VPhoneBundleOps.defaultROMSource(),
    sepromSource: VPhoneBundleOps.defaultSEPROMSource(),
    cpuCount: 8,
    memoryMB: 8192)
let bundle = try VPhoneBundleOps.create(spec, in: library)

This operation performs three critical steps: it creates the bundle directory, writes the default config.plist with the specified manifest, and copies the necessary ROM and SEP firmware files into the bundle structure.

Launching and Transferring Bundles

Once instantiated, a bundle becomes the input for the virtualization engine. The CLI boots instances using VPhoneVirtualMachine.start(with:) as implemented in sources/vphone-cli/VPhoneVMLaunchCLI.swift:

let bundle = try library.bundle(named: "my-iPhone-vm")
try VPhoneVirtualMachine.start(with: bundle)

The library validates the bundle's manifest integrity and delegates configuration to Apple's Virtualization.framework.

Export and Import Workflows

Bundles support serialization for backup and migration via sources/vphone-cli/VPhoneVMTransferCLI.swift. The export operation creates a compressed archive containing the entire bundle state:

let archive = try VPhoneBundleOps.export(
    bundleNamed: "my-iPhone-vm",
    to: URL(fileURLWithPath: "/tmp/my-iPhone-vm.tgz"),
    includeIPSW: false,
    in: library)

The import operation reconstructs the bundle from an archive into a new library location, preserving APFS snapshots and firmware integrity:

let imported = try VPhoneBundleOps.importArchive(
    from: archiveURL,
    name: "imported-vm",
    in: newLibrary)

Summary

  • A VM bundle is a directory-based container that encapsulates all files required to run a virtual iPhone, including configuration, disk images, and firmware.
  • The VPhoneBundle struct models the bundle's path and manifest, while VPhoneBundleOps handles creation, cloning, and destruction.
  • Key files include config.plist (hardware settings), Disk.img (APFS filesystem), SEP firmware blobs, and .vphoned.signed (host daemon).
  • Bundles support full lifecycle operations—create, launch, export, and import—enabling portable virtual device workflows across macOS systems.

Frequently Asked Questions

What file format does vphone-cli use for VM bundles?

vphone-cli uses a directory-based bundle format rather than a single file. The bundle is a standard filesystem directory containing a config.plist (Apple property list format), a raw Disk.img (APFS format), and binary firmware blobs. This structure allows the Virtualization.framework to memory-map disk images and access configuration directly without extraction overhead.

How do I move a VM bundle to another Mac?

Use the built-in export and import commands. Call VPhoneBundleOps.export(bundleNamed:to:includeIPSW:in:) to generate a compressed .tgz archive containing the bundle directory and its snapshots. Transfer this archive to the target Mac, then use VPhoneBundleOps.importArchive(from:name:in:) to reconstruct the bundle in the new library. This preserves the exact VM state, including APFS snapshots and hardware configuration.

Can I edit the VM configuration after creation?

Yes. Since the configuration is stored as config.plist inside the bundle directory, you can modify CPU count, memory size, or network settings by updating this property list. The VPhoneBundle struct provides the configURL property to locate this file programmatically. However, changes to hardware parameters typically require a VM reboot to take effect, and modifying the disk image filename requires the corresponding file to exist in the bundle directory.

Where does vphone-cli store VM bundles by default?

vphone-cli organizes bundles within a VPhoneLibrary, which is a root directory containing a Bundles/ subdirectory. When you create a bundle, it is placed as a subfolder named after the bundle inside this library path. The library path itself is configurable during initialization of the VPhoneLibrary object, allowing you to store VMs on external drives or specific volumes.

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 →