NucleicVMAgent
The native in-guest automation agent for Nucleic's macOS VMs — design and rationale in docs/MACOS_VM_NATIVE_AGENT.md. It runs inside the guest as a LaunchAgent in the auto-login Aqua session, listens on vsock port 2035, and executes NDJSON ops with Apple's frameworks directly:
- AXUIElement — semantic observe + control (
ax_dump,ax_action,ax_set_value,ax_focus,ax_element_at). Framebuffer-independent by-identity control: drive the UI without pixels, and keep working even when screenshots are blank or unavailable. - ScreenCaptureKit — in-process
screenshot. - CGEvent — raw
click/move/drag/type/key/scroll(a real wheel event).
A separate SwiftPM package from the main Nucleic one: the host app's floor is macOS 26, but this binary runs INSIDE the guest (supported guest is macOS 27). The package keeps a low platform floor so the same binary builds against older SDKs; SwiftPM has no per-target platform floors.
Build & install
# On the host (needs Swift; sign stably or TCC grants break on rebuild):
NUCLEIC_VMAGENT_SIGN_IDENTITY="Developer ID Application: …" ../../scripts/build-vm-agent.sh
# → dist/NucleicVMAgent.app + dist/xyz.blakeslee.nucleic.vmagent.plist
# Stage dist/* next to scripts/provision-macos-guest.sh inside the guest and run the provisioner —
# Phase 7d installs the app, the LaunchAgent, and the three TCC grants (Accessibility, PostEvent,
# ScreenCapture). On the supported macOS 27 build these grants are written automatically.
The host side (MacVMAgentClient in Sources/NucleicCore/MacVM/) probes the agent with a vsock
ping per VM boot and transparently falls back to the SSH + cliclick path when it's absent — the
agent is strictly additive. Wire constants are mirrored between VMAgentCore.AgentWire (here) and
MacVMAgentWire (host); keep them in lockstep.
Agent log inside the guest: /tmp/nucleic-vmagent.log.