Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Every flag

The complete argument surface, generated from the command tree — so it is exhaustive by construction, and a test fails when this page and the binary disagree. For what the flags mean together, read CLI; this page is the index, not the explanation.

Every flag is also --help-discoverable: boot2deb <command> --help.

Global

Accepted by every subcommand.

flagvaluewhat it does
--root<ROOT> (default .)Config root (the boot2deb repo dir holding devices/, socs/, …)
--overlay<OVERLAY>, repeatableOut-of-tree overlay directory holding your own devices/, socs/, kernels/, features/, or recipes/ files. Repeatable; later overlays win, and any overlay wins over the shipped root — a same-named layer is deep-merged last-wins, a new-named one adds a target. Fragments/blobs/overlay trees an overlay ships are resolved along the same path
--jsonMachine-readable output: list-*, resolve, doctor, and the verify-* commands print a JSON document; build streams NDJSON events (one JSON object per line, tagged by its event field, artifacts included) instead of the human rendering. A command with no machine form rejects the flag rather than ignoring it. Errors still go to stderr as text
--quiet, -qPrint only what a command produced — artifact paths and errors — and none of its progress. Conflicts with --verbose; ignored under --json, where the stream is the record
--verbose, -vPrint every line the build’s subprocesses emit (make, git, dpkg-buildpackage) as well as the step boundaries and each stage’s own decisions. The default shows the latter only, which keeps a tens-of-minutes compile readable; reach for this when a stage fails or hangs

list-devices

List available devices

This command takes no flags of its own.

list-recipes

List available recipes

This command takes no flags of its own.

list-kernels

List available kernel definitions (the --kernel override’s valid values)

This command takes no flags of its own.

list-features

List available rootfs features (the --feature override’s valid values)

This command takes no flags of its own.

list-kmods

List available out-of-tree kernel-module sets (a device’s device_kmods entries)

This command takes no flags of its own.

support-matrix

Print the support matrix: each shipped recipe’s support claim joined to the exact pins its lock records

flagvaluewhat it does
--markdownEmit the docs/src/reference/support-matrix.md page verbatim, for regenerating it after a claim changes or a lock is re-pinned

cli-reference

Print the complete flag reference: every command’s positional arguments and flags, generated from this command tree so it cannot drift from the binary. --help answers this per command; this answers it for all of them at once

flagvaluewhat it does
--markdownEmit the docs/src/reference/cli-flags.md page verbatim, for regenerating it after a flag is added, removed, or re-described

completions

Print a shell completion script on stdout, for the shell named. Install it where your shell looks (e.g. boot2deb completions bash > \ ~/.local/share/bash-completion/completions/boot2deb); boot2deb writes no files itself, since where they belong is the packager’s call

argumentrequiredwhat it is
shellyesShell to generate for

This command takes no flags of its own.

man

Print the boot2deb(1) man page (roff) on stdout, e.g. boot2deb man > /usr/share/man/man1/boot2deb.1

This command takes no flags of its own.

new-device

Scaffold a new devices/<name>.toml (and, by default, a matching recipe) from the typed model: it offers the valid SoC/boot-method/kernel/feature choices, fills every derivable value, and marks the researched values (kernel_dtb, uboot_defconfig, the rkbin blobs) with # TODO: comments. Interactive on a terminal; drive it with flags for scripting. Writes into the highest-precedence --overlay when one is given, else the primary root

argumentrequiredwhat it is
nameyesDevice name — the devices/<name>.toml (and recipe) file stem
flagvaluewhat it does
--description<DESCRIPTION>Board description. Prompted if omitted on a terminal
--soc<SOC>SoC (e.g. rk3588). Must already have a socs/<soc>.toml. Prompted if omitted on a terminal; required otherwise
--boot-method<BOOT_METHOD>Boot method (e.g. rockchip-rkbin). Prompted/defaulted if omitted
--kernel<KERNEL>Kernel definition id (e.g. rk3588-mainline-7.2). Must support the chosen SoC. Prompted/defaulted if omitted
--suite<SUITE>Default Debian suite. Prompted/defaulted (forky) if omitted
--layout<LAYOUT>Default image layout (combined | split). Prompted/defaulted if omitted
--hostname<HOSTNAME>Default image hostname. Defaults to the device name
--image-size<IMAGE_SIZE>Default image size (e.g. 2G). Prompted/defaulted if omitted
--feature<FEATURES>, repeatableA feature the scaffolded recipe selects (repeatable). Must be compatible with the chosen SoC/arch. Prompted from the compatible set on a terminal
--no-recipeDo not scaffold a recipe — write only the device file
--forceOverwrite existing files instead of refusing
--non-interactiveNever prompt; take every value from flags/defaults. Implied when stdin is not a terminal

resolve

Resolve a device or recipe to a complete build (no build work)

argumentrequiredwhat it is
targetyesDevice name (e.g. turing-rk1) or recipe name (e.g. turing-rk1/forky)
flagvaluewhat it does
--kernel<KERNEL>Kernel definition id (list-kernels shows the valid values); default: the recipe/device default_kernel. Must be one of the device’s supported_kernels
--uboot-series<UBOOT_SERIES>u-boot patch series (e.g. rk3576-display); default: the recipe/device default_uboot_series. Must be one of the device’s supported_uboot_series
--suite<SUITE>Debian suite the image is built for (e.g. forky, trixie); default: the recipe/device default_suite. Re-pinning it for a build is update’s job — here it resolves a different build point
--layout<LAYOUT>Image packaging: combined (one whole-disk image) or split (a bootloader-only image plus a separate rootfs image, for a two-medium install); default: the recipe/device default_layout
--boot-method<BOOT_METHOD>How the board boots: rockchip-rkbin (u-boot compiled into a raw gap) or depthcharge (a signed ChromeOS kernel partition); default: the device’s own. Must be one of the device’s supported_boot_methods
--board<BOARD>Depthcharge board profile (e.g. speedy-libreboot). A profile describes the firmware a unit runs, not the board model — so a unit with replacement firmware may take a different one. Must be in the device’s supported_boards; ignored by boot methods with no board profile
--feature<FEATURES>, repeatableRootfs feature add-in, repeatable (--feature media-accel-rockchip). When any is given, replaces the recipe’s feature list
--image-size<IMAGE_SIZE>Total image size (e.g. 4G); default: the recipe/device image_size. The rootfs grows to fill its medium on first boot, so this bounds the artifact, not the installed system
--locale<LOCALE>System locale — the image’s LANG (e.g. de_DE.UTF-8); default: the recipe/base locale. Always generated into the image, so it is safe to name a locale nothing else lists
--locale-gen<LOCALES_GENERATE>, repeatableExtra locale to generate into the image, repeatable (--locale-gen fr_FR.UTF-8). When any is given, replaces the base locales_generate list; the system locale is generated regardless
--timezone<TIMEZONE>System timezone (e.g. America/New_York); default: the recipe/base timezone
--ntp-server<NTP_SERVERS>, repeatableNTP server the image prefers, repeatable (--ntp-server ntp.lan); default: the recipe/base ntp_servers. When any is given, replaces that list. Debian’s fallback pool is kept either way, so this sets a preference rather than the only source — worth setting for a board that boots on a network the public pool cannot be reached from
--keymap<KEYMAP>Console keyboard layout (e.g. gb); default: the recipe/device keymap, and none at all on a headless board. Sets XKBLAYOUT; the model, variant, and options keep their defaults — set those in the device’s [keymap] table
--sudo<SUDO>What sudo asks of the default account: nopasswd (root with no prompt) or password (prompts for the account’s own); default: the recipe/base sudo
--password-length<PASSWORD_LENGTH>Length of the generated per-image first-boot password; default: the recipe/base first_boot_password_length. Shorter is friendlier to transcribe at a console and weaker in exactly one way — an attack on the password hash inside a shared image — so authorize an SSH key (ssh_authorized_keys) rather than shortening this if the goal is to stop typing it

