Build, run, and poke at the dev VM.
- macOS 26+ on Apple Silicon.
- Docker (OrbStack or Docker Desktop) running.
- Go 1.26+ (see
go.mod).
# Custom kernel (~8 min cold, ~1 s warm).
task kernel
# Initramfs + rootfs.img (~2 min cold, ~15 s warm).
task rootfs
# orcad-mini host binary + ad-hoc codesign with virtualization entitlement.
task buildOr task images to build kernel + rootfs in parallel. Both go through
docker buildx build --platform=linux/arm64 --target=export against
the matching Dockerfile; provenance/SBOM attestations are disabled so
the boot-image metadata stays on the concrete linux/arm64 payload.
Files land directly at the paths below.
| File | Built by | Source path inside OCI image |
|---|---|---|
kernel |
task kernel |
/Image (renamed locally) |
initrd |
task rootfs |
/initrd |
rootfs.img |
task rootfs |
/rootfs.img (mkfs.ext4 -d inside the Dockerfile) |
data.img |
first boot | sparse 1 TiB; mkfs'd by initramfs at first boot |
Release path (build + push to ghcr): edit Taskfile.yml's OCI_REPO
var, docker login ghcr.io, then task release (or
task release:kernel / task release:rootfs individually). Tags
ghcr.io/lixin9311/orca/kernel and ghcr.io/lixin9311/orca/rootfs
with both <short-git-sha> and latest.
sudo ./bin/orcad-mini daemon # foreground; SIGINT to stopCold boot to docker socket usable: ~2.6 s.
./bin/orcad-mini --help lists all subcommands; daemon --help shows
the boot flags (kernel, memory, --docker-bip, --docker-default-pool,
--swap-dns, --memory-balloon, etc.).
In another terminal:
# Docker socket on the host.
export DOCKER_HOST=unix://$HOME/.orca/run/docker.sock
docker run --rm hello-world
# Run a one-off command inside the guest.
./bin/orcad-mini exec -- /bin/sh -c 'mount | grep overlay'
# Tail a systemd unit.
./bin/orcad-mini logs docker.service
# Interactive PTY shell.
./bin/orcad-mini shell
# One-shot VM status snapshot (uptime, dockerd, memory, data.img).
./bin/orcad-mini statusCobra generates completion scripts for bash/zsh/fish/powershell:
# zsh (one-time): write to a dir on $fpath, then restart the shell.
./bin/orcad-mini completion zsh > "${fpath[1]}/_orcad-mini"
# bash (current shell):
source <(./bin/orcad-mini completion bash)Both TCP and UDP work; the macOS-side flag --publish-host (passed
to orcad-mini daemon) controls where wildcard bindings land.
# loopback only (default — same as Docker Desktop)
sudo ./bin/orcad-mini daemon
docker run --rm -p 8080:80 nginx # curl http://127.0.0.1:8080/
docker run --rm -p 5353:53/udp coredns # dig @127.0.0.1 -p 5353
# expose wildcard bindings on the LAN
sudo ./bin/orcad-mini daemon --publish-host 0.0.0.0
docker run --rm -p 8080:80 nginx # reachable from other LAN hostsExplicit -p IP:HOST:CTR bindings (e.g. -p 192.168.1.5:80:80) are
honored verbatim — --publish-host only narrows wildcards
("", 0.0.0.0, ::).
rm ~/.orca/vm/data.img # wipes overlay upper; re-mkfs'd next boot
rm -rf ~/.orca/vm # also wipes kernel + initrd + rootfs.img| Path | What |
|---|---|
cmd/orcad-mini/ |
Host CLI (cobra): daemon/exec/shell/logs/status/version. |
guest/kernel/ |
Custom kernel build (Linux 6.12.x + Orca config). |
guest/rootfs/ |
Dockerfile, initramfs init, guest agent, systemd units. |
scripts/orcad-mini/ |
sign.sh (ad-hoc codesign). |
internal/dns/, cmd/orca-*/ |
Other milestone-1 spikes (not used by orcad-mini). |
docs/ |
PRD, task files, spike results, memories. |
- docs/spikes/vm-bringup-results.md — S1 results, architecture, postmortem, measurements.
- docs/spikes/milestone-1-synthesis.md — milestone-1 synthesis across all five spikes.
- docs/prd/ — product requirements.
- docs/memories/ — durable project lessons.
- CLAUDE.md — guidance for AI agents working in this repo.