CLI Reference


Global Flags

Every jerboa command accepts:

FlagDescription
-H, --hostDaemon endpoint override
--storeLocal client-side store root used by commands that touch client-owned state
--output table|jsonOutput format
-V, --verboseShow raw build/download output
-v, --versionShow CLI version

Endpoint resolution order:

  1. --host
  2. deprecated --socket
  3. JERBOA_HOST
  4. [daemon] endpoint in ~/.jerboa/config.toml
  5. platform default

Defaults:

Authentication token resolution:

  1. JERBOA_AUTH_TOKEN
  2. [daemon] token in ~/.jerboa/config.toml

Core VM Commands

jerboa snapshot

Local macOS Firecracker/HVF snapshots on named networks:

jerboa snapshot create <vm> <name>
jerboa snapshot restore <vm> <name>
jerboa snapshot ls --output json
jerboa snapshot inspect <name>
jerboa snapshot rm <name>

Creation pauses and resumes a running VM. Restore requires the same VM to be stopped and resumes its captured memory and ephemeral root disk in place. VMs with volumes and the default slirp network are rejected. Existing TCP connections do not survive; snapshots are not portable backups. See macOS snapshots for quotas, compatibility and recovery.

jerboa run <image>

Create and start a VM from:

Key flags:

FlagDescription
--memoryVM memory, default 256M
--cpusvCPU count, default 1
-p, --portPort mapping [bindaddr:]host:guest[/tcp|udp]; without a bind address the port publishes on all interfaces, 127.0.0.1:host:guest restricts it to localhost
-e, --envRepeatable environment variable
--env-fileRead env vars from file; explicit -e flags override matching keys
--nameHuman-readable VM name
--rmAuto-remove after stop
-v, --volumeNamed volume mount name:path[:ro]
--attachStream serial console and block
-d, --detachDetached mode, default true
--networkManaged network name
--ipStatic guest IP, requires --network; omitted, the daemon allocates one from the network’s subnet
--health-checktcp:PORT or http:PORT:/path
--restartnever, on-failure, always[:max-retries]
--verifySignature verification mode: off, warn, enforce
--cpu-sharescgroup v2 CPU weight (macOS QEMU: process priority; Firecracker: not supported)
--memory-maxcgroup v2 memory hard limit (macOS QEMU: VM stopped when exceeded; Firecracker: not supported)
--emulate-x86macOS only: run an x86_64 image with QEMU emulation
--disk-iopsBoot-disk IOPS throttle
--disk-bpsBoot-disk throughput throttle
--disk-io-engineHost block I/O engine for every drive: sync (default) or async (io_uring; Linux 5.10+ only). Async can help parallel I/O but costs extra host CPU and device setup time; benchmark before enabling
--volume-cacheVolume flush handling: writeback (default; a guest fsync reaches host storage on QEMU and Firecracker) or unsafe (flushes ignored; faster, but committed data can be lost if the host crashes). Not supported by Firecracker/HVF on macOS

Notes:

jerboa ps

List VMs known to the daemon. The command help still says “running”, but the implementation prints the daemon registry, including stopped entries when present.

jerboa status

Summary view of daemon-side VM counts and restart/health state.

jerboa logs <id>

Print buffered serial console output.

Flag:

When the output contains a known Nanos failure signature (popen failure, error loading shared library, no space left on device, …), an explanation of the cause and the fix is printed after the logs. The same detection runs on jerboa run --attach output. See Troubleshooting for the full catalogue.

jerboa inspect <id>

Return full VM detail as JSON.

jerboa stats <id>

Show runtime stats.

Flags:

jerboa stop <id>

Graceful stop by default. Idempotent: stopping a VM that is already stopped (for example a program that ran to completion and exited on its own) is a no-op that succeeds, matching docker stop.

Flag:

jerboa rm <id>

Remove a stopped VM from the daemon registry.

jerboa exec <id>

Send a signal through the daemon.

Flag:


Image Commands

jerboa build <path>

Build an image from a static ELF or a source directory.

Key flags:

FlagDescription
--nameImage name
--tagImage tag, default latest
--memoryDefault memory baked into the image
--cpusDefault CPU count baked into the image
--pkgInclude runtime package(s); appends to [build] pkgs from unikernel.toml
--pkg-sourceops (default) or jerboa; an explicit flag overrides [build] pkg_source
--langgo, node, python, rust, raw
--platformCross-build target
--portDeclared service port; emits the guest network section in the build manifest
-f, --filePath to the unikernel.toml to use (default: <path>/unikernel.toml)
--no-preflightSkip the pre-build binary checks (ELF class/arch, shared-library closure, entrypoint presence)
--size-report[=text|json]Before assembling, print what the image will contain grouped by program, runtime package, npm module, Python distribution and top-level project path. json prints every group to stdout (the build summary then goes to stderr)
--layoutDisk image layout: standard (default; boots on every hypervisor) or compact (no boot code and no boot filesystem copy of the kernel; about 3–4 MiB smaller, boots only on Firecracker and native ARM64 QEMU on macOS). An explicit flag overrides [build] layout
--smokeBoot the image once after building, scan serial output for known failure signatures, then stop and remove the test VM