doctor

Preflight the host: arch/OS facts, and whether every tool a build needs is present — with the exact per-distro install command for anything missing. With a target it asks only for what that recipe will invoke; bare, it runs the requirements every board shares. A missing required tool is a non-zero exit

argumentrequiredwhat it is
targetnoDevice/recipe to preflight. Omit to check only the requirements no board can opt out of (user namespaces, the .deb packaging tools, the vendored apt trust anchors) — the answerable half before a board is chosen
flagvaluewhat it does
--work-dir<WORK_DIR>Scratch dir the target would build in; default: <root>/build/<target>. Only the overlay check reads it — it probes the filesystem that dir lands on, so checking a build you will run with --work-dir needs the same path here
--kernel<KERNEL>Kernel definition id (list-kernels shows the valid values); default: the recipe/device default_kernel. Must be one of the device’s supported_kernels
--uboot-series<UBOOT_SERIES>u-boot patch series (e.g. rk3576-display); default: the recipe/device default_uboot_series. Must be one of the device’s supported_uboot_series
--suite<SUITE>Debian suite the image is built for (e.g. forky, trixie); default: the recipe/device default_suite. Re-pinning it for a build is update’s job — here it resolves a different build point
--layout<LAYOUT>Image packaging: combined (one whole-disk image) or split (a bootloader-only image plus a separate rootfs image, for a two-medium install); default: the recipe/device default_layout
--boot-method<BOOT_METHOD>How the board boots: rockchip-rkbin (u-boot compiled into a raw gap) or depthcharge (a signed ChromeOS kernel partition); default: the device’s own. Must be one of the device’s supported_boot_methods
--board<BOARD>Depthcharge board profile (e.g. speedy-libreboot). A profile describes the firmware a unit runs, not the board model — so a unit with replacement firmware may take a different one. Must be in the device’s supported_boards; ignored by boot methods with no board profile
--feature<FEATURES>, repeatableRootfs feature add-in, repeatable (--feature media-accel-rockchip). When any is given, replaces the recipe’s feature list
--image-size<IMAGE_SIZE>Total image size (e.g. 4G); default: the recipe/device image_size. The rootfs grows to fill its medium on first boot, so this bounds the artifact, not the installed system
--locale<LOCALE>System locale — the image’s LANG (e.g. de_DE.UTF-8); default: the recipe/base locale. Always generated into the image, so it is safe to name a locale nothing else lists
--locale-gen<LOCALES_GENERATE>, repeatableExtra locale to generate into the image, repeatable (--locale-gen fr_FR.UTF-8). When any is given, replaces the base locales_generate list; the system locale is generated regardless
--timezone<TIMEZONE>System timezone (e.g. America/New_York); default: the recipe/base timezone
--ntp-server<NTP_SERVERS>, repeatableNTP server the image prefers, repeatable (--ntp-server ntp.lan); default: the recipe/base ntp_servers. When any is given, replaces that list. Debian’s fallback pool is kept either way, so this sets a preference rather than the only source — worth setting for a board that boots on a network the public pool cannot be reached from
--keymap<KEYMAP>Console keyboard layout (e.g. gb); default: the recipe/device keymap, and none at all on a headless board. Sets XKBLAYOUT; the model, variant, and options keep their defaults — set those in the device’s [keymap] table
--sudo<SUDO>What sudo asks of the default account: nopasswd (root with no prompt) or password (prompts for the account’s own); default: the recipe/base sudo
--password-length<PASSWORD_LENGTH>Length of the generated per-image first-boot password; default: the recipe/base first_boot_password_length. Shorter is friendlier to transcribe at a console and weaker in exactly one way — an attack on the password hash inside a shared image — so authorize an SSH key (ssh_authorized_keys) rather than shortening this if the goal is to stop typing it

update

Resolve upstream refs + hash blobs and write the recipe’s .lock. The sole path that consults upstream; build reads only the lock

argumentrequiredwhat it is
recipeyesRecipe to resolve (e.g. turing-rk1/forky)
flagvaluewhat it does
--feature<FEATURES>, repeatableRootfs feature to select, repeatable (--feature jellyfin --feature media-accel-rockchip). Replaces the recipe’s own feature list and pins the result as a variant of the recipe: the lock, its solved package manifest, and the build directory are all named <recipe>+<feature>..., so the recipe’s own lock is left alone and two selections never collide. Order is significant — kernel fragments and patch series compose in selection order. A variant carries no [support] claim; the claim belongs to the recipe
--kernel-ref<KERNEL_REF>Kernel ref to pin, resolved to a commit (e.g. v7.2). Optional once a lock exists: omitting it re-pins the previous lock’s kernel ref, so a routine re-pin (e.g. after importing a patch) needs no kernel tag the user did not touch. Required only for the first update, which has no prior ref to inherit. Auto-resolving a kernel track to its latest tag is a later refinement
--uboot-ref<UBOOT_REF>u-boot ref to pin. Defaults to the boot-method’s uboot_ref, re-read on every update, so bumping that one constraint moves every board on the method — except a lock already pinned to a bare commit sha, which is kept as the deliberate hand-pin only this flag can have created
--userspace-ref<NAME=REF>, repeatableMedia-accel userspace ref to pin, as NAME=REF, repeatable. Defaults to that tree’s own [[userspace]] ref, re-read on every update; a lock pinned to a bare commit sha is kept instead. The SoC declares which trees it has, so each override names one (--userspace-ref mpp=v1.5.0)
--ffmpeg-base-ref<FFMPEG_BASE_REF>ffmpeg base (V4L2) ref to pin. Defaults to the SoC layer’s ffmpeg.base, re-read on every update; a lock pinned to a bare commit sha is kept instead
--ffmpeg-rockchip-ref<FFMPEG_ROCKCHIP_REF>ffmpeg Rockchip provenance-tree ref to pin. Defaults to the SoC layer’s ffmpeg.rockchip, re-read on every update; a lock pinned to a bare commit sha is kept instead. Recorded as the graft’s provenance; not fetched
--patches-path<PATCHES_PATH>patches repo checkout whose HEAD pins the series (default: the config root’s sibling ../patches). update requires this local clone when the kernel names a patch series — the pin is its HEAD — unlike build, which auto-fetches the already-pinned commit and needs no checkout
--blobs-dir<BLOBS_DIR>Vendored rkbin blob directory (default: blobs/SOC under the config root)
--rootfs-manifest<ROOTFS_MANIFEST>Name recorded for the solved package manifest the rootfs stage writes (default: RECIPE.pkgs.lock)

