# nucleic-linux-agent

The in-guest control agent for Nucleic **Linux** VMs — the counterpart to `guest/NucleicVMAgent`
(the macOS-guest agent). Where the macOS agent is a Swift/AppKit app doing Accessibility +
ScreenCaptureKit + CGEvent, a Linux guest needs none of that: computer-use (screen capture +
mouse/keyboard) runs entirely **host-side** through the guest's virtio-gpu framebuffer and USB HID.
So this agent only carries the two ops the host reaches *into* the guest for:

- **`ping`** — capability/readiness handshake (protocol version + a synthetic display).
- **`exec`** — the streaming shell-exec sub-protocol the host's `MacVMExecChannel` speaks.

## Transport / protocol

NDJSON over `AF_VSOCK` port **2035** — one JSON request object per line, one JSON reply per line. This
mirrors `VMAgentCore.AgentWire` / `MacVMAgentWire` (host side) byte-for-byte; see
`docs/MACOS_VM_NATIVE_AGENT.md` §3–§4 and `docs/LINUX_VM.md`. Keep the port/version/frame keys in
lockstep with those.

`exec` takes over its connection for the life of the command (bidirectional base64 frames: `o`/`e`/`x`
guest→host, `i`/`eof`/`sig` host→guest). The host opens a dedicated connection per exec.

## Build

```sh
./build.sh            # → build/nucleic-linux-agent (static arm64 preferred)
```

Dependency-free C so it links fully static and runs on any arm64 Linux guest, and builds in the
Nucleic Linux build container with just `cc`. The base build stages this binary into the guest at
`/usr/local/bin/nucleic-linux-agent` and enables `systemd/nucleic-linux-agent.service`.

## Test

```sh
cc -O2 -pthread -o build/loopback_test test/loopback_test.c && ./build/loopback_test
```

`loopback_test.c` drives the connection handler over a socketpair (transport-independent), covering
ping, exec stdout/stderr/exit, the stdin round-trip, and JSON-escaped commands. `wire_test.c` is the
same round-trip over real `AF_VSOCK` loopback (`VMADDR_CID_LOCAL`) — run it *inside a guest* (or a host
with the `vsock_loopback` module) since many container kernels don't enable vsock loopback.
