Complete Guide to vphone-cli Message Types for Guest Communication

vphone-cli communicates with the guest-side daemon over VSock using a length-prefixed JSON protocol supporting 30+ distinct message types for handshake, input injection, file transfer, app management, and system control.

The open-source tool vphone-cli (maintained in Lakr233/vphone-cli) implements a host-side Swift client that orchestrates virtualized iOS devices. Every message exchanged with the guest daemon vphoned follows a strict JSON envelope containing a protocol version ("v"), message type ("t"), and an optional request identifier ("id"). Understanding these supported message types is essential for extending the tool or debugging guest communication failures.

Protocol Structure and Conventions

All frames are length-prefixed JSON objects sent over a VSock connection on port 1337. The host (Swift) and guest (Objective-C) share an identical vocabulary. Message types determine the payload schema and expected directionality.

In sources/vphone-cli/VPhoneControl.swift, the sendCommand method serializes requests while the read loop dispatches responses based on the "t" field. Timeouts and error handling are managed per-type in this single source file.

Host-to-Guest Request Types

These message types originate from the host CLI and trigger actions inside the guest operating system.

System Handshake and Lifecycle

  • hello – Sent during performHandshake (lines 76-84) to announce the host identity and transmit an optional binary hash for version verification.
  • ping – Liveness check implemented in sendPing (lines 36-37) expecting a pong response.
  • version – Retrieves the guest build hash via sendVersion (lines 40-42).
  • update – Pushes a raw binary payload to the guest when pushUpdate (lines 50-53) detects a version mismatch.
  • devmode – Queries developer mode status through sendDevModeStatus (lines 30-33).
  • low_power_mode – Toggles power state via lowPowerMode (lines 87-92).

Input Injection

  • hid – Transmits keyboard events through sendHIDPress and sendHIDRelease (lines 86-95) using HID page and usage codes.
  • touch – Sends digitizer events via sendTouch (lines 10-18) with phase values: 0 for down, 1 for move, and 3 for up.

File System Operations

The protocol supports full remote file management inside the guest sandbox:

  • file_list – Directory enumeration from listFiles (lines 81-84) returning metadata arrays.
  • file_get – Binary download initiated by downloadFile (lines 90-94).
  • file_put – Upload via uploadFile (lines 100-108) streaming raw bytes.
  • file_mkdir – Directory creation in createDirectory (lines 42-44).
  • file_delete – Removal command from deleteFile (lines 46-48).
  • file_rename – Move or rename operations via renameFile (lines 50-52).

Application Management

  • app_list – Enumerates installed applications through appList (lines 22-27).
  • app_launch – Starts applications optionally with URL payloads via appLaunch (lines 40-45).
  • app_terminate – Force-quits running apps using appTerminate (lines 48-49).
  • app_foreground – Queries the currently focused application in appForeground (lines 52-58).
  • ipa_install – Installs iOS packages through installIPA (lines 64-67).

Security and Clipboard

  • keychain_list – Retrieves stored credentials via listKeychainItems (lines 16-20).
  • keychain_add – Inserts new keychain entries using addKeychainItem (lines 27-33).
  • clipboard_get – Reads pasteboard contents (text and image) from clipboardGet (lines 52-56).
  • clipboard_set – Writes text or binary image data via clipboardSet (lines 63-71).

System Settings and URLs

  • settings_get – Reads user defaults or system preferences in settingsGet (lines 74-78).
  • settings_set – Writes configuration values through settingsSet (lines 80-84).
  • open_url – Requests the guest open a specific URL scheme via openURL (lines 62-66).

Advanced Diagnostics and Location

  • accessibility_tree – Dumps the UIAccessibility hierarchy via accessibilityTree (lines 97-102) for automation debugging.
  • location – Streams GPS coordinates, speed, and altitude updates from sendLocation (lines 112-125).
  • location_stop – Terminates location updates using sendLocationStop (lines 133-138).

