I’m building a menu bar app for macOS. It works perfectly on my Mac. Now I need to know if it works on a clean macOS: without my settings, without my permissions, without my data. A user installing it from scratch.

How do you test that? You need a virtual machine.

“Easy,” I thought. “I have UTM installed. I’ll open the wizard, create a macOS VM, and we’re good to go.”

It wasn’t going to be that easy.

UTM: beautiful but untameable

UTM is an excellent application. Polished interface, support for macOS as a guest on Apple Silicon, full screen, shared clipboard. For manual use, it’s great.

The problem comes when you try to automate it.

UTM has a CLI called utmctl. It can list VMs, start them, stop them, clone them. What it can’t do is create a VM. And for macOS guest, not even UTM’s AppleScript allows creating them — the operating system field is hardcoded to Linux.

In plain language: if you want a macOS VM in UTM, you create it manually through the wizard. Every time. With its clicks, its IPSW download (the macOS installation image for Apple Silicon — the equivalent of a traditional ISO, but packaged by Apple), its installation wait time.

For a dev who needs to spin up and destroy VMs as part of a QA workflow, that’s a pain in the ass.

Tart: macOS VMs for the rest of us

Tart is what happens when someone designs a virtualization tool thinking about developers instead of end users.

It uses exactly the same Apple Virtualization.framework that UTM does. Same technology, same capabilities, same native speed. The difference is the interface: Tart is CLI-first.

1
brew install cirruslabs/cli/tart

That’s it. No configuration GUI, no wizard. A binary in your PATH.

One command to rule them all

Create a macOS VM with the latest available version:

1
tart create my-vm --from-ipsw latest

That’s all. latest tells Tart “give me the latest version of macOS this Mac supports.” Tart queries Apple’s API, downloads the IPSW (~15 GB — yes, macOS is hefty), creates the virtual disk, installs the operating system and leaves you with a VM ready to boot. Go grab a latte, because it takes a while — but you don’t need to touch anything.

Start the VM:

1
tart run my-vm

A window opens with the macOS desktop. Mouse, keyboard, screen. Exactly like UTM, but launched from a tart run.

Shared folder: the detail that makes the difference

This is where Tart won me over. I need to copy my app from the host Mac to the VM. In UTM you have to manually configure VirtioFS, mount it from the guest terminal, and pray that the config.plist doesn’t get corrupted (there are known bugs).

In Tart:

1
tart run my-vm --dir=shared:~/code/tokamak/build

Inside the VM, the folder appears at /Volumes/My Shared Files/shared. You drag the app to /Applications and you’re done. No configuration, no mounting.

My actual QA workflow

This is what I do to test my app on a clean macOS:

1
2
3
4
5
6
7
8
# Create the VM (only the first time)
tart create tokamak-qa --from-ipsw latest --disk-size 50

# Build the app
cd ~/code/tokamak && make build

# Start the VM with the build shared
tart run tokamak-qa --dir=build:~/code/tokamak/build/Build/Products/Debug

Inside the VM:

  1. Open /Volumes/My Shared Files/build/
  2. Drag Tokamak.app to /Applications/
  3. Run and verify: login, permissions, sandbox, menu bar, notifications

If I need to start from scratch (test the first launch experience):

1
2
tart delete tokamak-qa
tart create tokamak-qa --from-ipsw latest --disk-size 50

Destroy and recreate. No questions, no confirmations, no wizard.

Configure resources

By default Tart assigns reasonable resources, but you can adjust them:

1
2
3
4
5
# 4 cores, 8 GB RAM
tart set my-vm --cpu 4 --memory 8192

# Resize disk
tart set my-vm --disk-size 80

What Tart doesn’t have (and why it doesn’t matter)

It doesn’t have a management GUI with thumbnails of each VM. It doesn’t have drag and drop for ISOs. It doesn’t have a pretty “New VM” button.

If what you need is a desktop app to manage VMs, use UTM. It’s fantastic for that.

But if what you need is to test your app on a clean macOS, destroy the VM, recreate it, share a folder, and do all that from a script or a Makefile… UTM can’t. Tart can.

The complete recipe

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Install
brew install cirruslabs/cli/tart

# Create macOS VM (downloads ~15 GB, takes ~20 min)
tart create test-vm --from-ipsw latest --disk-size 50

# Start with shared folder
tart run test-vm --dir=app:~/my-project/build

# Other useful commands
tart list                    # Existing VMs
tart stop test-vm            # Stop
tart clone test-vm copy-vm   # Clone (fast)
tart delete test-vm          # Delete
tart ip test-vm              # IP for SSH

The documentation fits in a README. The learning curve fits in a latte. If you’re developing for macOS and not using Tart, you’re making things harder than necessary.