# NucleicVMAgent

The **native in-guest automation agent** for Nucleic's macOS VMs — design and rationale in
[docs/MACOS_VM_NATIVE_AGENT.md](../../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

```sh
# 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`.
