A native QEMU Guest Agent for macOS and OS X virtual machines. The missing guest agent for Mac — enables Proxmox VE, libvirt, plain QEMU, and UTM to manage macOS guests through the standard QGA protocol.
45 commands, real filesystem freeze, zero dependencies. Supports Mac OS X 10.4 Tiger through macOS 26 Tahoe. Works as both a macOS guest agent and an OS X guest agent for legacy VMs.
1. On the PVE host — enable the guest agent:
qm set <vmid> --agent enabled=1,type=isa
qm stop <vmid> && sleep 5 && qm start <vmid>Why
type=isa? As of v2.5.0 the agent supports ISA serial only; VirtIO transport was removed. macOS guests run either under Apple's Virtualization.framework (UTM Virtualize,vz_run, anythingVZVirtualMachine-backed) — where Apple's own 18-commandAppleQEMUGuestAgentclaims the VirtIO console channel — or under plain QEMU/KVM (Proxmox, libvirt, raw QEMU, UTM Emulate; typically OpenCore-booted) where Apple's agent never launches but VirtIO would still let an image silently start behaving differently if it ever moved between host classes. Restricting to ISA serial gives one transport, one install, one launchd config, and one channel-detection list everywhere —Apple16X50Serial.kexthas shipped on every macOS from 10.4 Tiger onwards with an identical PCI class match, so this is universally satisfiable. See docs/COMPATIBILITY.md for the full evidence and CHANGELOG v2.5.0 BREAKING for the v2.4.x → v2.5.0 migration.
2. In the macOS VM:
# Download the universal binary — one slice (i386 / x86_64 / arm64) loads at runtime.
# Covers macOS 10.4 Tiger through 26 Tahoe.
# Note: on Tiger / Leopard / older Snow Leopard guests, the VM's TLS stack
# usually cannot reach GitHub directly. Download on a modern machine and
# transfer the file (scp / shared folder / USB).
curl -fLO https://github.com/mav2287/mac-guest-agent/releases/latest/download/mac-guest-agent
# Install
sudo mv mac-guest-agent /usr/local/bin/
sudo chmod +x /usr/local/bin/mac-guest-agent
sudo /usr/local/bin/mac-guest-agent --install3. Verify:
# From PVE host
qm agent <vmid> ping
qm agent <vmid> get-osinfo
# From inside VM
sudo mac-guest-agent --self-testThe agent communicates via an ISA serial port (16550 UART) using Apple's built-in Apple16X50Serial.kext driver, present on every macOS since 10.4. No custom kexts, no SIP changes, no code signing.
Note: macOS Big Sur and newer ship Apple's own
AppleQEMUGuestAgent(18 commands, no filesystem freeze). It only launches on Apple Virtualization.framework hosts — its IOKit match (AppleVirtIOAgentDevice) is set by theapplevirtio.consoledriver, which doesn't load under QEMU/OpenCore — so on Proxmox the VirtIO channel is actually free. We still default to ISA for symmetry across both host classes (see the Quick Start callout for the trade-off). Our agent provides 45 commands plus a real per-filesystem freeze dispatch — see docs/design/FREEZE_SEMANTICS.md for what "freeze" actually does perf_fstypename.
Single download: mac-guest-agent (i386 + x86_64 + arm64 in one tri-fat Mach-O, covers macOS 10.4 Tiger through 26 Tahoe). dyld picks the right slice at load time. (v2.5.0 published this as mac-guest-agent-darwin-universal for one day; v2.5.1+ drops the suffix.)
ISA serial driver (Apple16X50Serial.kext) verified present with identical PCI class match on every macOS from 10.4 Tiger (2005) through 26.3 Tahoe (2026). See the compatibility matrix for per-version evidence.
Tiger / Leopard (10.4 / 10.5):
/usr/local/binis not in the default shell PATH. Invoke the binary by its absolute path (sudo /usr/local/bin/mac-guest-agent ...) or add it to PATH for the session:export PATH=/usr/local/bin:$PATH. The LaunchDaemon itself uses the absolute path and is unaffected.
Open an issue at https://github.com/mav2287/mac-guest-agent/issues/new with as much of the following as you can collect. Items 1-3 work even when the binary won't launch (dyld rejection); items 4-6 require the binary to start successfully.
Loader-safe (no execution needed):
sw_vers— macOS version, buildfile /usr/local/bin/mac-guest-agent— confirms it's a Mach-O fat binarylipo -info /usr/local/bin/mac-guest-agent— shows the slice list
If the binary starts:
mac-guest-agent --versionmac-guest-agent --self-test-json— pipe to a file orgrep selected_archdirectly (do NOT pipe throughpython -m json.toolon Tiger/Leopard — those versions lack a reliable stdlibjsonmodule)tail -50 /var/log/mac-guest-agent.log
The universal binary is the supported install path; if it doesn't load on your specific host configuration we want to fix it, not work around it.
sudo launchctl list com.macos.guest-agent # Status
sudo launchctl start com.macos.guest-agent # Start
sudo launchctl stop com.macos.guest-agent # Stop
tail -f /var/log/mac-guest-agent.log # Logs
sudo mac-guest-agent --uninstall # Removemake build # Current architecture (no SDK needed)
make build-arm64 # Apple Silicon (11.0+, no SDK needed)
make test # Run all testsThe legacy slices (i386 for 10.4+, x86_64 for 10.6+) require the macOS 10.13
SDK because modern Xcode SDKs no longer expose pre-10.7 deployment targets.
Download it once, then pass it to make:
curl -fL -o /tmp/sdk.tar.xz \
https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.13.sdk.tar.xz
# SHA256 1d2984acab2900c73d076fbd40750035359ee1abe1a6c61eafcd218f68923a5a
tar xf /tmp/sdk.tar.xz -C /tmp
make build-i386 LEGACY_SDK=/tmp/MacOSX10.13.sdk # 10.4+ (32-bit)
make build-x86_64 LEGACY_SDK=/tmp/MacOSX10.13.sdk # 10.6+ (64-bit)
make build-universal LEGACY_SDK=/tmp/MacOSX10.13.sdk # tri-fat (release shape)The legacy slices also depend on Apple's ld-classic linker (-Wl,-ld_classic
in the Makefile) to honor -mmacosx-version-min for entry-point selection;
the default ld-prime hardcodes LC_MAIN on x86_64 and produces binaries
that 10.6/10.7 dyld cannot load (issue #4). See .github/workflows/build.yml
for the full toolchain story.
| Guide | Description |
|---|---|
| Proxmox VE | VM settings, backup config, TRIM, security profiles, troubleshooting |
| libvirt / virt-manager | Domain XML, virsh commands, quiesced snapshots, troubleshooting |
| UTM | Local macOS VM automation, utmctl integration, CI/CD workflows |
| All Platforms | Plain QEMU setup, transport priority |
| Commands | All 45 commands with status, Linux parity, privilege requirements |
| Compatibility | Support tiers, kext timeline, verification evidence per version |
| Backup & Freeze | Filesystem freeze, APFS snapshots, hook scripts, TRIM |
| Freeze Semantics | What "freeze" actually does per f_fstypename; divergences from upstream QGA |
| Security | Trust model, recommended profiles, freeze-state restrictions |
| Architecture | Data flow, protocol spec, macOS API usage |
| CLI Reference | All flags, config file format, examples |
| Changelog | Release history |
| Contributing | Build, style, testing guidelines |
MIT