Files
osy b1e1b12a05 scripting: model snapshots as scriptable objects
The snapshot commands could only name a snapshot and could not say anything
about it. A script could not tell when a snapshot was taken, how much it
holds, whether restoring it resumes the guest or starts it up, or whether
its data has gone missing, and there was no way to rename one or to throw
away a suspended state, both of which the window offers.

Make a snapshot an object instead. A virtual machine now has snapshots as
elements, each carrying those details, so a script can pick one out and
read it:

    tell application "UTM"
      set vm to virtual machine named "Debian"
      set candidates to (snapshots of vm whose includes running state)
      restore (item 1 of candidates)
    end tell

Renaming is setting the name, and the commands that act on a snapshot take
the snapshot itself. Creating one returns it. Two more commands cover what
the window can do and scripting could not: scanning the images for
snapshots made by other tools, and discarding a saved state so the guest
starts up instead of resuming.

This replaces the snapshot commands of the 5.0.5 beta, which addressed a
snapshot by name through its virtual machine, so scripts and utmctl calls
written against them have to be updated.

Snapshots are addressed by name, so names are now kept apart the way
virtual machine names are, by appending a number.

Deleting a snapshot is its own command rather than the standard delete,
which coerces a specifier for anything inside a virtual machine into the
virtual machine itself; deleting that would throw away far more than was
asked for. The delete command refuses such a specifier for the same reason.

UTMScripting.swift is regenerated from the sdef; only the hunks that
changed are taken.

Assisted-by: Claude:claude-opus-5
2026-09-22 10:57:36 -05:00

1025 lines
59 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="UTM Terminology" xmlns:xi="http://www.w3.org/2003/XInclude">
<xi:include href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef" xpointer="xpointer(/dictionary/suite)"/>
<suite name="UTM Suite" code="UTMs" description="UTM virtual machines scripting suite.">
<access-group identifier="com.utmapp.UTM.vm-access" />
<command name="make" code="corecrel" description="Create a new virtual machine.">
<cocoa class="UTMScriptingCreateCommand"/>
<parameter name="new" code="kocl" type="type" description="Specify 'virtual machine' here.">
<cocoa key="ObjectClass"/>
</parameter>
<parameter name="with properties" code="prdt" type="record" description="You must specify the backend as well as a configuration with a name. If this is a QEMU virtual machine, you must specify the architecture in the configuration as well.">
<cocoa key="KeyDictionary"/>
</parameter>
<result type="specifier" description="The new virtual machine (as a specifier)."/>
</command>
<class-extension extends="application" description="An application's top level scripting object.">
<element type="virtual machine" access="r">
<cocoa key="scriptingVirtualMachines"/>
</element>
<property name="auto terminate" code="kRlW" type="boolean" description="Auto terminate the application when all windows are closed?">
<cocoa key="isAutoTerminate"/>
</property>
<property name="UTM version" code="UTMV" type="text" access="r" description="The version number of UTM.">
<cocoa key="version"/>
</property>
</class-extension>
<enumeration name="operating system" code="ApOe" description="Guest operating system for an Apple virtual machine.">
<enumerator name="linux" code="ApOl" description="Linux guest."/>
<enumerator name="macOS" code="ApOm" description="macOS guest (Apple silicon only)."/>
</enumeration>
<enumeration name="backend" code="VmEb" description="Backend type.">
<enumerator name="apple" code="ApPl" description="Apple Virtualization.framework backend."/>
<enumerator name="qemu" code="QeMu" description="QEMU backend."/>
<enumerator name="unavailable" code="UnAv" description="The virtual machine is not currently available."/>
</enumeration>
<enumeration name="status" code="VmEs" description="Status type.">
<enumerator name="stopped" code="StSa" description="VM is not running."/>
<enumerator name="starting" code="StSb" description="VM is starting up."/>
<enumerator name="started" code="StSc" description="VM is running."/>
<enumerator name="pausing" code="StSd" description="VM is going to pause."/>
<enumerator name="paused" code="StSe" description="VM is paused."/>
<enumerator name="resuming" code="StSf" description="VM is resuming from pause."/>
<enumerator name="stopping" code="StSg" description="VM is stopping."/>
</enumeration>
<enumeration name="stop method" code="VmEs" description="Stop by method.">
<enumerator name="force" code="FoRc" description="Force stop VM by sending stop request to the backend."/>
<enumerator name="kill" code="KiLl" description="Force kill VM by terminating the backend."/>
<enumerator name="request" code="ReQu" description="Send a power down request to the guest OS which may be ignored."/>
</enumeration>
<enumeration name="serial interface" code="VmEr" description="Serial port interface.">
<enumerator name="ptty" code="PtTy" description="Pseudo TTY port."/>
<enumerator name="tcp" code="TcP " description="TCP port."/>
<enumerator name="unavailable" code="IUnA" description="Serial interface is currently unavailable or is in use by the GUI."/>
</enumeration>
<command name="start" code="UTMvstar" description="Start a virtual machine or resume a suspended virtual machine.">
<direct-parameter description="Virtual machine to start." type="virtual machine"/>
<parameter name="saving" code="SaVe" description="When false, do not save the VM changes to disk. Default value is true." type="boolean" optional="yes">
<cocoa key="saveFlag"/>
</parameter>
<parameter name="recovery" code="ReCo" description="When true, start the VM in recovery mode. Default value is false." type="boolean" optional="yes">
<cocoa key="bootRecoveryFlag"/>
</parameter>
<parameter name="provisioning" code="GpOp" description="Set up a macOS guest without user interaction. Only applies to the first start after macOS is installed and is never saved. Requires the Apple backend, macOS 27 or later, and a guest with macOS 27 or later." type="guest provisioning" optional="yes">
<cocoa key="provisioningOptions"/>
</parameter>
</command>
<record-type name="guest provisioning" code="GpCf" description="Account to create when setting up a macOS guest.">
<property name="full name" code="GpFn" type="text"
description="Full name of the account. Defaults to the username."/>
<property name="username" code="GpUs" type="text"
description="Short name of the account."/>
<property name="password" code="GpPw" type="text"
description="Password of the account."/>
<property name="automatic login" code="GpAl" type="boolean"
description="Log in to the account automatically when the guest starts up. Default value is false."/>
<property name="remote login" code="GpRl" type="boolean"
description="Turn on Remote Login (SSH) in the guest. Default value is false."/>
</record-type>
<command name="install" code="UTMvinst" description="Install macOS on a stopped Apple virtual machine from its IPSW recovery image. All data on the primary drive will be erased, there is no confirmation! Returns once the installation starts, use query install to follow its progress.">
<direct-parameter description="Virtual machine to install macOS on." type="virtual machine"/>
</command>
<record-type name="install progress" code="InPr" description="Progress of a macOS installation.">
<property name="installing" code="InIn" type="boolean" access="r"
description="If true, the installation has not finished yet.">
<cocoa key="isInstalling"/>
</property>
<property name="progress" code="InPg" type="real" access="r"
description="Fraction of the installation that is completed, from 0.0 to 1.0."/>
</record-type>
<command name="query install" code="UTMvqins" description="Query the progress of the last installation started with install. Raises an error if the installation failed.">
<direct-parameter description="Virtual machine to query." type="virtual machine"/>
<result type="install progress" description="Progress of the installation."/>
</command>
<command name="suspend" code="UTMvsusp" description="Suspend a running virtual machine to memory.">
<direct-parameter description="Virtual machine to suspend." type="virtual machine"/>
<parameter name="saving" code="SaVe" description="Save VM state to disk after suspend. Default value is false." type="boolean" optional="yes">
<cocoa key="saveFlag"/>
</parameter>
</command>
<command name="stop" code="UTMvstop" description="Shuts down a running virtual machine.">
<direct-parameter description="Virtual machine to stop." type="virtual machine"/>
<parameter name="by" code="StBy" description="Method to stop the VM." type="stop method" optional="yes">
<cocoa key="stopBy"/>
</parameter>
</command>
<command name="create snapshot" code="UTMvcrsn" description="Save the current state of a virtual machine as a new snapshot. A running QEMU virtual machine is saved along with its running state, otherwise only the disks are.">
<direct-parameter description="Virtual machine to snapshot." type="virtual machine"/>
<parameter name="named" code="SnNm" description="Name for the new snapshot. A name already in use gets a number appended. If omitted, a name is generated." type="text" optional="yes">
<cocoa key="snapshotName"/>
</parameter>
<result description="The snapshot that was created." type="snapshot"/>
</command>
<command name="restore" code="UTMvrssn" description="Replace the current state of a virtual machine with a snapshot. A virtual machine that is not running resumes from it the next time it is started.">
<direct-parameter description="Snapshot to restore." type="snapshot"/>
</command>
<command name="delete snapshot" code="UTMvdlsn" description="Delete a snapshot. Its data is deleted with it, there is no confirmation!">
<direct-parameter description="Snapshot to delete." type="snapshot"/>
</command>
<command name="overwrite" code="UTMvovsn" description="Replace what a snapshot holds with the current state of the virtual machine. The snapshot keeps its name and its place among the others.">
<direct-parameter description="Snapshot to overwrite." type="snapshot"/>
</command>
<command name="scan snapshots" code="UTMvscsn" description="Look through the disk images of a virtual machine for snapshots that UTM does not know about yet, and mark the ones whose data has gone missing. Only needed for snapshots made by other tools.">
<direct-parameter description="Virtual machine to scan." type="virtual machine"/>
</command>
<command name="discard saved state" code="UTMvdcss" description="Throw away the state a suspended virtual machine would resume from, so that it starts up normally instead. Snapshots are not affected.">
<direct-parameter description="Virtual machine to discard the saved state of." type="virtual machine"/>
</command>
<command name="delete" code="coredelo" description="Delete a virtual machine. All data will be deleted, there is no confirmation!">
<cocoa class="UTMScriptingDeleteCommand"/>
<access-group identifier="*"/>
<direct-parameter type="virtual machine" description="The virtual machine to delete."/>
</command>
<command name="duplicate" code="coreclon" description="Copy an virtual machine and all its data.">
<cocoa class="UTMScriptingCloneCommand"/>
<access-group identifier="*"/>
<direct-parameter type="virtual machine" requires-access="r" description="The virtual machine to copy."/>
<parameter name="with properties" code="prdt" type="record" description="Only the configuration can be changed." optional="yes">
<cocoa key="WithProperties"/>
</parameter>
</command>
<command name="import" code="coreimpo" description="Import a new virtual machine from a file.">
<cocoa class="UTMScriptingImportCommand"/>
<parameter name="new" code="imcl" type="type" description="Specify 'virtual machine' here.">
<cocoa key="ObjectClass"/>
</parameter>
<parameter name="from" code="ifil" type="file" description="The virtual machine file (.utm) to import.">
<cocoa key="file"/>
</parameter>
<result type="specifier" description="The new virtual machine (as a specifier)."/>
</command>
<command name="export" code="coreexpo" description="Export a virtual machine to a specified location.">
<cocoa class="UTMScriptingExportCommand"/>
<direct-parameter type="virtual machine" requires-access="r" description="The virtual machine to export."/>
<parameter name="to" code="efil" type="file" description="Location to export the VM to.">
<cocoa key="file"/>
</parameter>
</command>
<class name="virtual machine" code="UTMv" description="A virtual machine registered in UTM." plural="virtual machines">
<cocoa class="UTMScriptingVirtualMachineImpl"/>
<property name="id" code="ID " type="text" access="r"
description="The unique identifier of the VM."/>
<property name="name" code="pnam" type="text" access="r"
description="The name of the VM."/>
<property name="backend" code="BaKe" type="backend" access="r"
description="Emulation/virtualization engine used."/>
<property name="status" code="StUs" type="status" access="r"
description="Current running status."/>
<element type="serial port" access="r"
description="Serial ports exposed by the guest to the host to access.">
<cocoa key="serialPorts"/>
</element>
<element type="snapshot" access="r"
description="Saved states of this virtual machine, newest first.">
<cocoa key="snapshots"/>
</element>
<responds-to command="start">
<cocoa method="start:"/>
</responds-to>
<responds-to command="install">
<cocoa method="install:"/>
</responds-to>
<responds-to command="query install">
<cocoa method="queryInstall:"/>
</responds-to>
<responds-to command="suspend">
<cocoa method="suspend:"/>
</responds-to>
<responds-to command="stop">
<cocoa method="stop:"/>
</responds-to>
<responds-to command="create snapshot">
<cocoa method="createSnapshot:"/>
</responds-to>
<responds-to command="scan snapshots">
<cocoa method="scanSnapshots:"/>
</responds-to>
<responds-to command="discard saved state">
<cocoa method="discardSavedState:"/>
</responds-to>
<responds-to command="delete">
<cocoa method="delete:"/>
</responds-to>
</class>
<class name="snapshot" code="SnAp" description="A saved state of a virtual machine that it can be returned to." plural="snapshots">
<cocoa class="UTMScriptingSnapshotImpl"/>
<property name="id" code="ID " type="text" access="r"
description="The unique identifier of the snapshot."/>
<property name="name" code="pnam" type="text"
description="Name shown for the snapshot. Setting it renames the snapshot; a name already in use gets a number appended."/>
<property name="creation date" code="ascd" type="date" access="r"
description="When the snapshot was first saved."/>
<property name="modification date" code="asmo" type="date" access="r"
description="When the snapshot was last renamed or overwritten."/>
<property name="size" code="SnSz" type="real" access="r"
description="Bytes the snapshot occupies."/>
<property name="includes running state" code="SnRs" type="boolean" access="r"
description="Whether the snapshot holds the running machine as well as the disks. Restoring one that does not means the virtual machine starts up instead of resuming."/>
<property name="data missing" code="SnDm" type="boolean" access="r"
description="Whether the data behind the snapshot has gone missing, in which case it can only be deleted."/>
<property name="based on" code="SnBo" type="text" access="r"
description="Identifier of the snapshot the current state was based on when this one was saved, or empty if it was not based on any."/>
<responds-to command="restore">
<cocoa method="restore:"/>
</responds-to>
<responds-to command="overwrite">
<cocoa method="overwrite:"/>
</responds-to>
<responds-to command="delete snapshot">
<cocoa method="deleteSnapshot:"/>
</responds-to>
</class>
<class name="serial port" code="SeRi" description="A serial port in the guest that can be connected to from the host." plural="serial ports">
<cocoa class="UTMScriptingSerialPortImpl"/>
<property name="id" code="ID " type="integer" access="r"
description="The unique identifier of the tag."/>
<property name="interface" code="InTf" type="serial interface" access="r"
description="The type of serial interface on the host."/>
<property name="address" code="AdDr" type="text" access="r"
description="Host address of the serial port (determined by the interface type)."/>
<property name="port" code="PoRt" type="integer" access="r"
description="Port number of the serial port (not used in some interface types)."/>
</class>
</suite>
<suite name="UTM Guest Suite" code="UTMg" description="UTM virtual machine guest scripting suite. In order to use these commands, QEMU guest agent must be running.">
<access-group identifier="com.utmapp.UTM.vm-access" />
<class-extension extends="virtual machine" description="Guest agent access.">
<element type="guest file" access="r"
description="Open files for this virtual machine from the guest agent.">
<cocoa key="openFiles"/>
</element>
<element type="guest process" access="r"
description="Processe executed on this virtual machine from the guest agent.">
<cocoa key="processes"/>
</element>
<responds-to command="open file">
<cocoa method="openFile:"/>
</responds-to>
<responds-to command="execute">
<cocoa method="execute:"/>
</responds-to>
<responds-to command="query ip">
<cocoa method="queryIp:"/>
</responds-to>
</class-extension>
<enumeration name="open mode" code="OpMo" description="File open mode.">
<enumerator name="reading" code="OpRo" description="Open the file as read only. The file must exist."/>
<enumerator name="writing" code="OpWo" description="Open the file for writing. If the file does not exist, it will be created. If the file exists, it will be overwritten."/>
<enumerator name="appending" code="OpAp" description="Open the file for writing at the end. Offsets are ignored for writes. If the file does not exist, it will be created."/>
</enumeration>
<command name="open file" code="UTMgOpEn" description="Open a file on the guest. You must close the file when you are done to prevent leaking guest resources.">
<direct-parameter description="Virtual machine of the guest." type="virtual machine"/>
<parameter name="at" code="OpPt" description="The guest path of the file to open." type="text">
<cocoa key="path"/>
</parameter>
<parameter name="for" code="OpMd" description="Open mode." type="open mode" optional="yes">
<cocoa key="mode"/>
</parameter>
<parameter name="updating" code="OpAp" description="If true, will open for both reading and writing. The file existence requirement and creation is still governed by the open mode. Default is false." type="boolean" optional="yes">
<cocoa key="isUpdate"/>
</parameter>
<result type="guest file" description="Guest file to operate on."/>
</command>
<command name="execute" code="UTMgExEc" description="Execute a command or script on the guest.">
<direct-parameter description="Virtual machine of the guest." type="virtual machine"/>
<parameter name="at" code="ExPt" description="Either the full path of the executable to run or an executable found in the guest's PATH environment." type="text">
<cocoa key="path"/>
</parameter>
<parameter name="with arguments" code="ExAg" description="List of arguments to pass to the executable." optional="yes">
<cocoa key="argv"/>
<type type="text" list="yes"/>
</parameter>
<parameter name="with environment" code="ExEv" description="List of environment variables to pass to the executable. Each entry should be in the format NAME=VALUE." optional="yes">
<cocoa key="envp"/>
<type type="text" list="yes"/>
</parameter>
<parameter name="using input" code="ExIn" description="Data to feed into the process's standard input. If using base64 encoding, this should be a valid base64 string." type="text" optional="yes">
<cocoa key="input"/>
</parameter>
<parameter name="base64 encoding" code="Ex64" description="Input data is base64 encoded. The data will be decoded before being passed to the executable. Default is false." type="boolean" optional="yes">
<cocoa key="isBase64Encoded"/>
</parameter>
<parameter name="output capturing" code="ExOc" description="If true, the standard output and error will be captured and accessible in the returned object. You need to call update on the object to get the data. Default is false." type="boolean" optional="yes">
<cocoa key="isCaptureOutput"/>
</parameter>
<result type="guest process" description="Guest process that can be used to fetch the return value and outputs (if captured)."/>
</command>
<command name="query ip" code="UTMgIpAd" description="Query the guest for all IP addresses on its network interfaces (excluding loopback).">
<direct-parameter description="Virtual machine of the guest." type="virtual machine"/>
<result description="List of IP addresses on all network interfaces (excluding loopback). Both IPv4 and IPv6 addresses can be returned. IPv4 addresses will show up before IPv6 addresses if any are available.">
<type type="text" list="yes"/>
</result>
</command>
<class name="guest file" code="GuFi" description="A file that resides on the guest." plural="guest files">
<cocoa class="UTMScriptingGuestFileImpl"/>
<property name="id" code="ID " type="integer" access="r"
description="The handle for the file."/>
<responds-to command="read">
<cocoa method="read:"/>
</responds-to>
<responds-to command="pull">
<cocoa method="pull:"/>
</responds-to>
<responds-to command="write">
<cocoa method="write:"/>
</responds-to>
<responds-to command="push">
<cocoa method="push:"/>
</responds-to>
<responds-to command="close">
<cocoa method="close:"/>
</responds-to>
</class>
<enumeration name="whence" code="WeCe" description="Where to offset from.">
<enumerator name="start position" code="StRt" description="The start of the file (only positive offsets)."/>
<enumerator name="current position" code="CuRr" description="The current pointer (both positive and negative offsets)."/>
<enumerator name="end position" code="UnAv" description="The end of the file (only negative offsets for reads, both for writes)."/>
</enumeration>
<command name="read" code="GuFiReAd" description="Reads text data from a guest file.">
<direct-parameter description="Guest file to read." type="guest file"/>
<parameter name="at offset" code="RdOf" description="Specify the offset to start reading from. Default value is zero." type="integer" optional="yes">
<cocoa key="offset"/>
</parameter>
<parameter name="from" code="RdWh" description="Specify where the offset is from. Default value is from the current file pointer." type="whence" optional="yes">
<cocoa key="whence"/>
</parameter>
<parameter name="for length" code="RdLn" description="Amount of bytes to read. The limit is 48 MB. Default is to read until the end." type="integer" optional="yes">
<cocoa key="length"/>
</parameter>
<parameter name="base64 encoding" code="Rd64" description="If true, then the result will be base64 encoded. This is recommended if you are reading a binary file. Default is false." type="boolean" optional="yes">
<cocoa key="isBase64Encoded"/>
</parameter>
<parameter name="closing" code="RdCl" description="If true, the file will be closed after reading and must be opened again to perform more operations. If false, you can perform multiple reads on the same open file. The default is true." type="boolean" optional="yes">
<cocoa key="isClosing"/>
</parameter>
<result type="text" description="Data read from the guest file."/>
</command>
<command name="pull" code="GuFiPuLl" description="Pulls a file from the guest to the host.">
<direct-parameter description="Guest file to pull." type="guest file"/>
<parameter name="to" code="kfil" description="The host file in which to save the guest file." type="file">
<cocoa key="file"/>
</parameter>
<parameter name="closing" code="PlCl" description="If true, the file will be closed after reading and must be opened again to perform more operations. If false, you can perform multiple reads on the same open file. The default is true." type="boolean" optional="yes">
<cocoa key="isClosing"/>
</parameter>
</command>
<command name="write" code="GuFiWrIt" description="Writes text data to a guest file.">
<direct-parameter description="Guest file to write." type="guest file"/>
<parameter name="with data" code="WrDt" description="Data to write to the guest file. If base64 encoding is specified, this should be a valid base64 string which will be decoded before writing." type="text">
<cocoa key="data"/>
</parameter>
<parameter name="at offset" code="WrOf" description="Specify the offset to start writing to. Default value is zero." type="integer" optional="yes">
<cocoa key="offset"/>
</parameter>
<parameter name="from" code="WrWh" description="Specify where the offset is from. Default value is from the current file pointer." type="whence" optional="yes">
<cocoa key="whence"/>
</parameter>
<parameter name="base64 encoding" code="Wr64" description="If true, then the input data is base64 encoded. This is recommended if you are writing a binary file. Default is false." type="boolean" optional="yes">
<cocoa key="isBase64Encoded"/>
</parameter>
<parameter name="closing" code="WrCl" description="If true, the file will be closed after writing and must be opened again to perform more operations. If false, you can perform multiple reads on the same open file. The default is true." type="boolean" optional="yes">
<cocoa key="isClosing"/>
</parameter>
</command>
<command name="push" code="GuFiPuSh" description="Pushes a file from the host to the guest and closes it.">
<direct-parameter description="Guest file to push." type="guest file"/>
<parameter name="from" code="kfil" description="The host file in which to send to the guest." type="file">
<cocoa key="file"/>
</parameter>
<parameter name="closing" code="PsCl" description="If true, the file will be closed after writing and must be opened again to perform more operations. If false, you can perform multiple reads on the same open file. The default is true." type="boolean" optional="yes">
<cocoa key="isClosing"/>
</parameter>
</command>
<command name="close" code="GuFiClOs" description="Closes the file and prevent further operations.">
<direct-parameter description="Guest file to close." type="guest file"/>
</command>
<class name="guest process" code="GuPr" description="A process on the guest." plural="guest processes">
<cocoa class="UTMScriptingGuestProcessImpl"/>
<property name="id" code="ID " type="integer" access="r"
description="The PID of the process."/>
<responds-to command="get result">
<cocoa method="getResult:"/>
</responds-to>
</class>
<record-type name="execute result" code="ExRs" description="Process results after execution.">
<property name="exited" code="ExTd" type="boolean" access="r"
description="If true, the process has terminated.">
<cocoa key="hasExited" />
</property>
<property name="exit code" code="ExCd" type="integer" access="r"
description="Exit code if it was normally terminated."/>
<property name="signal code" code="SiCd" type="integer" access="r"
description="Signal number (Linux) or unhandled exception code (Windows) if the process was abnormally terminated."/>
<property name="output text" code="OuTx" type="text" access="r"
description="If capture is enabled, the stdout of the process as text."/>
<property name="error text" code="ErTx" type="text" access="r"
description="If capture is enabled, the stderr of the process as text."/>
<property name="output data" code="OuDa" type="text" access="r"
description="If capture is enabled, the stdout of the process as base64 encoded data."/>
<property name="error data" code="ErDa" type="text" access="r"
description="If capture is enabled, the stderr of the process as base64 encoded data."/>
</record-type>
<command name="get result" code="GuPrGeRs" description="Fetch execution result from the guest.">
<direct-parameter description="Guest process to fetch result from." type="guest process"/>
<result type="execute result" description="Result from the guest."/>
</command>
</suite>
<suite name="UTM Configuration Suite" code="UTMc" description="UTM virtual machine configuration suite. Use this to create and configure virtual machines.">
<access-group identifier="com.utmapp.UTM.vm-access" />
<class-extension extends="virtual machine" description="Virtual machine configuration.">
<property name="configuration" code="CoFg" access="r"
description="The configuration of the virtual machine.">
<type type="qemu configuration"/>
<type type="apple configuration"/>
</property>
<responds-to command="update configuration">
<cocoa method="updateConfiguration:"/>
</responds-to>
<responds-to command="reload configuration">
<cocoa method="reloadConfiguration:"/>
</responds-to>
</class-extension>
<command name="update configuration" code="UTMcUpDt" description="Update the configuration of the virtual machine. The VM must be in the stopped state.">
<direct-parameter description="Virtual machine to configure." type="virtual machine"/>
<parameter name="with" code="UpCf" description="The configuration to update the virtual machine. You cannot change the backend with this!">
<cocoa key="newConfiguration"/>
<type type="qemu configuration"/>
<type type="apple configuration"/>
</parameter>
</command>
<command name="reload configuration" code="UTMcReLd" description="Reload the configuration of the virtual machine from disk, discarding any unsaved in-memory changes. Useful when the .utm bundle has been modified externally (e.g. by an automation tool) and UTM's cached configuration needs to be refreshed. The VM must be in the stopped state.">
<direct-parameter description="Virtual machine to reload." type="virtual machine"/>
</command>
<record-type name="qemu configuration" code="QeCf" description="QEMU virtual machine configuration.">
<property name="name" code="pnam" type="text"
description="Virtual machine name."/>
<property name="icon" code="IcOn" type="text"
description="Virtual machine icon."/>
<property name="notes" code="NoTe" type="text"
description="User-specified notes."/>
<property name="architecture" code="ArCh" type="text"
description="QEMU system architecture."/>
<property name="machine" code="MaCh" type="text"
description="QEMU target machine (if empty, the default will be used)."/>
<property name="memory" code="MeMy" type="integer"
description="RAM size (in mebibytes)."/>
<property name="cpu cores" code="CpUc" type="integer"
description="Number of CPU cores (0 is the default for this host)."/>
<property name="hypervisor" code="HyPr" type="boolean"
description="Use the hypervisor (if supported)?"/>
<property name="uefi" code="UeFi" type="boolean"
description="Use UEFI boot?"/>
<property name="directory share mode" code="DrSm" type="qemu directory share mode"
description="Mode for directory sharing."/>
<property name="drives" code="DrVs"
description="List of drive configuration.">
<type type="qemu drive configuration" list="yes"/>
</property>
<property name="network interfaces" code="NtIf"
description="List of network configuration.">
<type type="qemu network configuration" list="yes"/>
</property>
<property name="serial ports" code="SrPt"
description="List of serial configuration.">
<type type="qemu serial configuration" list="yes"/>
</property>
<property name="displays" code="DiPs"
description="List of display configuration.">
<type type="qemu display configuration" list="yes"/>
</property>
<property name="qemu additional arguments" code="QeAd"
description="List of qemu arguments.">
<type type="qemu argument" list="yes"/>
</property>
</record-type>
<enumeration name="qemu directory share mode" code="QeSm" description="Method for sharing directory in QEMU.">
<enumerator name="none" code="SmOf" description="Do not enable directory sharing."/>
<enumerator name="WebDAV" code="SmWv" description="Use SPICE WebDav (SPICE guest tools required)."/>
<enumerator name="VirtFS" code="SmVs" description="Use VirtFS mount tagged 'share' (VirtFS guest drivers required)."/>
</enumeration>
<record-type name="qemu drive configuration" code="QdEc" description="QEMU virtual existing drive configuration.">
<property name="id" code="ID " type="text" access="r"
description="The unique identifier for this drive (if empty, a new drive will be created)."/>
<property name="removable" code="ReMv" type="boolean" access="r"
description="Is this drive removable (cannot be changed after creation)?"/>
<property name="interface" code="InTf" type="qemu drive interface"
description="The hardware interface this drive is attached to (if empty, the default will be used)."/>
<property name="host size" code="HoSz" type="integer" access="r"
description="The size of this drive as seen by the host (in MiB)."/>
<property name="guest size" code="GuSz" type="integer"
description="The size of this drive as seen by the guest (in MiB)."/>
<property name="raw" code="RaAw" type="boolean"
description="Is this disk image raw format (only for newly created drives)?"/>
<property name="source" code="SrCe" type="file"
description="An existing file to use as the source image."/>
</record-type>
<enumeration name="qemu drive interface" code="QeDi" description="QEMU drive interfaces.">
<enumerator name="none" code="QdIN"/>
<enumerator name="IDE" code="QdIi"/>
<enumerator name="SCSI" code="QdIs"/>
<enumerator name="SD" code="QdId"/>
<enumerator name="MTD" code="QdIm"/>
<enumerator name="Floppy" code="QdIf"/>
<enumerator name="PFlash" code="QdIp"/>
<enumerator name="VirtIO" code="QdIv"/>
<enumerator name="NVMe" code="QdIn"/>
<enumerator name="USB" code="QdIu"/>
</enumeration>
<record-type name="qemu network configuration" code="QeCn" description="QEMU virtual network configuration.">
<property name="index" code="pidx" type="integer"
description="The position of the configuration to update. It can be empty to create a new device. Index is invalid after updating the configuration and must be reset to the current position."/>
<property name="hardware" code="HaWe" type="text"
description="Name of the emulated network card (if empty, the default will be used)."/>
<property name="mode" code="MoDe" type="qemu network mode"
description="This determines how the network device is attached to the host."/>
<property name="address" code="AdDr" type="text"
description="MAC address (formatted as XX:XX:XX:XX:XX:XX, if empty a random address will be genertaed)"/>
<property name="host interface" code="HoIf" type="text"
description="Only used in bridged mode. Specify the interface name to bridge to."/>
<property name="port forwards" code="PtFw"
description="Only used in emulated mode. Allows port forwarding from guest to host.">
<type type="qemu port forward" list="yes"/>
</property>
<property name="vlan guest address" code="VgAd" type="text"
description="IPv4 subnet of the emulated VLAN in CIDR notation (e.g. 192.168.222.0/24). Only used in shared or host mode. If empty, the existing value is preserved."/>
<property name="vlan guest address ipv6" code="Vga6" type="text"
description="IPv6 prefix of the emulated VLAN (e.g. fec0::/64). Only used in shared or host mode. If empty, the existing value is preserved."/>
<property name="vlan dhcp start address" code="VdSt" type="text"
description="First IPv4 address of the DHCP pool handed to the guest. Only used in shared or host mode. If empty, the existing value is preserved."/>
<property name="vlan dhcp end address" code="VdEn" type="text"
description="Last IPv4 address of the DHCP pool handed to the guest. Only used in shared or host mode. If empty, the existing value is preserved."/>
<property name="isolate from host" code="IsFh" type="boolean"
description="When true, the guest is isolated from the host on the shared network."/>
</record-type>
<enumeration name="qemu network mode" code="QeNm" description="Mode for networking device.">
<enumerator name="emulated" code="EmUd" description="Emulate a VLAN."/>
<enumerator name="shared" code="ShRd" description="NAT based sharing with the host."/>
<enumerator name="host" code="HoSt" description="NAT based sharing with no WAN routing."/>
<enumerator name="bridged" code="BrGd" description="Bridged to a host interface."/>
</enumeration>
<record-type name="qemu port forward" code="QePf" description="QEMU port forward configuration.">
<property name="protocol" code="PrTl" type="network protocol"
description="Protocol of the port that will be forwarded."/>
<property name="host address" code="HoAd" type="text"
description="The host interface IP address to forward to (if empty, it will forward to any interface)."/>
<property name="host port" code="HoPo" type="integer"
description="Port number on the host."/>
<property name="guest address" code="GuAd" type="text"
description="The IP address on the guest subnet to forward from (if empty, any guest IP will be accepted)."/>
<property name="guest port" code="GuPo" type="integer"
description="Port number on the guest."/>
</record-type>
<enumeration name="network protocol" code="NtPr" description="Supported network protocols.">
<enumerator name="TCP" code="TcPp"/>
<enumerator name="UDP" code="UdPp"/>
</enumeration>
<record-type name="qemu serial configuration" code="QeSn" description="QEMU virtual serial configuration.">
<property name="index" code="pidx" type="integer"
description="The position of the configuration to update. It can be empty to create a new device. Index is invalid after updating the configuration and must be reset to the current position."/>
<property name="hardware" code="HaWe" type="text"
description="Name of the emulated serial device (if empty, the default will be used)."/>
<property name="interface" code="InTf" type="serial interface"
description="The type of serial interface on the host."/>
<property name="port" code="PoRt" type="integer"
description="The port number to listen on when the interface is a TCP server."/>
</record-type>
<record-type name="qemu display configuration" code="QdYc" description="QEMU virtual display configuration.">
<property name="index" code="pidx" type="integer"
description="The position of the configuration to update. It can be empty to create a new device. Index is invalid after updating the configuration and must be reset to the current position."/>
<property name="hardware" code="HaWe" type="text"
description="Name of the emulated display card (required. if given hardware not found, the default will be used)."/>
<property name="dynamic resolution" code="DyRe" type="boolean"
description="If true, attempt to use SPICE guest agent to change the display resolution automatically."/>
<property name="native resolution" code="NaRe" type="boolean"
description="If true, use the true (retina) resolution of the display. Otherwise, use the percieved resolution."/>
<property name="upscaling filter" code="UpFi" type="qemu scaler"
description="Filter to use when upscaling."/>
<property name="downscaling filter" code="DoFi" type="qemu scaler"
description="Filter to use when downscaling."/>
</record-type>
<enumeration name="qemu scaler" code="QeSc" description="QEMU Scaler.">
<enumerator name="linear" code="QsLi"/>
<enumerator name="nearest" code="QsNe"/>
</enumeration>
<record-type name="qemu argument" code="QeAr" description="QEMU argument configuration.">
<property name="argument string" code="ArSt" type="text"
description="The QEMU argument as a string."/>
<property name="file urls" code="FlUr"
description="Optional URLs associated with this argument.">
<type type="file" list="yes"/>
</property>
</record-type>
<record-type name="apple configuration" code="ApCf" description="Apple virtual machine configuration.">
<property name="name" code="pnam" type="text"
description="Virtual machine name."/>
<property name="icon" code="IcOn" type="text"
description="Virtual machine icon."/>
<property name="notes" code="NoTe" type="text"
description="User-specified notes."/>
<property name="memory" code="MeMy" type="integer"
description="RAM size (in mebibytes)."/>
<property name="cpu cores" code="CpUc" type="integer"
description="Number of CPU cores (0 is the default for this host)."/>
<property name="directory shares" code="DiRs"
description="List of directory share configuration.">
<type type="apple directory share configuration" list="yes"/>
</property>
<property name="drives" code="DrVs"
description="List of drive configuration.">
<type type="apple drive configuration" list="yes"/>
</property>
<property name="network interfaces" code="NtIf"
description="List of network configuration.">
<type type="apple network configuration" list="yes"/>
</property>
<property name="serial ports" code="SrPt"
description="List of serial configuration.">
<type type="apple serial configuration" list="yes"/>
</property>
<property name="displays" code="DiPs"
description="List of display configuration.">
<type type="apple display configuration" list="yes"/>
</property>
<property name="os" code="ApOs" type="operating system"
description="Guest operating system. Only used when creating; defaults to Linux."/>
<property name="macRecoveryIpsw" code="ApIp" type="file"
description="IPSW recovery image used to install macOS. Required when os is macOS."/>
</record-type>
<record-type name="apple directory share configuration" code="ApDs" description="Apple directory share configuration.">
<property name="index" code="pidx" type="integer"
description="The position of the configuration to update. It can be empty to create a new device. Index is invalid after updating the configuration and must be reset to the current position."/>
<property name="read only" code="RdOy" type="boolean" access="r"
description="Is this directory read-only?"/>
</record-type>
<record-type name="apple drive configuration" code="ApEc" description="Apple virtual existing drive configuration.">
<property name="id" code="ID " type="text" access="r"
description="The unique identifier for this drive (if empty, a new drive will be created)."/>
<property name="removable" code="ReMv" type="boolean" access="r"
description="Is this drive removable (cannot be changed after creation)?"/>
<property name="host size" code="HoSz" type="integer" access="r"
description="The size of this drive as seen by the host (in MiB)."/>
<property name="guest size" code="GuSz" type="integer"
description="The size of this drive as seen by the guest (in MiB)."/>
<property name="source" code="SrCe" type="file"
description="An existing file to use as the source image."/>
</record-type>
<record-type name="apple network configuration" code="ApCn" description="Apple virtual network configuration.">
<property name="index" code="pidx" type="integer"
description="The position of the configuration to update. It can be empty to create a new device. Index is invalid after updating the configuration and must be reset to the current position."/>
<property name="mode" code="MoDe" type="apple network mode"
description="This determines how the network device is attached to the host."/>
<property name="address" code="AdDr" type="text"
description="MAC address (formatted as XX:XX:XX:XX:XX:XX, if empty a random address will be genertaed)"/>
<property name="host interface" code="HoIf" type="text"
description="Only used in bridged mode. Specify the interface name to bridge to."/>
</record-type>
<enumeration name="apple network mode" code="ApNm" description="Mode for networking device.">
<enumerator name="shared" code="ShRd" description="NAT based sharing with the host."/>
<enumerator name="nat network" code="NaNw" description="NAT based sharing with the host on a network common to other virtual machines (macOS 26+)."/>
<enumerator name="host" code="HoSt" description="Network shared with the host and other virtual machines with no WAN routing (macOS 26+)."/>
<enumerator name="bridged" code="BrGd" description="Bridged to a host interface."/>
</enumeration>
<record-type name="apple serial configuration" code="ApSn" description="Apple virtual serial configuration.">
<property name="index" code="pidx" type="integer"
description="The position of the configuration to update. It can be empty to create a new device. Index is invalid after updating the configuration and must be reset to the current position."/>
<property name="interface" code="InTf" type="serial interface"
description="The type of serial interface on the host (only PTTY is supported)."/>
</record-type>
<record-type name="apple display configuration" code="AdYc" description="Apple virtual display configuration.">
<property name="id" code="ID " type="text" access="r"
description="The unique identifier for this display (if empty, a new display will be created)."/>
<property name="dynamic resolution" code="DyRe" type="boolean"
description="Dynamic Resolution."/>
</record-type>
</suite>
<suite name="UTM USB Devices Suite" code="UTMu" description="UTM virtual machine USB devices suite. Use this to connect USB devices from the host to the guest.">
<access-group identifier="com.utmapp.UTM.vm-access" />
<class-extension extends="application" description="An application's top level scripting object.">
<element type="usb device" access="r"
description="List of all USB devices currently connected to the host. If there is no running VM with USB sharing supported and enabled, then this will always return an empty list.">
<cocoa key="scriptingUsbDevices"/>
</element>
</class-extension>
<class name="usb device" code="UsBd" description="A host USB device that is shared with the guest." plural="usb devices">
<cocoa class="UTMScriptingUSBDeviceImpl"/>
<property name="id" code="ID " type="integer" access="r"
description="A unique identifier corresponding to the USB bus and port number."/>
<property name="name" code="pnam" type="text" access="r"
description="The name of the USB device."/>
<property name="manufacturer name" code="UsBM" type="text" access="r"
description="The product name described by the iManufacturer descriptor."/>
<property name="product name" code="UsBP" type="text" access="r"
description="The product name described by the iProduct descriptor."/>
<property name="vendor id" code="UsBv" type="integer" access="r"
description="The vendor ID described by the idVendor descriptor."/>
<property name="product id" code="UsBp" type="integer" access="r"
description="The product ID described by the idProduct descriptor."/>
<responds-to command="connect">
<cocoa method="connect:"/>
</responds-to>
<responds-to command="disconnect">
<cocoa method="disconnect:"/>
</responds-to>
</class>
<class-extension extends="virtual machine" description="Virtual machine USB devices.">
<element type="usb device" access="r"
description="List of connected USB devices.">
<cocoa key="connectedUsbDevices"/>
</element>
</class-extension>
<command name="connect" code="UTMuCoNt" description="Connect a USB device to a running VM and remove it from the host.">
<direct-parameter description="The USB device to connect to the VM." type="usb device"/>
<parameter name="to" code="UsBn" description="The virtual machine to connect. The virtual machine must be running. Not all backends support USB sharing.">
<cocoa key="vm"/>
<type type="virtual machine"/>
</parameter>
</command>
<command name="disconnect" code="UTMuDiSc" description="Disconnect a USB device from the guest and re-assign it to the host.">
<direct-parameter description="The USB device to disconnect." type="usb device"/>
</command>
</suite>
<suite name="UTM Registry Suite" code="UTMr" description="UTM virtual machine registry suite. Use this to update virtual machine registry.">
<access-group identifier="com.utmapp.UTM.vm-access" />
<class-extension extends="virtual machine" description="Virtual machine registry.">
<property name="registry" code="ReGs" access="r"
description="The registry of the virtual machine.">
<type type="file" list="yes"/>
</property>
<responds-to command="update registry">
<cocoa method="updateRegistry:"/>
</responds-to>
</class-extension>
<command name="update registry" code="UTMrUpDt" description="Update the registry of the virtual machine.">
<direct-parameter description="Virtual machine to update." type="virtual machine"/>
<parameter name="with" code="UpRg" description="The registry to update the virtual machine. Currently you can only change the shared directory with this!">
<cocoa key="newRegistry"/>
<type type="file" list="yes"/>
</parameter>
</command>
</suite>
<suite name="UTM Input Automation Suite" code="UTMi" description="UTM virtual machine input automation suite. Only supported on QEMU backend.">
<access-group identifier="com.utmapp.UTM.vm-access" />
<class-extension extends="virtual machine" description="Input automation.">
<responds-to command="input scan code">
<cocoa method="sendScanCode:"/>
</responds-to>
<responds-to command="input keystroke">
<cocoa method="sendKeystroke:"/>
</responds-to>
<responds-to command="input mouse click">
<cocoa method="sendMouseClick:"/>
</responds-to>
</class-extension>
<command name="input scan code" code="UTMiInSc" description="Send raw PC AT scan codes. Only supported on QEMU backend.">
<direct-parameter description="Virtual machine to send scan code to." type="virtual machine"/>
<parameter name="codes" code="ScCd" description="List of PC AT scan codes.">
<type type="integer" list="yes"/>
<cocoa key="codes"/>
</parameter>
</command>
<enumeration name="modifier key" code="MoKy" description="Modifier key to send with keystroke.">
<enumerator name="caps lock" code="MoCl" description="Caps Lock (⇪)"/>
<enumerator name="shift" code="MoSh" description="Shift (⇧)"/>
<enumerator name="control" code="MoCt" description="Control (⌃)"/>
<enumerator name="option" code="MoOp" description="Option (⌥)"/>
<enumerator name="command" code="MoCm" description="Command (⌘)"/>
<enumerator name="escape" code="MoEs" description="Escape (⎋)"/>
</enumeration>
<command name="input keystroke" code="UTMiInKs" description="Send text as a sequence of keystrokes to the virtual machine. Only supported on QEMU backend.">
<direct-parameter description="Virtual machine to send keystrokes to." type="virtual machine"/>
<parameter name="text" code="InTx" description="ASCII characters to send as a sequence." type="text">
<cocoa key="keystrokes"/>
</parameter>
<parameter name="with modifiers" code="KsMd" description="List of modifier keys to hold down while sending key sequence." optional="yes">
<type type="modifier key" list="yes"/>
<cocoa key="modifiers"/>
</parameter>
</command>
<enumeration name="mouse button" code="MsBt" description="Mouse button.">
<enumerator name="left" code="MsLf" description="Left Click"/>
<enumerator name="right" code="MsRt" description="Right Click"/>
<enumerator name="middle" code="MsMd" description="Middle Click"/>
</enumeration>
<command name="input mouse click" code="UTMiInMc" description="Send a mouse position and click to the virtual machine. Only supported on QEMU backend.">
<direct-parameter description="Virtual machine to send scan code to." type="virtual machine"/>
<parameter name="at" code="McAt" description="X-Y coordinate of the absolute position on screen to perform the click. Must be a list of two numbers.">
<type type="integer" list="yes"/>
<cocoa key="coordinate"/>
</parameter>
<parameter name="to" code="McTo" description="Which monitor to target (starting at 1). If omitted, the first monitor will be used." type="integer" optional="yes">
<cocoa key="monitor"/>
</parameter>
<parameter name="with mouse button" code="McBt" description="Mouse button to click. If omitted, a left click will be used." type="mouse button" optional="yes">
<cocoa key="button"/>
</parameter>
</command>
</suite>
</dictionary>