verify-patches

Dry-run the locked patch series against source checkouts with git am --3way, hard-erroring on the first patch that does not apply

argumentrequiredwhat it is
recipeyesRecipe whose lock names the kernel ref + patch series
flagvaluewhat it does
--kernel-path<KERNEL_PATH>Kernel checkout to verify the kernel series against. Optional: omit it and the locked kernel is auto-fetched at its pinned ref into a durable cache, so verification works on a fresh clone with no hand-cloned tree
--kernel-src<KERNEL_SRC>Kernel clone source (git URL or local path) for the auto-fetch, in place of the kernel definition’s upstream URL. A local checkout (e.g. ../linux) that holds the locked commit makes the fetch near-instant. Ignored with --kernel-path, and only used on the first materialization (the cache keys on the commit, so later runs are hits regardless)
--ffmpeg-path<FFMPEG_PATH>ffmpeg checkout to verify the ffmpeg series against. Optional: omit it and, when the series carries ffmpeg patches, the locked ffmpeg base is auto-fetched at its pin
--ffmpeg-base-src<FFMPEG_BASE_SRC>ffmpeg base clone source (git URL or local path) for the auto-fetch, in place of the SoC layer’s ffmpeg.base URL. A local checkout makes the fetch near-instant. Ignored with --ffmpeg-path
--uboot-path<UBOOT_PATH>u-boot checkout to verify the u-boot series against. Optional: omit it and, when the recipe pins a u-boot series, the locked u-boot is auto-fetched at its pin
--uboot-src<UBOOT_SRC>u-boot clone source (git URL or local path) for the auto-fetch, in place of the boot method’s uboot_source. Ignored with --uboot-path
--userspace-path<USERSPACE_PATH>Userspace (MPP/RGA) checkout to verify the userspace series against. Optional: omit it and, when the series carries userspace patches, the locked MPP tree is auto-fetched at its pin
--userspace-src<USERSPACE_SRC>Clone source (git URL or local path) for the auto-fetch of the patched userspace tree, in place of that tree’s own [[userspace]] URL. A local checkout makes the fetch near-instant. Ignored with --userspace-path
--patches-path<PATCHES_PATH>patches repo checkout the series + patches are read from. Omit to use the config root’s sibling ../patches if present, else auto-fetch the series at the lock’s patches.commit
--patches-url<PATCHES_URL>Clone URL for auto-fetching the patches series when no local checkout is present; default: the repo the lock’s patch pin names
--kernel<VERSION>Verify against this kernel version instead of the one the lock pins, leaving the lock untouched — “would this series survive 7.2?” answered before adopting 7.2. Takes a kernel tag (v7.2, v7.2-rc3); pair it with --kernel-path or --kernel-src pointing at a tree that holds it. — A version outside the series’ declared applies_to_kernel is measured, not refused: that is the case worth asking about, and gating on the envelope would answer the question by assuming it. The run says so and reports what git am actually does, so a clean result is the evidence for widening the envelope. — A release candidate is matched against its base release here, so an -rc tree is answerable; the build path stays release-strict. — Kernel axis only: a recipe that pins no kernel (a deliverable = "uboot" one) rejects it rather than quietly verifying its u-boot series and reporting a green that answers nothing.
--keep-goingReport every patch that fails to apply rather than stopping at the first. — One boundary usually spawns adjacent ones, so the first failure is rarely the whole story. Note that each failing patch is skipped, so later results are measured against a tree missing it — a map of the damage, not a final verdict.

verify-config

Generate the kernel .config (base defconfig + fragments via merge_config.sh) on a patched kernel tree; with a reference config, additionally check byte-identical CONFIG_* parity against it

argumentrequiredwhat it is
recipeyesRecipe whose resolved kernel names the base defconfig + fragments
flagvaluewhat it does
--kernel-path<KERNEL_PATH>Kernel checkout (at the locked ref, patch series applied) to configure. Optional: omit it and the locked kernel is auto-fetched at its pinned ref and the kernel patch series applied for you, so the gate works on a fresh clone
--reference-config<REFERENCE_CONFIG>Reference .config to check byte-identical CONFIG_* parity against. Omit for a clean-merge check only
--work-dir<WORK_DIR>Directory for the two out-of-tree config builds (default: a temp dir)
--kernel-src<KERNEL_SRC>Kernel clone source (git URL or local path) for the auto-fetch, in place of the kernel definition’s upstream URL. A local checkout (e.g. ../linux) that holds the locked commit makes the fetch near-instant. Ignored with --kernel-path
--patches-path<PATCHES_PATH>patches repo checkout the kernel series is read from when auto-fetching the tree (ignored with --kernel-path, which is assumed already patched). Omit to use the config root’s sibling ../patches if present, else auto-fetch at the lock’s patches.commit
--patches-url<PATCHES_URL>Clone URL for auto-fetching the patches series; default: the kernel definition’s patches_url. Used only when auto-fetching the kernel tree

verify-packages

Ask the archives a build would resolve against whether they carry every package the recipe names, and report the ones they do not. Runs the read half of a resolve — release and indexes, nothing downloaded, no closure computed — so one pass answers every name at once, before any build work starts

argumentrequiredwhat it is
recipeyesRecipe whose resolved package set to check (e.g. turing-rk1/forky)

This command takes no flags of its own.

verify-image

Hold a finished image artifact to the invariants that are checkable without a board: the artifact set is present, the plan document parses and its digest matches what the provenance records, [[archives]] is well formed, the ext4 filesystem is exactly its GPT partition, and a fitted --image-size left the slack it asked for. Read-only, no root: only the head of the artifact is decompressed. The off-board half of the hardware gate