Guest-to-Host Response Types

The guest daemon sends these types back to the host, typically as acknowledgments or data payloads.

  • ok – Generic success response handled in the read loop default case (lines 44-48), optionally containing a message string.
  • pong – Explicit response to ping requests (lines 49-51).
  • version – Returns the guest build hash (lines 52-55).
  • err – Error indication carrying a "msg" field, caught as ControlError.guestError in the host (lines 56-58).
  • file_data – Inline binary payload for file_get responses (lines 95-110).
  • clipboard_get – Binary image data when clipboard contains non-text content (lines 15-21).

Bidirectional Common Types

Certain types appear in both directions with context-specific payloads:

  • hello (guest side) – Response during handshake (lines 98-104) carrying guest name, capabilities, IP address, iOS version, and update requirements.
  • need_update – Boolean flag inside the guest hello payload (line 104) triggering the host's update sequence.

Implementation in VPhoneControl.swift

The entire protocol implementation resides in sources/vphone-cli/VPhoneControl.swift. Key architectural details include:

  • VSock connection establishment through VPhoneVirtualMachine.swift (port 1337).
  • Request/response correlation using the "id" field for async/await bridging.
  • Timeout handling per message category (file transfers allow longer durations than pings).
  • Guest daemon scripts in scripts/vphoned/* mirror this type vocabulary in Objective-C.

Practical Code Examples

Sending a HID keyboard shortcut to hide the current app:

let control = VPhoneControl(variant: .regular)
control.sendHIDPress(page: 0x07, usage: 0x0b)   // Command + H

Requesting the UI accessibility tree for automation:

let tree = try await control.accessibilityTree(depth: 3)
print(tree)

Uploading and retrieving a file from the guest:

await control.uploadFile(path: "/tmp/example.txt",
                        data: Data("Hello".utf8))
let data = try await control.downloadFile(path: "/tmp/example.txt")
print(String(data: data, encoding: .utf8) ?? "-")

Handling guest-side errors explicitly:

do {
    try await control.sendPing()
} catch VPhoneControl.ControlError.guestError(let msg) {
    print("Guest reported error: \(msg)")
}

Summary

  • vphone-cli uses a length-prefixed JSON protocol over VSock with mandatory "v" (version) and "t" (type) fields.
  • Host-initiated types cover handshake (hello), input (hid, touch), file operations (file_*), app lifecycle (app_*), and system control (settings_*, location).
  • Guest response types include status codes (ok, err), data payloads (file_data, clipboard_get), and liveness checks (pong).
  • All message types are implemented in VPhoneControl.swift with specific line-numbered handlers for serialization and parsing.
  • The protocol supports binary blob transfer for files, images, and clipboard contents alongside structured JSON metadata.

Frequently Asked Questions

What transport protocol does vphone-cli use for guest communication?

vphone-cli establishes a VSock (Virtio Socket) connection on port 1337 to the guest-side daemon. Messages are length-prefixed JSON objects, ensuring framing integrity when transmitting binary payloads like file contents or HID reports.

How does vphone-cli handle asynchronous responses from the guest?

The host correlates requests and responses using an optional "id" field in the JSON envelope. The Swift implementation in VPhoneControl.swift maintains an internal continuation map that resumes async/await calls when matching response types (like ok, file_data, or err) arrive with the corresponding identifier.

Can vphone-cli transfer binary files between host and guest?

Yes. The file_put and file_get message types support raw binary transmission. When uploading, the host sends the binary payload immediately after the JSON header. When downloading, the guest responds with a file_data frame containing the raw bytes, handled in VPhoneControl.swift lines 95-110.

What happens when the guest vphoned daemon needs an update?

During the initial hello handshake (lines 76-104), the guest sets a need_update boolean flag if its binary hash differs from the host's. The host then sends an update message type via pushUpdate (lines 50-53) containing the new daemon binary, which the guest replaces atomically before reconnecting.

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 →