unikernel.toml is read automatically when present, or selected explicitly with -f/--file. Relevant [build] keys:

KeyDescription
langBuild driver: go, node, python, rust, raw
entrypointOverride the default entrypoint
runShell commands to run before packaging (like a Dockerfile RUN)
pkgsPackages to include (e.g. ["eyberg/postgresql:11.3.0"]); --pkg flags append to this list
pkg_sourcePackage source: ops (default) or jerboa; an explicit --pkg-source flag wins
disk_sizeMinimum image size (e.g. 512M, 1G) for runtime scratch space
layoutstandard (default) or compact; see --layout
includeAllowlist of project paths to package for node, python and raw builds (e.g. ["server.js", "lib", "node_modules", "**/*.json"]). Paths are relative to the project root; * matches within a path segment, ** across segments, and a directory matches everything below it. It only narrows what .unignore lets through — re-include ignored defaults such as node_modules with !node_modules in .unignore. Python builds must list packages (pip dependencies). The build fails if the entrypoint is not included
dirsAbsolute directories to create empty in the image — volume mount points (a volume can only mount onto a directory that already exists in the image) and runtime scratch paths

For lang = "raw", [program] path names the runtime binary resolved from package files; the program is executed from its real in-image path, so binaries that locate their installation prefix relative to their own executable (e.g. postgres, mysqld) and binaries with $ORIGIN-relative library paths resolve correctly. When [program] is omitted entirely, the program and its arguments are inherited from the ops package’s own package.manifest (Program/Args), so well-formed ops packages build with just pkgs = [...].

Before assembling the image the build runs preflight checks: the program must be a 64-bit Linux ELF for a supported architecture; if dynamically linked, its interpreter and the full recursive DT_NEEDED shared-library closure must resolve against the image contents; node/python entrypoints must be among the packed files. Errors abort the build with a fix hint; --no-preflight skips the checks. See Build Concepts for the background.

[env] keys are baked into the image environment (highest priority — they override env supplied by packages or the language driver).

[run] keys are baked into the image manifest and inherited by jerboa run unless overridden by a flag (precedence: run flag > [run] value > built-in default):

KeyDescription
memoryDefault VM memory (e.g. 512M); applied unless --memory is given
cpusDefault vCPU count; applied unless --cpus is given
portshost:guest publish maps; applied when the VM joins a network (--network) and no -p is given

[[stages]] defines multi-stage builds: each stage has its own lang, entrypoint, args, and copy_from (stage, src, dst) directives; the final stage’s output becomes the image binary.

Build driver behavior to know:

Newly built images reserve a 4 MiB embedded boot filesystem partition instead of the previous 12 MiB layout, so they are about 8 MiB smaller (for example, hello drops from about 16.6 MiB to about 8.1 MiB). Older images are unchanged; rebuild an image to get the smaller layout.

jerboa init [path]

Write a commented unikernel.toml scaffold into path (default .). The language is auto-detected from marker files (go.mod, Cargo.toml, package.json, pyproject.toml/requirements.txt); ambiguous or empty directories get the generic template. The generated file documents every field inline, including the raw-mode program-path pitfalls.

Flags:

FlagDescription
--langForce the template: go, node, python, rust, raw
--forceOverwrite an existing unikernel.toml

init is a purely local command — it never contacts the daemon.

jerboa images

List images stored by the daemon.

jerboa rmi <ref>

Remove an image from the daemon store. Refused with an error if any VM (running or stopped) still references the image; remove those VMs first. This mirrors docker rmi and prevents leaving a VM pointing at a disk that no longer exists. Removing by digest removes all tags pointing to that image. Ambiguous digest prefixes are rejected.

jerboa sign <image>

Resolve the image through the daemon and sign its disk digest with the default Ed25519 key.

jerboa verify <image>

Resolve the image through the daemon, hash its actual disk contents, and verify the signature against that digest. run --verify enforce pins the verified digest; each hypervisor verifies the bytes while writing its private boot copy and starts the VM only if the digest matches.


Package Commands

jerboa pkg manages runtime packages used during builds.

Subcommands:

CommandPurpose
pkg listList locally cached packages; with no --source it lists both the ops and jerboa sources (so pkg create packages are visible), --source ops|jerboa filters to one
pkg search <query>Search remote index
pkg get <ref>Download package
pkg remove <ref>Remove cached package
pkg create <name>[:version] <binary>Create a local package
pkg from-docker <name>[:version] <image>Extract a binary and libraries from a Docker image
pkg push <name>:<version> <index-url>Push a local package to a remote index
pkg load <package>Download a package, build an image from it, and run it in one step (-d/--detach runs in the background)

Supported package sources (--source, default ops):

pkg from-docker flags:

# redis is a shell-launcher image, so name the real binary with --file.
jerboa pkg from-docker redis:7.2 redis:7.2 --file /usr/local/bin/redis-server
# unikernel.toml: lang="raw", pkgs=["redis:7.2"], pkg_source="jerboa",
#                 [program] path="/usr/local/bin/redis-server"
jerboa build . --name redis

pkg create flags:

pkg from-docker and selection operations also accept --platform. Docker imports record the requested reference, immutable image ID and available repository digest. Local variants coexist and take precedence over the remote index. jerboa images inspect <ref> displays image platform and integrated package versions, hashes and provenance. See ARM64 package workflow for local sysroots, compatibility rules and reproducible Firecracker acceptance.

pkg load uses the root command’s endpoint and authentication configuration, including --host and JERBOA_HOST. Use --source jerboa for local packages. pkg push without --platform prefers the default platform, then a legacy package, then the sole downloaded variant; use the flag for explicit selection.


Network And DNS Commands

jerboa network create <name>

Flags:

jerboa network ls

jerboa network inspect <name>

jerboa network rm <name>

jerboa dns resolve <name>

jerboa dns resolve-all <name>

jerboa dns list

Each DNS command accepts --network where relevant.

Published ports on Linux

jerboad --port-publish selects how a published port (-p) reaches the guest. Every mode keeps a real listening socket on the host, so the port is reserved and WSL2 can mirror it.

ModeClients on this hostClients on other hostsUDP
auto (default)kernel NAT (nftables), or the userspace proxy without ituserspace proxywith kernel NAT
natkernel NAT; the daemon fails to start without ituserspace proxyyes
nat-lankernel NATkernel NATyes
proxyuserspace proxyuserspace proxyno

Kernel NAT removes a userspace hop on every message. With a Redis guest on an x86 host, kernel NAT served about 45 % more requests than the proxy.

nat-lan is opt-in because it changes how the host firewall applies to published ports, exactly as Docker does for its own ports:

Connections from guests to a port published on the host keep using the proxy in every mode. On WSL2, kernel NAT is disabled and every mode uses the proxy.


Volume Commands

jerboa volume create <name>

Flags:

FlagDescription
--sizeVolume size, default 1G
--seed-pkgPackage to seed the volume from right after creation (repeatable)
--pkg-sourceSource for --seed-pkg: ops (default) or jerboa
--srcIn-package subtree whose contents become the volume root (default /)

Create and seed in one step:

jerboa volume create pgdata --size 1G \
  --seed-pkg eyberg/postgresql:11.3.0 --src /db

jerboa volume seed <name>

Populate an existing volume with an initialized filesystem taken from one or more packages, so the data is present the first time the volume is mounted. Created volumes are empty; mounting an empty volume over a data directory shadows whatever the image baked there. Seeding writes the package files into the volume’s filesystem (via mkfs on the daemon) so the data persists across VM lifecycles.

The canonical use is making a database persistent: a package such as eyberg/postgresql ships a pre-initialized data directory (initdb cannot run inside a unikernel — it fork/execs helper processes, which Nanos does not support), which is seeded onto a volume and then mounted.

jerboa volume create pgdata --size 1G
jerboa volume seed pgdata --pkg eyberg/postgresql:11.3.0 --src /db
jerboa run postgresql -v pgdata:/db --network pgnet -p 5432:5432

Flags:

FlagDescription
--pkgPackage providing the seed files (repeatable)
--pkg-sourceops (default) or jerboa
--srcIn-package subtree whose contents become the volume root (default /); e.g. /db

Notes:

jerboa volume ls

jerboa volume inspect <name>

jerboa volume rm <name>

Volume removal and seeding are rejected while any VM references the volume, including stopped VMs. Remove those VMs first.


Compose Commands

jerboa compose up <file>

jerboa compose down <file>

jerboa compose ps <file>

jerboa compose logs <file> <service>

Current behavior to know:


Cluster Commands

jerboa node ls

Requires the daemon to run with --cluster-addr.


Kernel Commands

jerboa kernel check