argumentrequiredwhat it is
recipeyesRecipe whose built image to verify (e.g. turing-rk1/forky)
flagvaluewhat it does
--out-dir<OUT_DIR>Directory holding the built artifacts (default: the recipe’s own <work>/artifacts)

verify-sources

Probe each locked source pin against its configured upstream URL and report whether it is a durable tag, an ephemeral branch, or ORPHANED (not re-fetchable) — the source-pin durability survey as a command. Read-only: git ls-remote plus a timeout-bounded ancestry check, no build, no checkout, no hardware

argumentrequiredwhat it is
recipeyesRecipe whose lock names the source pins (e.g. turing-rk1/forky)

This command takes no flags of its own.

patch

Curate the patch series. Subcommand: import

patch import

Fetch a patch (patchwork/mbox URL, a file, or - for stdin), normalize it to canonical git am-ready mbox, slot it into a series’ scope at a position, and — with --verify-tree — dry-run git am-verify the resulting series

argumentrequiredwhat it is
sourceyesPatch source: an http(s):// URL (a patchwork mbox), a local file path, or - to read from stdin
flagvaluewhat it does
--series<SERIES>Series to slot the patch into (e.g. rk3588-accel) — names series/<name>/series.toml in the patches repo
--scope<SCOPE>Which source tree’s ordered list to insert into
--position<POSITION>1-based position in the scope list to insert at (default: append to the end). 0 or a value past one-beyond-the-end is an error, not a clamp
--dest-dir<DEST_DIR>Repo subdirectory to write the patch into (default: media-accel/<scope>). Use e.g. rocket to target the NPU scope of the kernel list
--name<NAME>Filename slug override (default: a kebab-case slug of the subject). The written file is <dest-dir>/<prefix>-<slug>.patch
--as<LABEL>Explicit repo-relative destination label, overriding the derived dir/prefix/slug entirely (e.g. media-accel/kernel/045-fix.patch)
--author<AUTHOR> (default boot2deb import <import@boot2deb>)From: author for a synthesized header (bare diff / git show fallback)
--subject<SUBJECT>Subject override — the title for a bare diff carrying none, or an override for git show. Ignored for an already-formatted mbox
--origin<ORIGIN>DEP-3 Origin: provenance trailer to add to the commit message
--patches-path<PATCHES_PATH>patches repo checkout to write into (default: the config root’s sibling ../patches). patch import requires this local clone — it writes the patch file and edits the series there — unlike build, which auto-fetches pinned commits
--verify-tree<VERIFY_TREE>Source checkout to dry-run git am-verify the spliced series against. Omit to import without verifying (a warning is printed)
--forceOverwrite the destination file if it already exists (default: refuse)

build

Drive the build stages (kernel, u-boot, userspace, ffmpeg, and the disk image) from the recipe’s lock, streaming the structured build event stream. Reads only the lock for pinned sources; the lock-independent image axes (--layout, --image-size) are overridable, while re-pinning a source axis (kernel/suite/features/boot-method) is update’s job

argumentrequiredwhat it is
recipeyesRecipe to build (e.g. turing-rk1/forky); its .lock must exist
flagvaluewhat it does
--feature<FEATURES>, repeatableRootfs feature to select, repeatable — the same selection update --feature pinned. It names which lock to build from (<recipe>+<feature>...), it does not re-resolve one: update must have written that variant’s lock first, and a selection with no lock is an error naming the update line to run. Passing the reference directly (build turing-rk1/forky+jellyfin) is equivalent
--stageall | kernel | dtb | kmod | uboot | userspace | ffmpeg | rootfs | image (default all)Which stage(s) to run
--kernel-src<KERNEL_SRC>Kernel clone source (git URL or local path); default: the kernel definition’s source URL. A local clone (e.g. ../linux) is far faster
--uboot-src<UBOOT_SRC>u-boot clone source (git URL or local path); default: the boot method’s uboot_source
--userspace-src<NAME=SRC>, repeatableMedia-accel userspace clone source, as NAME=SRC, repeatable; default: that tree’s own [[userspace]] URL. The SoC declares which trees it has, so each override names one (--userspace-src mpp=../mpp-rockchip). A local checkout is far faster than a fresh clone. The clone is still made at the locked commit, so the named tree must contain it
--ffmpeg-base-src<FFMPEG_BASE_SRC>ffmpeg base (Kwiboo) clone source; default: the SoC layer’s ffmpeg.base URL. A local checkout makes the fetch near-instant
--kmod-src<NAME=SRC>, repeatableOut-of-tree module clone source, as NAME=SRC, repeatable; default: that kmod’s locked source. Unlike the single-tree axes there are several modules, so each override names the device_kmods entry it applies to (--kmod-src aic8800=../aic8800). The clone is still made at the locked commit, so the named tree must contain it
--userspace<NAME>, repeatableAlso build an optional media-accel userspace tree, by name, repeatable. — A tree the SoC marks optional is skipped unless named here: libmali is the live case — the transcode pipeline rides the VPU and the RGA, not the GPU, so a headless box never needs the blob and compiling its variant matrix is minutes for nothing. Naming an optional tree also changes what the whole userspace stage layers, so every tree’s cache key moves with it.
--patches-path<PATCHES_PATH>patches repo checkout the series is read from. Omit to use the config root’s sibling ../patches (if present, with the lock’s patches.commit enforced), else auto-fetch the series at the pinned commit from --patches-url/the repo the pin names. Pass an explicit path to co-develop the series from a working checkout, which downgrades a pin mismatch to a loud warning
--patches-url<PATCHES_URL>Clone URL for auto-fetching the patches series when no local checkout is present; default: the repo the lock’s patch pin names. The series is fetched at the lock’s patches.commit into a durable cache and its pin enforced. Ignored when --patches-path or the sibling ../patches supplies a checkout
--blobs-dir<BLOBS_DIR>Vendored rkbin blob directory (default: blobs/SOC under the config root)
--keyring<KEYRING>Debian archive keyring every root this build provisions is verified against (default: the vendored blobs/keyrings/debian-archive-keyring.gpg; omit on a Debian host to use its apt trust store)
--unsafe-overlay-keyringTrust an overlay-shipped copy of the archive keyring. By default an overlay that ships blobs/keyrings/debian-archive-keyring.gpg is refused as a trust-anchor swap; this opts into the overlay’s copy explicitly
--work-dir<WORK_DIR>Scratch dir for clones + builds (default: <root>/build/RECIPE)
--out-dir<OUT_DIR>Where produced artifacts are staged (default: WORK_DIR/artifacts). Every artifact is named for the recipe, so several builds may share one directory
--jobs<JOBS>make -j parallelism (default: host available parallelism). Must be at least 1 — 0 would reach make -j0 (“unlimited”), never what a typo means
--rootfs-tar<ROOTFS_TAR>Rootfs tar archive for the image stage. Optional: --stage image otherwise uses the tar the rootfs stage produced (auto-discovered in the output dir), so this is only needed to point at a tar built elsewhere
--rootfs-label<ROOTFS_LABEL> (default rootfs)ext4 volume label / GPT partition name for the image rootfs
--compressxz | gz | none, repeatable (default xz)Containers to compress the finished image(s) into, comma-separated and in preference order — xz (default), gz, or none. Use gz for an image u-boot will write to a disk itself: gzwrite reads gzip only, never xz. --compress xz,gz emits both; the first named is what the next: hint points at
--keep-rawKeep the raw .img after compressing it (default: delete it once every requested container is written, since it is derivable and the largest artifact). Has no effect under --compress none, where the raw image is the only output anyway
--layout<LAYOUT>Image layout override (combined | split); default: the recipe/device layout. Lock-independent — it changes only image packaging, not any pinned source, so it is safe to set against an existing lock
--image-size<IMAGE_SIZE>Image-size override (e.g. 4G, or fit+20% to size the image to its contents with a fifth of the rootfs left free); default: the recipe/device image_size. Lock-independent — it changes only image geometry, not any pinned source
--snapshot<SNAPSHOT>Snapshot activation for the rootfs bootstrap: off (live mirror), fallback (live first, snapshot.debian.org fills 404s), pin (snapshot only, fully deterministic). Default: the lock’s captured mode (off if none). fallback/pin need a captured snapshot (--save-snapshot)
--save-snapshotAfter a successful build, capture the current UTC time as a snapshot.debian.org timestamp into the lock (dormant, mode = off), so the solved versions stay fetchable after they rotate off the live mirror; a later build activates it with --snapshot fallback|pin
--save-manifestAfter the rootfs stage, commit the solved package manifest beside the lock and record its sha256 in the lock ([rootfs].manifest_sha256) — the reproducibility pin later builds verify a fresh solve against
--allow-manifest-driftDowngrade a solved-manifest drift from the committed pin to a warning instead of a hard error — for co-development or a knowingly-moved mirror. Re-pin deliberately with --save-manifest (which skips the drift check entirely, so combining the two is rejected as contradictory)
--sbomspdx | cyclonedx, repeatableAlso write a software bill of materials beside the image, in this format (repeatable — --sbom spdx --sbom cyclonedx writes both). Off by default, so a build never silently gains a file; the same documents can be produced later from the published provenance manifest with boot2deb sbom. Set SOURCE_DATE_EPOCH for a byte-reproducible document — everything else in it is derived from the image’s own content
--refresh-rootfsIgnore a rootfs cache hit and re-bootstrap, refreshing the stored tree. The plan is still resolved — the rootfs cache keys on the solved set, so a moved mirror already rebuilds automatically; this is the manual escape when you want a clean bootstrap regardless
--no-artifact-cacheDisable the Tier-2 artifact cache: always recompile the kernel / u-boot / userspace / ffmpeg .debs instead of restoring a stored output on a signature hit, and do not store this build’s outputs. The durable store at <root>/cache/artifacts is left untouched
--allow-stale-builderBuild even though this boot2deb binary does not match the source checkout it is being run from — it was compiled before the checkout’s current commit, or before edits under crates/. The image is built by the running binary either way; what the mismatch costs is the truth of the [built_with] stamp, which would name a commit that is not what ran. The fix is normally cargo build, which takes seconds; this is for the case where you mean it

reproduce

Rebuild an image from the plan document a previous build published, instead of resolving the archive afresh. The lock pins the sources; the plan pins the package versions the archive served, which the lock cannot. Takes every build flag, and differs from it in one way: the rootfs installs the plan’s exact set by the digests it records, reading neither a release nor a package index — so the plan, not an archive signature, is what those digests chain to

argumentrequiredwhat it is
recipeyesRecipe to reproduce (e.g. turing-rk1/forky); its .lock must exist
flagvaluewhat it does
--from<FROM>Directory holding the published <stem>.plan (and, for the builder advisory, <stem>.provenance.toml) — the directory the image shipped from. Default: this build point’s own output dir, which is where a build on this machine already published them
--feature<FEATURES>, repeatableRootfs feature to select, repeatable — the same selection update --feature pinned. It names which lock to build from (<recipe>+<feature>...), it does not re-resolve one: update must have written that variant’s lock first, and a selection with no lock is an error naming the update line to run. Passing the reference directly (build turing-rk1/forky+jellyfin) is equivalent
--stageall | kernel | dtb | kmod | uboot | userspace | ffmpeg | rootfs | image (default all)Which stage(s) to run
--kernel-src<KERNEL_SRC>Kernel clone source (git URL or local path); default: the kernel definition’s source URL. A local clone (e.g. ../linux) is far faster
--uboot-src<UBOOT_SRC>u-boot clone source (git URL or local path); default: the boot method’s uboot_source
--userspace-src<NAME=SRC>, repeatableMedia-accel userspace clone source, as NAME=SRC, repeatable; default: that tree’s own [[userspace]] URL. The SoC declares which trees it has, so each override names one (--userspace-src mpp=../mpp-rockchip). A local checkout is far faster than a fresh clone. The clone is still made at the locked commit, so the named tree must contain it
--ffmpeg-base-src<FFMPEG_BASE_SRC>ffmpeg base (Kwiboo) clone source; default: the SoC layer’s ffmpeg.base URL. A local checkout makes the fetch near-instant
--kmod-src<NAME=SRC>, repeatableOut-of-tree module clone source, as NAME=SRC, repeatable; default: that kmod’s locked source. Unlike the single-tree axes there are several modules, so each override names the device_kmods entry it applies to (--kmod-src aic8800=../aic8800). The clone is still made at the locked commit, so the named tree must contain it
--userspace<NAME>, repeatableAlso build an optional media-accel userspace tree, by name, repeatable. — A tree the SoC marks optional is skipped unless named here: libmali is the live case — the transcode pipeline rides the VPU and the RGA, not the GPU, so a headless box never needs the blob and compiling its variant matrix is minutes for nothing. Naming an optional tree also changes what the whole userspace stage layers, so every tree’s cache key moves with it.
--patches-path<PATCHES_PATH>patches repo checkout the series is read from. Omit to use the config root’s sibling ../patches (if present, with the lock’s patches.commit enforced), else auto-fetch the series at the pinned commit from --patches-url/the repo the pin names. Pass an explicit path to co-develop the series from a working checkout, which downgrades a pin mismatch to a loud warning
--patches-url<PATCHES_URL>Clone URL for auto-fetching the patches series when no local checkout is present; default: the repo the lock’s patch pin names. The series is fetched at the lock’s patches.commit into a durable cache and its pin enforced. Ignored when --patches-path or the sibling ../patches supplies a checkout
--blobs-dir<BLOBS_DIR>Vendored rkbin blob directory (default: blobs/SOC under the config root)
--keyring<KEYRING>Debian archive keyring every root this build provisions is verified against (default: the vendored blobs/keyrings/debian-archive-keyring.gpg; omit on a Debian host to use its apt trust store)
--unsafe-overlay-keyringTrust an overlay-shipped copy of the archive keyring. By default an overlay that ships blobs/keyrings/debian-archive-keyring.gpg is refused as a trust-anchor swap; this opts into the overlay’s copy explicitly
--work-dir<WORK_DIR>Scratch dir for clones + builds (default: <root>/build/RECIPE)
--out-dir<OUT_DIR>Where produced artifacts are staged (default: WORK_DIR/artifacts). Every artifact is named for the recipe, so several builds may share one directory
--jobs<JOBS>make -j parallelism (default: host available parallelism). Must be at least 1 — 0 would reach make -j0 (“unlimited”), never what a typo means
--rootfs-tar<ROOTFS_TAR>Rootfs tar archive for the image stage. Optional: --stage image otherwise uses the tar the rootfs stage produced (auto-discovered in the output dir), so this is only needed to point at a tar built elsewhere
--rootfs-label<ROOTFS_LABEL> (default rootfs)ext4 volume label / GPT partition name for the image rootfs
--compressxz | gz | none, repeatable (default xz)Containers to compress the finished image(s) into, comma-separated and in preference order — xz (default), gz, or none. Use gz for an image u-boot will write to a disk itself: gzwrite reads gzip only, never xz. --compress xz,gz emits both; the first named is what the next: hint points at
--keep-rawKeep the raw .img after compressing it (default: delete it once every requested container is written, since it is derivable and the largest artifact). Has no effect under --compress none, where the raw image is the only output anyway
--layout<LAYOUT>Image layout override (combined | split); default: the recipe/device layout. Lock-independent — it changes only image packaging, not any pinned source, so it is safe to set against an existing lock
--image-size<IMAGE_SIZE>Image-size override (e.g. 4G, or fit+20% to size the image to its contents with a fifth of the rootfs left free); default: the recipe/device image_size. Lock-independent — it changes only image geometry, not any pinned source
--snapshot<SNAPSHOT>Snapshot activation for the rootfs bootstrap: off (live mirror), fallback (live first, snapshot.debian.org fills 404s), pin (snapshot only, fully deterministic). Default: the lock’s captured mode (off if none). fallback/pin need a captured snapshot (--save-snapshot)
--save-snapshotAfter a successful build, capture the current UTC time as a snapshot.debian.org timestamp into the lock (dormant, mode = off), so the solved versions stay fetchable after they rotate off the live mirror; a later build activates it with --snapshot fallback|pin
--save-manifestAfter the rootfs stage, commit the solved package manifest beside the lock and record its sha256 in the lock ([rootfs].manifest_sha256) — the reproducibility pin later builds verify a fresh solve against
--allow-manifest-driftDowngrade a solved-manifest drift from the committed pin to a warning instead of a hard error — for co-development or a knowingly-moved mirror. Re-pin deliberately with --save-manifest (which skips the drift check entirely, so combining the two is rejected as contradictory)
--sbomspdx | cyclonedx, repeatableAlso write a software bill of materials beside the image, in this format (repeatable — --sbom spdx --sbom cyclonedx writes both). Off by default, so a build never silently gains a file; the same documents can be produced later from the published provenance manifest with boot2deb sbom. Set SOURCE_DATE_EPOCH for a byte-reproducible document — everything else in it is derived from the image’s own content
--refresh-rootfsIgnore a rootfs cache hit and re-bootstrap, refreshing the stored tree. The plan is still resolved — the rootfs cache keys on the solved set, so a moved mirror already rebuilds automatically; this is the manual escape when you want a clean bootstrap regardless
--no-artifact-cacheDisable the Tier-2 artifact cache: always recompile the kernel / u-boot / userspace / ffmpeg .debs instead of restoring a stored output on a signature hit, and do not store this build’s outputs. The durable store at <root>/cache/artifacts is left untouched
--allow-stale-builderBuild even though this boot2deb binary does not match the source checkout it is being run from — it was compiled before the checkout’s current commit, or before edits under crates/. The image is built by the running binary either way; what the mismatch costs is the truth of the [built_with] stamp, which would name a commit that is not what ran. The fix is normally cargo build, which takes seconds; this is for the case where you mean it

diff

Compare two build points: the packages, the kernel pin and its requested config, the patch series and the patch files behind them, every other source pin, the rkbin blobs, and what built each side. Each side is a recipe name, a .lock, or a .provenance.toml; mixing is allowed, and a section only one side can answer is reported unavailable rather than as a change. Offline — reads documents the build already wrote

argumentrequiredwhat it is
leftyesThe left side: a recipe (e.g. turing-rk1/forky), or a path to a .lock or .provenance.toml
rightyesThe right side, in any of the same forms
flagvaluewhat it does
--sectionpackages | kernel | patches | sources | blobs | builder, repeatableReport only these sections (repeatable). Default: all of them
--patches-path<PATCHES_PATH>patches checkout to resolve a moved patches commit into named files. Default: the config root’s sibling ../patches

sbom

Export an image’s bill of materials as SPDX 2.3 or CycloneDX 1.6 JSON, from the provenance manifest and solved package manifest a build published. Lists every installed package with its version and sha256, every pinned source tree the image was compiled from, every rkbin blob, and every externally-fetched .deb. Licenses are declared NOASSERTION — boot2deb records none, and inventing them would produce a field that looks authoritative and is not. Offline; builds nothing

argumentrequiredwhat it is
targetyesRecipe whose published image to describe (e.g. turing-rk1/forky), or a path to a .provenance.toml shipped with an image
flagvaluewhat it does
--formatspdx | cyclonedx (default spdx)Document format to write
--out<OUT>Write to this file instead of stdout
--feature<FEATURES>, repeatableRootfs feature the published image was built with, repeatable — the same selection build --feature used. It names which image’s documents to read; passing the reference directly (sbom turing-rk1/forky+jellyfin) is equivalent. Ignored when a .provenance.toml path is given, which already names one image

size

Break down what an image’s package set weighs, from the plan document a build published — per binary package, per source package, or per repository. The figures are the archives’ own Installed-Size estimates in kibibytes, so they answer “what did the packages contribute” and not “how large is the image”: they exclude filesystem overhead and everything the image gains after dpkg. Offline; builds nothing

argumentrequiredwhat it is
targetyesRecipe whose published image to weigh (e.g. turing-rk1/forky), or a path to a .plan shipped with an image
flagvaluewhat it does
--bypackage | source | archive (default package)Axis to roll up on: one row per binary package, per source package (which attributes a source’s several outputs to the thing that was built), or per repository (which separates what Debian shipped from what this build compiled)
--top<TOP> (default 25)Show only the heaviest N rows; 0 shows every row. The totals always describe the whole set, so a truncated view still says what it is a view of
--feature<FEATURES>, repeatableRootfs feature the published image was built with, repeatable — the same selection build --feature used. It names which image’s plan to read; passing the reference directly (size turing-rk1/forky+jellyfin) is equivalent. Ignored when a .plan path is given, which already names one image

outdated

Survey what has moved upstream since the locks were pinned: for each recipe’s git source pins, whether a newer release tag exists (and how far behind the pin is), or whether a pinned branch’s tip has moved. Read-only — one git ls-remote per distinct remote, no fetch and no re-pin. Being behind is not a failure, so this always exits zero; verify-sources is the gate, and it answers the different question of whether a pin is still fetchable at all

argumentrequiredwhat it is
recipesnoRecipes to survey (e.g. turing-rk1/forky). Default: every recipe in the config tree

This command takes no flags of its own.

why-rebuild

Explain, per compile node, what the next build will actually redo: whether it reuses or rebuilds the cached source tree (naming the pinned input that moved), and whether the durable artifact cache lets it skip the compile entirely. Offline: reads the lock, the build stamps, and the artifact store; runs no build

argumentrequiredwhat it is
recipeyesRecipe to inspect (e.g. turing-rk1/forky); its .lock must exist
flagvaluewhat it does
--work-dir<WORK_DIR>Build scratch dir to inspect (default: <root>/build/RECIPE) — must match the dir the build used, since the stamps live there
--patches-path<PATCHES_PATH>The build being reasoned about used an explicit --patches-path co-dev checkout (folded into the kernel/u-boot/ffmpeg signatures). Pass the same value so the prediction matches what that build would reuse
--userspace<NAME>, repeatableThe build being reasoned about names these optional userspace trees (--userspace <name>). Pass the same set: an optional tree changes what the whole userspace stage layers, so it moves every userspace node’s key
--no-artifact-cacheThe build being reasoned about passes --no-artifact-cache. The Tier-2 artifact cache is then off, so no node restores a stored .deb and every one recompiles — pass it here to see that prediction rather than the cached one

shell

Open an interactive shell in the root a build stage compiles in — the same base tree, the same layered build-dependencies, the same mounts and the same environment the compile has. The way to diagnose a failed compile by looking at it rather than by reading what it printed. Provisions the root if this work dir has none; needs a terminal

argumentrequiredwhat it is
recipeyesRecipe whose root to enter (e.g. turing-rk1/forky); its .lock must exist
commandnoThe command to run in the root, and its arguments. Default: an interactive bash. Everything after -- is taken verbatim, so a command’s own flags reach it rather than boot2deb
flagvaluewhat it does
--stagekernel | uboot | kmod | userspace | ffmpeg | packagingWhich root to enter. Required: the whole point is entering a particular stage’s root, and no default is more likely right than another
--feature<FEATURES>, repeatableRootfs feature to select, repeatable — the same selection build --feature used, since a variant builds in a work dir of its own. Passing the reference directly (shell turing-rk1/forky+jellyfin) is equivalent
--work-dir<WORK_DIR>Build scratch dir whose roots to enter (default: <root>/build/RECIPE) — the same default build uses, so a session lands in the tree a build made
--out-dir<OUT_DIR>Directory holding the .debs the compile stages staged (default: WORK_DIR/artifacts). Read only by --stage ffmpeg, whose root layers this build’s own userspace packages out of it
--userspace<NAME>, repeatableEnter the userspace root as a build naming these optional trees would see it, carrying the development packages their own probes need — the same set the userspace stage ran under
--snapshot<SNAPSHOT>Snapshot activation, as build takes it. Default: the lock’s captured mode. It is in every provisioned root’s cache key, so a session opened under a different mode than the build ran under would enter a different tree
--keyring<KEYRING>Debian archive keyring for the bootstrap, if the root has to be provisioned. Default: the vendored blobs/keyrings/debian-archive-keyring.gpg

clean

Remove a recipe’s build scratch (clones, sandbox, rootfs cache) under its work dir, or sweep the durable caches every recipe shares, to reclaim disk or force a clean rebuild

argumentrequiredwhat it is
recipenoRecipe whose build scratch to remove (e.g. turing-rk1/forky). Optional when every selector given is root-scoped (--artifacts, --verify-trees, --kconfig, --all-caches), since those name a shared store rather than one recipe’s work dir
flagvaluewhat it does
--work-dir<WORK_DIR>Build scratch dir to clean (default: <root>/build/RECIPE)
--cacheRemove only the rootfs early-cutoff cache (WORK_DIR/cache), keeping the compiled source trees and artifacts
--sandboxRemove only the provisioned roots (WORK_DIR/sandbox: the target-arch build sandbox and the host-arch packaging root) — the largest reclaimable tree
--build-rootsRemove the provisioned build roots and the layers staged over them, sparing the packaging root, so the next build provisions them against the archive as it stands now — the answer to the <stage> build root does not satisfy its own dependencies, where a cached base has aged past the archive its layer resolved from. --sandbox clears the same skew but takes the packaging root with it, which is a second bootstrap for a root that is never layered and cannot skew
--artifactsRemove the durable Tier-2 artifact store (<root>/cache/artifacts). Root-scoped: this store is shared across recipes, so it clears cached outputs for every recipe, not just one
--verify-treesPrune the auto-fetched source checkouts (<root>/cache/verify-trees, and the patches checkouts beside them) down to what is still pinned: a checkout is commit-addressed, so one whose commit no recipes/*/*.lock names can only be re-fetched, never reconstructed from, and is dead. Root-scoped. Pinned checkouts stay — --all-caches is what takes those too. Pass the same --overlay flags a build of these recipes uses: the pinned set is read from the search paths, so a sweep that omits an overlay calls its checkouts dead. The run reports how many locks it read, which is what makes a narrow set visible
--kconfigRemove verify-config’s scratch tree (<root>/cache/kconfig), one work dir per recipe holding a provisioned cross root and a kbuild output dir. Pure scratch: the next verify-config re-provisions. Root-scoped
--all-cachesRemove the whole durable cache tree (<root>/cache) — artifacts, every auto-fetched checkout including the pinned ones, the kconfig scratch, and the pre-built extra-deb store. Root-scoped, and the nuclear option: everything here is reclaimable by construction, but re-earning it costs a full re-fetch and a cache-cold rebuild
--dry-runShow what would be removed (with sizes) without removing anything
--forceRemove the work dir even when it is not stamped as boot2deb-created (no .boot2deb-work marker). Without this, clean refuses such a target, so a mistyped --work-dir cannot recursively delete an arbitrary tree

press

Produce a ready-to-flash image file from a build’s artifacts, verified and optionally personalized per unit (--hostname/--ssh-key/--wifi-ssid seed keys) or extended with per-site files (--copy/--deb/--embed-image, which re-assemble the image from the kept rootfs tar). boot2deb does not write devices — hand the pressed file to any flasher, dd included

argumentrequiredwhat it is
recipeyesRecipe whose artifacts to press (e.g. turing-rk1/forky)
outputnoThe image file to write, for a build with one artifact (a combined image or a u-boot deliverable). A split build is two files for two media and takes --boot-out + --rootfs-out instead
flagvaluewhat it does
--boot-out<BOOT_OUT>The boot image’s output file, for a split build — what goes onto the eMMC/SPI medium the board boots from
--rootfs-out<ROOTFS_OUT>The rootfs image’s output file, for a split build — what goes onto the disk the OS lives on
--hostname<HOSTNAME>Per-unit hostname, written into the image’s seed partition and applied by the device at first boot
--ssh-key<SSH_KEYS>, repeatableSSH public key (the full ssh-ed25519 AAAA... comment line), repeatable — appended to the default account’s authorized_keys at first boot
--wifi-ssid<WIFI_SSID>Wi-Fi network the device joins at first boot (images with NetworkManager only — every Wi-Fi-capable board’s has it). The per-site value that never belongs in a committed recipe
--wifi-psk<WIFI_PSK>WPA passphrase for --wifi-ssid (8-63 characters, or 64 hex digits). Omit for an open network. Stored as plain text in the seed partition, like every seed key
--static-ip<ADDR/PREFIX[,GW[,DNS...]]>Static IPv4 (ADDRESS/PREFIX[,GATEWAY[,DNS...]]) for the connection the seed sets up: the Wi-Fi profile when --wifi-ssid is present, the wired interface otherwise — NetworkManager or dhcpcd, whichever the image carries. Omit for DHCP
--copy<SRC:DEST>, repeatableCopy a host file into the image at an absolute path (SRC:DEST), repeatable — a site config, a one-off script. Mode 0644 (0755 when the source is executable), owner root. Re-assembles the image from the kept rootfs tar, so the build must have run. A source named *.tmpl is a template: its {{image.<name>}} references (hostname, PARTUUIDs, suite, …) are expanded at press time and it lands at DEST
--copy-tree<DIR>, repeatableCopy a whole directory that mirrors the target rootfs, repeatable — DIR/etc/site.conf lands at /etc/site.conf. Every regular file and symlink under it is placed; directories are not, since the parents each file needs are created root-owned 0755. Same modes as --copy, and a *.tmpl file is expanded and lands without the suffix
--deb<PATH>, repeatableStage a local .deb (repeatable) for installation at first boot via dpkg -i. Dependencies already in the image resolve immediately; missing ones are fetched only if the board has network by then
--embed-imageCarry the recipe’s own compressed image artifact inside the pressed image (at /var/lib/boot2deb/install/), so the booted board can install itself to internal storage with boot2deb-install-to — the boot-from-card, install-to-eMMC workflow
--no-verifySkip the post-write verification of the pressed file. The press is not faster; only the re-read is saved
--dry-runPrint what would be pressed — artifacts, outputs, additions, seed keys — without writing anything
--layout<LAYOUT>Image layout override (combined | split), matching the build that produced the artifacts
--rootfs-label<ROOTFS_LABEL> (default rootfs)ext4 volume label / GPT partition name for a re-assembled rootfs — match the build --rootfs-label the artifacts were made with
--work-dir<WORK_DIR>Build scratch dir holding the artifacts (default: <root>/build/RECIPE)
--out-dir<OUT_DIR>Directory the build wrote its artifacts to (default: WORK_DIR/artifacts)

seed

Rewrite the per-unit seed partition of an already-pressed image file — the same personalization press applies, without re-pressing. With no keys the seed resets to the empty template. Takes a file: to re-personalize a card that is already written, edit seed.txt on its B2D-SEED volume directly

argumentrequiredwhat it is
imageyesThe pressed image file whose seed partition to rewrite
flagvaluewhat it does
--hostname<HOSTNAME>Per-unit hostname, written into the image’s seed partition and applied by the device at first boot
--ssh-key<SSH_KEYS>, repeatableSSH public key (the full ssh-ed25519 AAAA... comment line), repeatable — appended to the default account’s authorized_keys at first boot
--wifi-ssid<WIFI_SSID>Wi-Fi network the device joins at first boot (images with NetworkManager only — every Wi-Fi-capable board’s has it). The per-site value that never belongs in a committed recipe
--wifi-psk<WIFI_PSK>WPA passphrase for --wifi-ssid (8-63 characters, or 64 hex digits). Omit for an open network. Stored as plain text in the seed partition, like every seed key
--static-ip<ADDR/PREFIX[,GW[,DNS...]]>Static IPv4 (ADDRESS/PREFIX[,GATEWAY[,DNS...]]) for the connection the seed sets up: the Wi-Fi profile when --wifi-ssid is present, the wired interface otherwise — NetworkManager or dhcpcd, whichever the image carries. Omit for DHCP
--dry-runPrint what the seed would say without writing anything

try

Boot the built image under QEMU before it is flashed, and assert the userland works: systemd reaches multi-user with no failed unit, the generated password logs in, first-boot completes, the on-image selftest passes in userland mode — and a second boot of the same disk still does, the check no single-boot smoke test covers. Boots the suite’s generic kernel as a fixture; the shipped kernel and the board are not under test

argumentrequiredwhat it is
recipeyesRecipe whose built image to boot (e.g. turing-rk1/forky); run boot2deb build first
flagvaluewhat it does
--timeout<TIMEOUT> (default 900)Seconds one boot may take to reach a login prompt (and to settle after it). The default is sized for TCG emulation on a loaded host; with KVM a boot takes a fraction of it, and the timeout is a ceiling, not a wait
--keep-diskKeep the booted disk copy under the work dir after the run, for a post-mortem or to boot it by hand. Its account password was changed at first login; the run’s report prints the one now set
--refresh-fixtureDiscard the cached fixture kernel and harvest the suite’s current one — how a new point release of the generic kernel is picked up
--work-dir<WORK_DIR>Build scratch directory (default build/<recipe> under the config root) — where the disk copy and the fixture kernel live
--out-dir<OUT_DIR>Where the build’s artifacts were written, when not the default <work-dir>/artifacts
--keyring<KEYRING>Debian archive keyring for the fixture-kernel root’s bootstrap (default: the vendored debian-archive-keyring.gpg)