How to Manage VM Bundles with vphone-cli: Complete CLI Guide
vphone-cli treats each virtual iPhone instance as a VM bundle—a directory containing a config.plist manifest and associated disk image—and provides sub-commands to create, list, inspect, boot, and delete these bundles.
The Lakr233/vphone-cli repository implements a lightweight virtualization toolkit for macOS that abstracts virtual machines into portable bundles. Understanding how to manage VM bundles with vphone-cli requires familiarity with the bundle directory structure, the VPhoneBundle Swift type, and the CLI commands that orchestrate the lifecycle from creation to deletion.
Understanding the VM Bundle Structure
A VM bundle is a self-contained directory that houses everything needed to run a virtual iPhone instance. According to the source code in sources/VPhoneCore/VPhoneBundle.swift, each bundle must contain:
config.plist– A serializedVPhoneVirtualMachineManifestthat stores hardware model identifiers, boot arguments, and the disk image filename.- Disk image – The raw storage file referenced by the
manifest.diskImageproperty.
The bundle abstraction is materialized by the VPhoneBundle type, which provides the static method load(at:) to deserialize a bundle from a file URL. This method validates the directory structure, parses the manifest, and returns a ready-to-use instance that exposes metadata such as name and diskSizeBytes.
CLI Commands for Bundle Lifecycle Management
The command-line interface in sources/vphone-cli/ exposes five primary operations for managing these bundles. Each command maps to specific Swift implementation files that handle the underlying file system and virtualization logic.
Creating New Bundles with vphone create
The create sub-command, implemented in sources/vphone-cli/VPhoneVMCreateCLI.swift, initializes a new bundle directory and writes a default manifest. Internally, it uses VPhoneCreateOrchestrator to:
- Create the bundle directory under the configured VM root.
- Serialize a new
VPhoneVirtualMachineManifesttoconfig.plist. - Optionally copy a base disk image into the bundle.
// Pseudocode representation of the orchestration
let orchestrator = VPhoneCreateOrchestrator(rootURL: vmRoot)
try orchestrator.createBundle(name: "MyiPhone", baseImage: templateURL)
Enumerating Bundles with vphone list
To discover existing bundles, the CLI relies on VPhoneVMPicker located in sources/VPhoneCore/VPhoneVMPicker.swift. This class scans the VM root directory, filters for folders containing a config.plist, and yields VPhoneBundle instances. The allBundles() method returns an array that the CLI formats using VPhoneBundleReport for human-readable output.
Inspecting Bundle Metadata with vphone inspect
The inspect command provides detailed visibility into a specific bundle. It leverages the diskSizeBytes property on VPhoneBundle, which lazily queries the file system for the disk image size. This is useful for verifying storage utilization before booting the VM.
let bundle = try VPhoneBundle.load(at: bundleURL)
print("Disk size (MiB):", bundle.diskSizeBytes / 1_048_576)
Booting Virtual Machines with vphone boot
Booting a bundle involves loading its manifest and constructing a VZVirtualMachineConfiguration. The logic resides in sources/vphone-cli/VPhoneVirtualMachine.swift, orchestrated by VPhoneAppDelegate.swift. The boot command reads the hardware model from the manifest, attaches the disk image, and starts the VZVirtualMachine instance.
Deleting Bundles with vphone delete
The delete command triggers VPhoneBundleOps.delete(bundle:) in sources/VPhoneCore/VPhoneBundleOps.swift. This operation recursively removes the bundle directory and its disk image from the file system. This action is destructive and removes the underlying storage file referenced by the manifest.
Programmatic Bundle Management
While the CLI provides convenient sub-commands, you can manage bundles directly using the Swift types. The following examples demonstrate common workflows using the core library:
Loading a specific bundle by path:
import VPhoneCore
let bundleURL = URL(fileURLWithPath: "/Users/me/vphone/vms/MyiPhone")
let bundle = try VPhoneBundle.load(at: bundleURL)
print("Bundle name:", bundle.name)
print("Manifest hardware:", bundle.manifest.hardwareModel)
Enumerating all bundles in the VM root:
let picker = VPhoneVMPicker(rootURL: URL(fileURLWithPath: "/Users/me/vphone/vms"))
for bundle in try picker.allBundles() {
print("\(bundle.name) – \(bundle.diskSizeBytes) bytes")
}
Deleting a bundle programmatically:
// Warning: This permanently removes the disk image
try VPhoneBundleOps.delete(bundle: bundle)
Summary
- VM bundles are directories containing a
config.plistmanifest and a disk image file. - Use
vphone createto initialize new bundles viaVPhoneCreateOrchestrator. - Use
vphone list, backed byVPhoneVMPicker, to enumerate available bundles. - Use
vphone inspectto query metadata such asdiskSizeBytesbefore booting. - Use
vphone bootto load the manifest and start the VM viaVPhoneVirtualMachine. - Use
vphone deleteto permanently remove bundles throughVPhoneBundleOps.
Frequently Asked Questions
What files are inside a vphone-cli VM bundle?
Each bundle directory contains a config.plist file, which stores the VPhoneVirtualMachineManifest (hardware settings and boot arguments), and the raw disk image file named in the manifest's diskImage property. These files are managed by the VPhoneBundle type defined in sources/VPhoneCore/VPhoneBundle.swift.
How does vphone-cli locate VM bundles on disk?
The CLI uses VPhoneVMPicker from sources/VPhoneCore/VPhoneVMPicker.swift to scan the configured VM root directory. It filters directories for the presence of config.plist and instantiates VPhoneBundle objects for each valid bundle found, exposed through the allBundles() method.
Can I manage bundles without using the CLI commands?
Yes. You can import the VPhoneCore module directly and use Swift APIs such as VPhoneBundle.load(at:), VPhoneBundleOps.delete(bundle:), and VPhoneCreateOrchestrator to create, inspect, and remove bundles programmatically without invoking the CLI binary.
Where is the VM configuration stored?
The configuration is stored in the bundle's config.plist file, which is serialized and deserialized by VPhoneVirtualMachineManifest in sources/VPhoneCore/VPhoneVirtualMachineManifest.swift. This plist contains the hardware model identifier, boot arguments, and disk image filename required to construct the VZVirtualMachineConfiguration.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →