72 Commits
Author SHA1 Message Date
osy 100701eb8b Merge pull request #7902 from utmapp/feature/apple-audio-input
apple: allow sound input and output to be enabled separately
2026-09-22 18:51:24 -05:00
osy e50840634f apple: allow sound input and output to be enabled separately
Since the input and output streams were merged into a single
virtio-sound device, playing audio in the guest also opens the host
microphone, which switches Bluetooth headphones into headset mode.
Replace the "Enable Sound" toggle with a choice of input only, output
only, or both so users can avoid opening the microphone.

The existing "Audio" key keeps meaning output and a new "AudioInput"
key is added. When "AudioInput" is missing it defaults to "Audio", so
existing configs keep both streams and new configs still load on older
versions of UTM.

Resolves #7875

Assisted-by: Claude:claude-opus-5-5
2026-09-22 15:03:12 -05:00
osy adb43bffbb scripting: close the VM's window when updating its configuration
A VM's window is kept after it stops and run(vm:) reuses it as is. The Edit
button closes it before opening the settings, but AppleScript's update
configuration did not. If the displays were removed that way, the next start
got the old display window, which looks up the now missing display 0 and
crashes with an index out of range.

Close the window before updating the configuration, like the Edit button does,
so the next start creates the right kind of window.

Resolves #7882

Assisted-by: Claude:claude-opus-5-5
2026-09-22 14:11:18 -05:00
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
osy 0086417b97 snapshots: manage QEMU snapshots through a backend
Snapshots were read straight out of the QEMU images by the scripting
commands, which only worked while the VM was off and knew nothing beyond
the tags in the image.

Put a backend behind the operations instead. Which one is chosen depends on
whether the VM is running, and each says what it can do in that state:

- A running VM goes through the QEMU monitor, which saves and loads the
  whole machine along with the disks.
- A VM that is off goes through qemu-img, which can only save and revert
  disk contents. Nothing may touch the images while QEMU has them open, so
  a snapshot of disks alone is left alone until the VM stops.

Either way a snapshot spans every writable image, the UEFI variable store
included, because QEMU refuses to load one that any of them is missing. A
snapshot that some of them lack, such as one taken before a drive was added,
is kept but cannot be restored, which is not the same as its state being
gone: reverting only some of the drives would leave them at different points
in time. Reclaiming space rebuilds an image without its snapshots, so it is
refused while there are any.

UTMSnapshotService sits above the backend and keeps the manifest and the
stored state consistent: it marks entries whose state has disappeared when
an operation fails, and the first time a VM is opened it adopts whatever
snapshots are already in the images so that snapshots taken by other tools
are not lost. Both wait until the VM is stopped, because a running QEMU
lists the snapshots of every drive together, removable ones included.

Suspending is folded into the same mechanism. A VM now suspends to a
snapshot of its own rather than always the same name, so a suspended state
can be kept as a snapshot without copying it, and restoring a snapshot
makes the VM resume from it. The state is deleted once nothing refers to
it, where it used to be left behind in the image. One that cannot be deleted
right away stays listed in the manifest and is tried again the next time.

Assisted-by: Claude:claude-fable-5-1
Assisted-by: Claude:claude-opus-5
2026-09-22 10:57:30 -05:00
osy 602d8fc615 scripting: provision macOS guests on first boot
macOS 27 can create the guest's user account, turn on automatic login and
Remote Login without going through Setup Assistant, which lets CI and other
automation get a ready-to-use macOS VM. The guest only reads these options
on the first boot after macOS is installed and they include a password, so
they are passed as a parameter to a single start and are never saved to the
configuration or the registry.

This is only exposed to AppleScript (`start ... provisioning {...}`) and
utmctl (`start --provision-*`) because most users will never need it. utmctl
can read the password from standard input to keep it out of the process
list. Requests that cannot be honoured (not a macOS guest, host older than
macOS 27, install still pending, saved state, recovery mode, invalid account)
fail before the VM starts so the first boot is not used up.

UTMScripting.swift has only the regenerated `start` declaration. The rest of
the current bridge-gen.sh output is unrelated to this change.

Assisted-by: Claude:claude-fable-5-1
2026-09-19 22:05:10 -05:00
osy fa30b642f9 Merge pull request #7863 from meisenbarth/scripting-install-command
scripting: add an install command for macOS guests
2026-09-19 10:44:34 -05:00
Marc Eisenbarth e25397a431 scripting: allow creating macOS VMs with the Apple backend
createAppleVirtualMachine hardcodes the guest OS:

    config.system.boot = try UTMAppleConfigurationBoot(for: .linux)

Every other field in the record is already honoured via
updateConfiguration(from:). The OS is the only thing a script cannot ask
for, and UTMAppleConfigurationBoot.init(for:) already accepts one.

This reads `os` from the record (as an AEKeyword, the same as `backend`;
sdef enumerations do not arrive as strings), defaulting to .linux so
existing scripts are unaffected. When the OS is macOS it requires and sets
`macRecoveryIpsw`, since without it the VM has nothing to restore from.

It also derives macPlatform from the caller's IPSW. fillVZConfiguration
throws platformUnsupported for a macOS guest with no platform, so setting
the OS and IPSW alone produces a VM that is created and then fails to
start with "This virtual machine cannot run on the current host machine."
The hardware model comes from the caller's own image via
VZMacOSRestoreImage.image(from:) rather than fetchLatestSupported: the
caller named a specific IPSW and the model must match it. An IPSW this
Mac cannot run fails with the same error the wizard shows.

And it gives a macOS guest a display, audio, keyboard and pointer by
default. The scripted create clears `displays` (the headless-by-default
convention that suits a Linux guest with a serial console), and
fillVZConfiguration only builds a graphics device when `displays` is
non-empty. For macOS that produced a guest with no framebuffer: it booted
to 0% CPU and UTMData.run chose a headless session because there was
nothing to show. The defaults mirror VMWizardState for a new macOS VM
(1920x1200, audio, generic keyboard, trackpad on Ventura+). A caller may
still override `displays`, but the input and audio devices cannot be set
from a script, so they are always enabled for a macOS guest.

The sdef gains an `operating system` enumeration (linux / macOS) and a
`macRecoveryIpsw` file property. The property name matches the existing
macRecoveryIpswURL and the "IPSW Install Image" label in
VMConfigAppleBootView.

UTMScripting.swift: the UTMScriptingOperatingSystem enum matches the
output of bridge-gen.sh for this sdef change.

Verified against main on Xcode 26.6 / Apple Silicon: a macOS 26.6.2 VM
created from AppleScript with OperatingSystem=macOS, a HardwareModel,
MachineIdentifier, AuxiliaryStoragePath and a 1920x1200 Display in the
resulting config.plist, and booted to Setup Assistant in a UTM display
window.

Refs #6092

Assisted-by: Claude:claude-opus-5
2026-09-19 10:09:24 -05:00
osy 5d395abfc8 scripting: return from install before the Apple Event times out
A macOS install takes several minutes, well past the default two minute
Apple Event timeout. A plain `install` therefore failed with -1712 while
the installation kept running, and a script reacting to that error by
retrying or starting the VM would race the install.

`install` now returns as soon as the installation starts, and the new
`query install` verb reports whether it is still running and how far it
has progressed, or raises the error if it failed. The installation only
counts as finished once the VM has stopped by itself, so the VM can be
started right away.

Other verbs fail with a clear error while an installation started from
a script is in progress. This includes `start`, which would otherwise
open a window that asks to install macOS again. As in the GUI, `stop`
cancels the installation.

Assisted-by: Claude:claude-opus-5
2026-09-19 09:49:15 -05:00
Marc Eisenbarth 8d04b96c23 scripting: add an install command for macOS guests
VMDisplayAppleWindowController.windowDidLoad shows a confirmation sheet
before calling requestInstallVM, so a macOS install cannot be driven from
a script without someone clicking OK.

This does not remove the sheet. It guards a genuinely destructive action
(it erases the primary drive) and a GUI user who opens a VM that happens
to carry an IPSW should keep being asked. It is also structurally
unavailable to a script: showConfirmAlert calls
beginSheetModal(for: window!), so it needs a window, and the scripted
`start` verb calls data.run(...), which loads the window controller and
raises the sheet in the first place.

So this adds a separate `install` verb that goes straight to
installVM(with:) and never opens a window. The confirmation moves rather
than disappearing: asking for `install` is the confirmation, which is why
the sdef entry says DESTRUCTIVE in as many words. This matches the
CONTRIBUTING.md guidance about putting things most users do not need into
the scripting interface rather than the UI.

It also clears the IPSW on success, as the GUI does in
didCompleteInstallation. That clearing lives in the window controller's
delegate callback, and a scripted install has no window, so without it
the IPSW outlives the install and the next `start` that does open a
display window asks "Would you like to install macOS?" over a guest that
is already installed. Measured before the fix: the registry still held
the IPSW after a completed scripted install.

Two guards, because installVM returns silently when the VM is not
stopped and calling it unguarded would report success having done
nothing: a VM with no IPSW configured, and a VM that is not stopped, each
fail with an error naming the cause.

Verified against main on Xcode 26.6 / Apple Silicon: no confirmation
sheet at any point, a macOS 26.6.2 install run to completion (21 GB,
framework returned success), the IPSW cleared from the registry
afterwards, and a subsequent `start` opening a display window with no
reinstall prompt and the guest booting to Setup Assistant.

UTMScripting.swift gains the install() method that bridge-gen.sh
generates for this sdef change.

Refs #6092

Assisted-by: Claude:claude-opus-5
2026-09-19 09:34:56 -05:00
osy a3242448ca Merge pull request #7856 from atkinsam/fix/apple-scripting-shared-dir
scripting: fix shared directory access for Apple Virtualization VMs
2026-09-19 09:02:23 -05:00
osy 47eadda150 apple: make the vmnet modes predictable and simpler
Follow-up to the vmnet networking modes:

- Rename "Shared Network (VM to VM)" to "NAT Network" (config value
  "NATNetwork", scripting term "nat network") so the picker does not offer
  two "Shared" modes that differ only by a suffix.
- Request a fixed subnet per mode outside of the ranges vmnet hands out by
  default. Those ranges are also used by NAT attachments and QEMU, so guest
  addresses depended on what else was running whenever the network was
  (re)created. Fall back to a vmnet chosen subnet when ours is taken.
- Show the mode description with DetailedSection. The bare Text row widened
  the form and clipped the labels and controls in the settings window.
- Only require macOS 26 when a network is actually created, so a VM using
  one of these modes can still be edited and saved on older hosts.
- Do not apply locale digit grouping to the vmnet error code.
- Fold the validation flag into the existing one that skipped drives and
  leave the device unattached instead of using a NAT placeholder, remove
  the unused reverse mapping, key the networks by vmnet_mode_t, and isolate
  the manager to the main actor in place of a lock with no concurrent users.

Use .1 as the host-side address within each preferred /24. As reproduced
in PR #7865, vmnet accepts .0 during network creation but the interface
fails later at startup.

Assisted-by: Claude:claude-fable-5-1
Assisted-by: ChatGPT:GPT-6-Astra-Pro
2026-09-18 20:43:49 -04:00
lovon-spec 31b431f8b5 apple: let virtual machines connect to each other
Apple Virtualization's existing Shared Network uses a separate NAT
attachment per VM, so guests cannot use it to reach each other. macOS 26
adds VZVmnetNetworkDeviceAttachment, which lets multiple VMs attach to the
same process-owned vmnet network.

Add two macOS 26+ modes:

- "Shared Network (VM to VM)": guests share a NAT-backed vmnet network and
  can reach each other, the host, and external networks.
- "Host Only": guests share a host-only vmnet network and can reach each
  other and the host without external routing.

UTMAppleVmnetNetworkManager keeps a weak attachment cache per mode while
Virtualization configuration and runtime objects own the attachment and its
native network. The network therefore follows the actual VZ object lifetime
rather than UTM's presentation state, including failure paths where a VZ VM
can remain alive after UTM reports it stopped. Configuration validation uses
a side-effect-free placeholder so saving a VM does not create a live vmnet
network.

Hide both modes before macOS 26 and add matching scripting enumerators and
round-trip parsing.

Resolves #6975.
Related to #7418 and #7380.

Assisted-by: Claude:claude-fable-5-1
Assisted-by: ChatGPT:GPT-6-Pro
Assisted-by: ChatGPT:GPT-5.6-Sol
2026-09-18 13:26:24 +02:00
osy f6adf300e0 scripting: support USB devices on Apple VMs
The `connect` and `disconnect` USB commands and the application's list of USB
devices only worked with QEMU VMs because they were tied to CocoaSpice
objects. Now that Apple Virtualization VMs support USB passthrough on macOS
27, the scripting object wraps a small protocol adopted by both backends and
dispatches on the type of the target VM. The QEMU list is preferred when a
QEMU VM with USB sharing is running, otherwise the AccessoryAccess list is
returned so scripts work the same for both backends.

Assisted-by: Claude:claude-fable-5-1
2026-09-17 22:15:30 +02:00
Sam Atkinson f2c3ecaedc scripting: fix shared directory access for Apple Virtualization VMs
update registry falls back to a disconnected UTMProcess for non-QEMU
backends, which mints a non-security-scoped bookmark wrapped in an
unresolved URL; the resulting entry can never be accessed, so the VM
fails to start with "Cannot access resource". Build a real
security-scoped bookmark directly for the Apple backend instead, and
explicitly resync config from the registry since there is no QEMU
process to trigger it.

Assisted-by: Claude:claude-sonnet-5
2026-08-25 15:12:54 -04:00
Naveenraj M a11e968084 snapshots: expose QEMU full-VM snapshots
Expose named create, list, restore, and delete operations through AppleScript and utmctl so automation can manage QEMU full-VM snapshots. QEMU image metadata remains the source of truth, the internal suspend snapshot stays hidden and reserved, and Apple virtualization reports the feature as unsupported until it can preserve equivalent VM state reliably.

Assisted-by: Codex:gpt-5
2026-08-20 13:26:29 -07:00
osy 81db1d4cc3 Merge pull request #7710 from GregOriol/feat/expose-vlan-network-properties
Expose VLAN guest/DHCP addresses on AppleScript network settings
2026-07-31 22:44:48 -07:00
Greg ORIOL c8da6919ff Add an AppleScript command to reload machine configuration from disk 2026-05-12 22:47:22 +02:00
Greg ORIOL 47c5638356 Expose VLAN guest/DHCP addresses on the network settings 2026-05-12 22:05:42 +02:00
TronickDev 646327cc40 Refactor same function to improve device matching
Fixed USB function which is used via utmctl that connection and disconnextion of USB devices from cli is working again (tested with local build).
2026-05-03 23:15:38 +02:00
osy 89ef5e2a9b scripting: fix some typos
Resolves #7687
2026-05-03 13:28:22 -07:00
Victor Muryn c8450702d1 Added ability to get ip for AppleVirtualization machines (#7643)
* added ability to get ip for AppleVirt machines

* fixed comments
2026-05-03 10:51:01 -07:00
osy 03db3f8c67 scripting: fixed broken scripting due to name collision
Fixes #7360
2025-08-19 14:25:19 -07:00
osy d5c224b88d utmctl: add version command
For the scripting backend, we have to use a hack. The existing property
`version` cannot be accessed through App Sandbox because the inherited
suite does not define an access-group. We create a new property that is
accessible by the com.utmapp.UTM.vm-access access group.

Resolves #7350
2025-08-17 20:22:16 -07:00
osy fa8daa1b77 display(macOS): fix simultaneous mouse buttons
Fixes #7068
2025-08-16 22:46:17 -07:00
osy a2dda805d9 scripting: more gracefully handle invalid AEKeyword 2025-08-15 10:10:18 -07:00
osy 311654dc4b scripting: add input automation suite
Resolves #6462
2025-08-15 10:06:06 -07:00
osy 7ec85d56a9 scripting: replace uuid with index for displays
We do not have persistent UUIDs for displays and so every time a new
config object is constructed, the UUIDs will change. We should
use index instead just like with serial and networking options.

Fixes #7145
2025-07-24 11:02:55 -07:00
user d5402b7735 utmctl: support booting into recovery mode 2025-04-16 12:16:49 +02:00
osy 2b86f67d99 Merge pull request #6978 from naveenrajm7/script-display
scripting: expose display config
2025-04-07 16:06:09 -07:00
osy 3dfcddcc79 Merge pull request #6977 from naveenrajm7/script-sandbox-path
scripting : add vm registry suite
2025-04-07 16:05:44 -07:00
Naveenraj M 77a36173cc scripting: expose display config
qemu display
- All fields , except vga ram is exposed
apple display
- only dynamic resolution property is exposed.
- From GUI , the height, width and pixel of resolution is in pre-defined ratio as hence not exposed.

Both display will have id, which can be used to track and ditach the displays.
2025-01-19 02:17:17 -07:00
Naveenraj M f57fe2ef64 scripting: add vm resgistry suite
The registry suite is used to read and update vm registry.
All configs saved to disk is exposed by Configuration suite,
similarly those that are not saved to disk are stored in RegistryEntry
 will now be exposed by Registry suite.
  - UTMScriptingRegistryEntryImpl will control what will be exposed from RegistryEntry to scripting bridge, currently only shared directory is exposed in the form of [URL]
  - expose UTMQemuVirtualMachine.system as public to be used in Scripting
  - Add UTMRegistryEntry.appendSharedDirectory to support multiple directory shares.
2025-01-18 16:55:32 -07:00
Naveenraj M f0cf825c22 scripting: add file urls to qemu additional arguments
* file urls is a list of file
* file urls are not saved to the disk (config.plist)
* QEMU launcher looks at file urls of args to collect required resources
* QEMU uses file URLs to access its corresponding bookmark
* The permissions of these urls is not handled as part of config update (ConfigImpl) , they should be handled at VM level(VMImpl) to update registryEntry of each VM
2025-01-17 17:30:50 -07:00
Naveenraj M 26fe0de354 scripting: expose icon in config
* Allows to get/set built-in icons
iconURL is URL in UTMConfig, but stored as string in config.plist, same is done for scripting interface.
2024-12-22 23:31:12 -07:00
osy 8a35d037bc Merge pull request #6741 from naveenrajm7/qemu-args
scripting: add qemu additional arguments
2024-11-21 09:39:24 -08:00
osy 6093498b44 utmctl: remove Export command because it cannot work in sandbox 2024-11-21 09:37:55 -08:00
Naveenraj M f101cceca0 scripting: drop file urls from qemu arguments
If file urls were be supported, handle file permissions before use (app sandbox)
2024-11-20 20:29:12 -07:00
osy f11cda7a3b Merge branch 'main' into utm-import 2024-11-20 11:32:16 -08:00
Naveenraj M 7c8f656592 scripting: change property name
Avoid using reserved keyword in AppleScript as property name
2024-10-12 22:03:57 -06:00
Naveenraj M a4a79fea7c scripting: add qemu additional arguments
read and update qemu additional argument of vm config
2024-10-12 14:08:49 -06:00
Naveenraj M bfecac3ca3 scripting: add import command
import new vm from a file
2024-10-09 21:13:34 -06:00
Naveenraj M 05065625bf scripting: add export command 2024-10-04 01:33:50 -06:00
osy 2724075c57 scripting: fix missing retain on scripted object
Fixes #5963
2024-03-30 17:38:34 -07:00
osy 8d7b51b878 utmctl: implement USB commands
Resolves #5157
2023-09-04 20:49:43 -07:00
osy 1193b80725 scripting: add support for USB operations 2023-09-04 19:39:50 -07:00
osy e65578fe07 Merge pull request #5357 from MMP0/patch-1
Fix string format + Update Japanese localization
2023-07-03 09:16:56 -05:00
osy 37991d246f vm: rewrite UTMVirtualMachine in Swift 2023-06-28 19:45:05 -05:00
osy d498239b38 data: refactor UTMVirtualMachine to VMData for use in Views
This replaces the functionality of UTMWrappedVirtualMachine and moves some of
the presentation logic from UTMVirtualMachine.
2023-06-26 23:28:18 -05:00
osy 03d200422f manager: factor out QEMUKit as a separate project 2023-06-25 08:43:05 -05:00