wirenboard-agent-vm/npm-dist
Evgeny Boger 0468a2649a B2: ship a native aarch64-linux release binary via npm
Why
---
PLAN.md item "B2 — Cross-arch binaries" (section B, Distribution /
release) calls for cross-arch builds and per-platform npm packaging,
noting that "the package currently bundles a linux-x86_64 binary". As a
result Apple Silicon and ARM Linux users get no native artifact and fall
back to slow x86 emulation (Rosetta / qemu) — a poor fit for a tool whose
job is to launch microVMs quickly. This change delivers the linux/aarch64
half of B2: a genuine aarch64 binary, built, packaged, and selected at
install time, so ARM hosts run native.

How
---
Release workflow (.github/workflows/release-npm.yml): every build job
(build-agent-vm, build-msb, build-libkrunfw) and the package job gain a
linux-arm64 matrix leg. Because GitHub's hosted arm64 Linux runners
aren't on the free tier, the arm64 leg cross-compiles on the x64 runner:
a `cross: true` matrix flag drives a `CROSS` env switch that (a) enables
the arm64 multiarch apt repo and installs the cross linker
(gcc-aarch64-linux-gnu) plus the :arm64 dev libs agent-vm / msb link
against (libcap-ng, libdbus, libsqlite3), and (b) exports
PKG_CONFIG_ALLOW_CROSS / PKG_CONFIG_PATH / PKG_CONFIG_SYSROOT_DIR so the
`pkg-config` crate resolves the target libs. The msb job also sets
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER directly, since it builds
from vendor/microsandbox (a separate workspace not on the superproject's
.cargo config search path). All of these guards are no-ops on the native
x64 leg, so the existing x86_64 path is unchanged. The libkrunfw arm64
leg cross-builds the guest kernel with ARCH=arm64 / CROSS_COMPILE and
fails fast with a clear message if its arm64 kbuild .config seed
(libkrunfw-overrides/config-libkrunfw_aarch64.patch) hasn't been ported
yet, rather than silently shipping a mis-configured kernel. The publish
job downloads the new agent-vm-linux-arm64 artifact alongside the x64 one.

Cross toolchain config (.cargo/config.toml, new): pins the
aarch64-unknown-linux-gnu linker to aarch64-linux-gnu-gcc so a local
cross build reproduces CI; the file documents the matching apt packages.

npm launcher (npm-dist/agent-vm/bin/agent-vm.js,
npm-dist/agent-vm/package.json): un-comment the linux-arm64 entry in the
launcher's PLATFORM_PACKAGES map and add @wirenboard/agent-vm-linux-arm64
to the main package's optionalDependencies, so `npm install` pulls the
arm64 subpackage on ARM hosts and the launcher dispatches to it.

arm64 subpackage scaffold (npm-dist/agent-vm-linux-arm64/, new): mirrors
the x64 subpackage layout — package.json (os linux / cpu arm64),
README.md, and bin/.gitkeep + lib/.gitkeep placeholders — so the
directory exists in the tree for the release workflow to drop the
cross-built binary, msb, and libkrunfw into.

Dispatch test (npm-dist/agent-vm/bin/agent-vm.dispatch.test.js, new):
arm64 dispatch can't be exercised on an x86_64 CI host because node
reports the host's real process.arch. The test re-derives the launcher's
PLATFORM_PACKAGES map + bin-path logic from the source and asserts the
linux-arm64 key resolves to the arm64 subpackage with the same bin/
layout as x64, so a future edit that forgets arm64 fails here instead of
silently falling through to "no prebuilt binary" on ARM hardware.

README (npm-dist/README.md): document that the package now ships both the
linux-x64 and linux-arm64 per-platform subpackages.

macOS / darwin and win32 cross builds remain out of scope for this change
(still commented placeholders in the launcher) and are tracked under the
rest of B2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 18:57:07 +00:00
..
agent-vm B2: ship a native aarch64-linux release binary via npm 2026-05-31 18:57:07 +00:00
agent-vm-linux-arm64 B2: ship a native aarch64-linux release binary via npm 2026-05-31 18:57:07 +00:00
agent-vm-linux-x64 distribution: address code-review findings before v0.1.0 2026-05-25 11:43:08 +03:00
.gitignore distribution: ship via npm + ghcr.io image, drop local-build flow 2026-05-24 21:02:56 +03:00
README.md B2: ship a native aarch64-linux release binary via npm 2026-05-31 18:57:07 +00:00

npm-dist

Templates and tooling for distributing agent-vm via npm.

Layout

  • agent-vm/ — the user-facing main package. Tiny JS launcher (bin/agent-vm.js) that detects ${platform}-${arch} at runtime and execves the prebuilt native binary from the matching per-platform subpackage. Declares per-platform subpackages as optionalDependencies so npm installs only the right one.
  • agent-vm-linux-x64/, agent-vm-linux-arm64/ — per-platform subpackages. Each ships the prebuilt bin/agent-vm, the patched bin/msb, and lib/libkrunfw.so.5.2.1. agent-vm finds msb and libkrunfw via current_exe()-relative paths so a user's separate microsandbox install never shadows them.
  • Future per-platform subpackages: -darwin-arm64, -darwin-x64, -win32-x64. Add to the launcher's PLATFORM_PACKAGES map and to the main package's optionalDependencies.

How releases happen

CI populates each subpackage's bin/ and lib/ with freshly cross-compiled artifacts, rewrites every package.json version field to match the release tag, and runs npm publish for each package. See .github/workflows/release-npm.yml.

The OCI image is on a separate cadence (hourly cron) — see .github/workflows/build-image.yml. Binary releases pin the default image to ghcr.io/wirenboard/agent-vm-template:latest; users override per-launch via --image or AGENT_VM_IMAGE_TAG.

Local smoke test

To verify the launcher resolves a subpackage correctly without publishing, drop a prebuilt binary into a subpackage's bin/ and npm link it:

# build the binary
cargo build --release -p agent-vm
cargo build --release --manifest-path vendor/microsandbox/Cargo.toml \
    -p microsandbox-cli --bin msb

cp target/release/agent-vm npm-dist/agent-vm-linux-x64/bin/
cp vendor/microsandbox/target/release/msb npm-dist/agent-vm-linux-x64/bin/
cp ~/.microsandbox/lib/libkrunfw.so.5.2.1 npm-dist/agent-vm-linux-x64/lib/

cd npm-dist/agent-vm-linux-x64 && npm link && cd ..
cd npm-dist/agent-vm && npm link @wirenboard/agent-vm-linux-x64 && npm link

agent-vm --help   # should exec target/release/agent-vm