# How to Manage VM Bundles with vphone-cli: Complete CLI Guide

> Learn to manage VM bundles with vphone-cli. This complete CLI guide covers creating, listing, inspecting, booting, and deleting virtual iPhone instances efficiently.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: how-to-guide
- Published: 2026-09-12

---

**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`](https://github.com/Lakr233/vphone-cli/blob/main/sources/VPhoneCore/VPhoneBundle.swift), each bundle must contain:

- **`config.plist`** – A serialized `VPhoneVirtualMachineManifest` that stores hardware model identifiers, boot arguments, and the disk image filename.
- **Disk image** – The raw storage file referenced by the `manifest.diskImage` property.

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`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneVMCreateCLI.swift), initializes a new bundle directory and writes a default manifest. Internally, it uses `VPhoneCreateOrchestrator` to:

1. Create the bundle directory under the configured VM root.
2. Serialize a new `VPhoneVirtualMachineManifest` to `config.plist`.
3. Optionally copy a base disk image into the bundle.

```swift
// 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`](https://github.com/Lakr233/vphone-cli/blob/main/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.

```swift
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`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneVirtualMachine.swift), orchestrated by [`VPhoneAppDelegate.swift`](https://github.com/Lakr233/vphone-cli/blob/main/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`](https://github.com/Lakr233/vphone-cli/blob/main/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:**

```swift
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:**

```swift
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:**

```swift
// Warning: This permanently removes the disk image
try VPhoneBundleOps.delete(bundle: bundle)

```

## Summary

- **VM bundles** are directories containing a `config.plist` manifest and a disk image file.
- Use **`vphone create`** to initialize new bundles via `VPhoneCreateOrchestrator`.
- Use **`vphone list`**, backed by `VPhoneVMPicker`, to enumerate available bundles.
- Use **`vphone inspect`** to query metadata such as `diskSizeBytes` before booting.
- Use **`vphone boot`** to load the manifest and start the VM via `VPhoneVirtualMachine`.
- Use **`vphone delete`** to permanently remove bundles through `VPhoneBundleOps`.

## 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`](https://github.com/Lakr233/vphone-cli/blob/main/sources/VPhoneCore/VPhoneBundle.swift).

### How does vphone-cli locate VM bundles on disk?

The CLI uses `VPhoneVMPicker` from [`sources/VPhoneCore/VPhoneVMPicker.swift`](https://github.com/Lakr233/vphone-cli/blob/main/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`](https://github.com/Lakr233/vphone-cli/blob/main/sources/VPhoneCore/VPhoneVirtualMachineManifest.swift). This plist contains the hardware model identifier, boot arguments, and disk image filename required to construct the `VZVirtualMachineConfiguration`.