# nucleic-runner container image

The Antimatter runner's host-of-record container (design:
[docs/ANTIMATTER_RUNNER.md](../../docs/ANTIMATTER_RUNNER.md) §2, §9). Extends the
[`nucleic-sandbox`](../nucleic-sandbox) image with the `nucleicd` daemon, so a single container
is both the sync host of record and the agent sandbox — the CLOUD_RUNTIME `RunSpec.container =
nil` model, where the container *is* the sandbox.

## Building

The `nucleicd` **Linux** build is real — the CLOUD_RUNTIME Phase-2 port landed: the full
NucleicProtocol test suite (Noise handshake vectors, relay-enrollment PoP, sealed-credential
crypto) passes on Linux under swift-crypto, GRDB runs on Linux, the approval server listens on
BSD sockets, secrets live in the 0600-file store, and the relay WebSocket is SwiftNIO. A booted
Linux `nucleicd` enrolls with the deployed relay and mints pairing codes — verified on **both**
aarch64 (glibc) and **x86_64** (the fully-static musl build, run under qemu).

- **Self-host on a Mac:** you don't need this image at all — `swift run nucleicd` runs the
  daemon natively, joining the mesh as a `PeerKind.cloud` host.
- **Container build — Cloudflare Containers run `linux/amd64` ONLY.** The image binary is a
  fully-static x86_64-musl cross-build (works at native speed from any host arch; the script
  installs the Static Linux SDK and gives its sysroot the SQLite that GRDB links):
  ```sh
  docker run --rm -v "$PWD":/src -w /src swift:6.3-bookworm scripts/build-nucleicd-linux.sh
  cp .build/x86_64-swift-linux-musl/release/nucleicd containers/nucleic-runner/
  docker build --platform linux/amd64 -t nucleic-runner containers/nucleic-runner
  ```

Two gates before this image deploys to Cloudflare: the `nucleic-sandbox` **base image is
arm64-only today** and needs its linux/amd64 CI variant (the exact work CLOUD_RUNTIME §3.2
names), and the built image must be pushed to a registry — then uncomment the `containers`
block in [`cloud/nucleic-runner/wrangler.jsonc`](../../cloud/nucleic-runner/wrangler.jsonc).
The rest of the runner stack (Worker + pool DO) deploys and is tested without it.

## Runtime contract

The pool (`RunnerPool` DO → `RunnerContainer` DO) injects at start:
`NUCLEIC_RUNNER_{POOL_ID,INSTANCE_ID,EPOCH,INSTANCE_TOKEN,CONTROL_URL}` and optional
`NUCLEIC_RELAY_URL`. `nucleicd` enrolls with the relay, listens relay-only, heartbeats the pool
with its fencing epoch, and serves a one-shot pairing payload on loopback `:9200` for the
provisioning proxy.