jerboa kernel update

kernel update accepts -y, --yes to skip the confirmation prompt.

These manage the cached toolchain (mkfs, boot.img, kernel.img) independently of the CLI version. Both resolve the latest kernel from the signed release manifest at releases.jerboa.dev and verify each artifact against its recorded SHA-256; there is no GitHub fallback and no historical version selection.


Version Command

jerboa version

Read-only readout of the installed CLI and kernel versions alongside the latest published version of every component (CLI, kernel, daemon, distro, desktop) taken from the signed release manifest. It never installs anything: on Windows the toolset is updated through the Jerboa Desktop app; on Linux you reinstall the CLI/daemon yourself. (jerboa --version still prints just the CLI version.)

Add --channel beta to query the beta channel instead of stable.


Config Commands

jerboa config get <key>

jerboa config set <key> <value>

The command group currently exposes only one writable key:

The config file supports more fields than the CLI subcommand currently edits. The underlying schema in ~/.jerboa/config.toml also includes:

Those are read by the codepath even though jerboa config set does not edit them yet.

With hypervisor = "qemu", the daemon automatically enables KVM when /dev/kvm is accessible by adding -enable-kvm -cpu host. If KVM is not available, QEMU falls back to TCG emulation and the daemon logs a warning. Firecracker still requires KVM.


Windows Daemon Commands

These commands exist only on Windows.

jerboa daemon install

Import the dedicated WSL2 distro. Before replacing an existing installation, the CLI downloads and validates the replacement and exports a recovery backup. The backup path is printed and retained if replacement fails. Local --rootfs archives are also validated before any unregister operation.

Flags:

jerboa daemon reinstall

Reimport the distro rootfs (fresh or newer). Unlike install --force, which destroys everything, --keep-data preserves your images, VMs, networks and volumes across the swap (exported before, restored after). The daemon is stopped and restarted around the reimport; the kernel toolchain cache is not preserved (it re-downloads on demand).

Flags:

jerboa daemon uninstall

jerboa daemon start

jerboa daemon restart

jerboa daemon stop

jerboa daemon status

jerboa daemon logs

Daemon start/restart flag:

jerboa daemon logs flag:

The daemon runs as root inside the dedicated distro. The client persists rendezvous state in ~/.jerboa/daemon.json.


Native jerboad Flags

jerboad is the Linux daemon binary.

FlagDescription
-H, --hostListen endpoint
--auth-tokenShared secret for Auth.Hello (env: JERBOA_AUTH_TOKEN); empty disables auth
--insecureAllow serving a TCP endpoint without an auth token (unsafe). A TCP endpoint with no token is rejected at startup otherwise; a Unix socket needs no token (it is restricted to the owning user with 0600 permissions)
--qemuQEMU binary path (default qemu-system-x86_64)
--hypervisorqemu or firecracker (overrides ~/.jerboa/config.toml)
--fc-binFirecracker binary path (only with --hypervisor=firecracker)
--fc-kernelFirecracker-compatible kernel path (auto-downloaded if omitted)
--fc-metrics-dirLinux only: write each Firecracker VM’s device metrics (per-drive bytes, operations, flushes, latency) as JSON lines to fc-<id>-metrics.json in this directory, for storage profiling
--tools-dirToolchain cache/lookup directory (mkfs, boot.img, kernel.img); empty caches under ~/.jerboa/tools
--storeImage store root directory (default ~/.jerboa/images)
--vm-disk-dirDirectory for per-VM private boot disks (default ~/.jerboa/vm-disks). Keep it on the image store’s filesystem: on btrfs, XFS (reflink) and APFS each start clones the image instantly; elsewhere a sparse copy writes only the image’s data blocks. Leftover disks from VMs that are no longer running are removed at startup
--vm-storeVM state store backend: file (default) or sqlite
--vm-log-max-bytesMax in-memory serial log bytes retained per VM (0 = 4 MiB default)
--log-formatLog format: text (default) or json
--metrics-addrHTTP address for Prometheus metrics (e.g. :9090); empty disables metrics
--ui-addrHTTP address for the web dashboard (e.g. :8080); empty disables it
--trace-addrOTLP gRPC address for trace export (e.g. localhost:4317); empty disables tracing
--cluster-addrHTTP address for the cluster gossip endpoint (e.g. :7946); empty disables cluster
--joinComma-separated seed node addresses to join (e.g. 10.0.0.2:7946,10.0.0.3:7946)

Observability and store flags (--metrics-addr, --ui-addr, --trace-addr, --log-format, --vm-log-max-bytes, --vm-store) are covered in more detail in Observability.


Current Command Surface

Root commands currently exposed by the built CLI: