Skip to content

Releases: yoebuild/yoe

v0.10.5

09 May 16:54
797dc4a

Choose a tag to compare

  • Build progress bar. While a build is in flight the feed banner at the top
    of the screen swaps out for a live progress bar showing the percentage done,
    how many units have finished, and how many are still to build. The bar
    disappears and the feed banner returns once the build settles.

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.10.4

08 May 21:34
280c14e

Choose a tag to compare

  • Search bar clears with Ctrl+U. Readline's kill-line shortcut wipes the
    query input back to a blank bar in one keystroke — faster than holding
    Backspace or pressing \ to snap to the saved default. Live-applied like a
    backspace, so the unit list updates to "showing all" immediately.
  • Tab completions show up under the query bar. When the search input can't
    be advanced further (multiple equally-good matches), the candidate list now
    renders as a vertical column directly under the query bar — closer to the
    cursor than the previous horizontal blob at the bottom of the screen, and
    easier to scan for the next character to type. Long lists truncate with a "(N
    more — type a letter to narrow)" hint.
  • Fresh projects from yoe init build out of the box. The generated
    PROJECT.star now pins xz to the Alpine module, matching the canonical
    e2e-project template. Without this, kmod's depmod failed at image-assembly
    time because module-core's xz is static-only and doesn't ship liblzma.so.5.
  • Switching a unit/module to dev mode transfers far less data. The
    depth-limited fetch (last 100 / 1000 commits, last year, last month) now
    narrows to the unit's pinned ref instead of fanning out across every branch
    the upstream tracks, and adds --filter=blob:none so file content comes down
    on demand instead of all at once. For a Linux-kernel-sized repo that's the
    difference between a multi-gigabyte fetch and tens of megabytes; git log and
    git blame still work, and missing blobs are fetched lazily when needed.
  • TUI / makes refining an existing query faster. When you press / and
    the active query is non-empty, the bar opens with a trailing space so you can
    immediately type the next term — no need to press End or space first. A blank
    query still opens empty.
  • Toggle any unit or module between pinned and dev mode from the TUI. A new
    SRC column on the units and modules tabs surfaces whether each source dir is
    yoe-managed (pin), tracking upstream (dev), has commits beyond upstream
    (dev-mod), or has uncommitted edits (dev-dirty). Press u on a unit's
    detail page (or a module row) to switch between pin and dev — yoe asks whether
    to rewrite origin to SSH, then how much history to fetch (full / last 1000
    commits / last 100 commits) so the Linux kernel's full history doesn't have to
    come down every time. A spinner runs while the fetch is in flight so you can
    see something is happening. Once you're happy with a dev-mod HEAD, P
    captures it back into the .star pin so other people building the project
    pick it up. A dev* unit is left untouched at build time, so yoe build
    won't overwrite your working tree or undo in-flight changes.
  • TUI size column no longer overflows on big artifacts. Sizes like a 1003
    KiB kernel image render as 1003K instead of 1003.4K, keeping the column
    aligned. The decimal still shows for small values (e.g. 9.9K, 1.2M) where
    it carries useful precision.
  • Device hostname now matches the machine, not the image. A fleet of
    raspberrypi4s flashed with dev-image no longer all answer to
    yoe-dev.local; each board comes up as <machine>.local (e.g.
    raspberrypi4.local, qemu-x86_64.local) so they're distinguishable on the
    LAN out of the box. Set hostname = "..." on an image to override (e.g. a
    branded kiosk image).
  • TUI help bar reflects the active mode. While typing in the search bar, the
    bottom help row swaps to the keys that actually work there (type filter,
    tab complete, ⌫ delete, enter apply, esc cancel) instead of pretending
    b build, q quit, etc. still fire. Out of search-edit it shows the
    navigation shortcuts as before.
  • Tab in the search bar always shows progress. When Tab can't advance the
    input (multiple candidates with no common prefix to extend — most visibly when
    you've just opened the bar, or typed a single ambiguous letter), the candidate
    list now flashes in place of the help bar instead of silently doing nothing.
    Single-candidate completions still splice in. Empty pool flashes "no
    completions".

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.10.3

07 May 22:40
30742cb

Choose a tag to compare

  • docker-image starts dockerd at boot. Pulls in Alpine's docker-openrc
    package (which ships /etc/init.d/docker and the /etc/conf.d/docker config
    template upstream maintains) and adds the default-runlevel symlink at
    packaging time, so dockerd is supervised on a fresh boot without manual
    rc-update add.
  • prefer_modules on project() pins a unit to a specific module. Set
    prefer_modules = {"xz": "alpine"} in PROJECT.star and the xz unit
    registers only from module-alpine, regardless of which module wins the
    default last-module shadowing. Use it when module-core's source-built
    version of a package is broken or under-configured and the Alpine prebuilt is
    the right answer; the shadow appears on the Diagnostics tab the same way an
    ordinary cross-module shadow does.
  • modprobe works on the booted system. Image assembly now runs depmod
    inside the rootfs after apk add, so /lib/modules/<ver>/ carries a real
    modules.dep index instead of just bare .ko files. The kernel build still
    skips depmod (the toolchain container has no copy of it); the rootfs's own
    kmod supplies it via chroot.
  • Kernel ships container-runtime CONFIG by default. A container.cfg
    fragment (overlayfs, bridge/veth, the full netfilter chain including
    NFT_COMPAT so iptables-nft works, IPv4 + IPv6 NAT, namespaces, seccomp,
    cgroup BPF, eBPF) is merged into the kernel's defconfig during the linux
    unit's build, so dockerd and containerd start cleanly without per-image
    kernel customisation. The cost on non-container images is a few hundred KB of
    kernel modules that nothing references.
  • TUI flash remembers the last device. Picking and confirming a flash target
    writes flash_device = "/dev/sdX" to local.star, and re-entering the flash
    view positions the cursor on that device when it shows up in the candidate
    list. Reflashing the same SD card or USB stick is now f → Enter → y.
  • /etc/os-release now reports the project version. VERSION,
    VERSION_ID, and PRETTY_NAME come from version = "..." in PROJECT.star,
    so tools that read /etc/os-release (and humans on the device) can tell which
    build is running. Templates can reach the value as {{.project_version}}.
  • Image rows in the TUI show the project version. The image() class
    defaults each image unit's version to PROJECT_VERSION (from
    PROJECT.star), so the VERSION column in the units table — which used to be
    blank for image rows — now shows the version the resulting .img represents.
  • OpenRC replaces the old rcS startup script. Services now boot under
    Alpine's OpenRC service manager, so they get dependency ordering, supervised
    start/stop, and proper status/restart commands (rc-service sshd restart,
    rc-status) instead of the silent run-everything-in-/etc/init.d/S* pattern.
    Units declare services = ["sshd"] (plain names, no S40 prefix) and the
    resulting apk drops the script in /etc/init.d/ plus a runlevel symlink in
    /etc/runlevels/default/.
  • Source-built libraries auto-declare what they ship. Each .apk yoe builds
    from a destdir now lists provides = so:<soname>=<ver>-r<rel> for every
    shared library in the package, matching Alpine's convention. Alpine prebuilt
    packages whose upstream PKGINFO declares depend = so:libcrypto.so.3 or
    similar now resolve cleanly against yoe-source-built openssl, zlib, etc. —
    no manual SONAME bookkeeping in the .star file.
  • module-alpine packages now ship with their upstream metadata intact.
    Prebuilt Alpine apks pass through yoe's pipeline verbatim — only the signature
    is swapped for the project's key — so replaces, provides, triggers, and
    post-install hooks (busybox applet symlink creation, sshd privsep user adds,
    …) reach the on-target system the way Alpine intended. Image assembly drops
    --no-scripts so those hooks actually run; this fixes the no-/sbin/init
    kernel panic that hit when relying on Alpine's busybox.
  • Alpine packages no longer end up with doubled--r filenames. alpine_pkg
    splits upstream pkgver like 1.2.5-r11 into yoe's separate version + release
    fields, so the published apk is musl-1.2.5-r11.apk instead of
    musl-1.2.5-r11-r0.apk. Apk's solver finds the file at the URL it constructs
    from the index, fixing "package mentioned in index not found" on every
    module-alpine package.
  • noarch passthrough packages route correctly across the repo. apk-tools
    constructs fetch URLs from PKGINFO's arch = field (always
    <base>/noarch/<file> for noarch packages), but its solver only reads one
    arch's APKINDEX per repo. Three coordinated fixes:
    • Passthrough alpine_pkg units with arch = noarch publish under
      <repo>/noarch/ (where apk fetches them from).
    • Each per-arch APKINDEX now scans the sibling noarch/ tree at generation
      time, so the solver sees noarch packages from any arch's perspective.
    • A noarch publish refreshes every per-arch APKINDEX (since each one
      references those noarch entries).
    • Cache validation also looks under noarch/ for the published apk, so noarch
      units don't rebuild on every invocation.
  • base-files ships an Alpine-style runlevel baseline. OpenRC services
    cgroups, devfs, dmesg (sysinit), bootmisc, hostname, modules,
    sysctl (boot), and mount-ro, killprocs (shutdown) are now wired into the
    rootfs via /etc/runlevels/<level>/<svc> symlinks, so a fresh image boots
    with the hostname set, kernel modules loaded, the cgroup hierarchy mounted (so
    container runtimes don't trip on "Devices cgroup isn't mounted"), and shutdown
    that unmounts cleanly.
  • TUI SIZE column for images shows installed content, not partition size. An
    image whose machine reserves a 600 MB rootfs partition now reports the ~50 MB
    actually populated by apk add, so you can see what your image contains
    rather than how big the partition was sized.
  • New docker-image. Builds a dev-image-style rootfs that also ships Docker
    (engine, CLI, buildx, containerd, runc) so you can poke at the docker
    userspace on a yoe-built system. Kernel and init still need the container
    pieces before dockerd can actually launch a container — that's the next
    step.
  • Files tab on the unit detail page. Tab into a sortable list of every file
    the unit installs and its on-disk size — easy to spot the biggest payloads or
    confirm a binary actually landed where you expected without leaving the TUI.
  • Drop into a shell on the source. Press $ in the units tab or detail page
    to open a shell in the unit's checked-out source directory, or in the Modules
    tab to open a shell in a module's clone — handy for git status, spot-edits,
    or running an out-of-tree command without leaving the TUI.
  • VERSION column in the unit table. Each row now shows the unit's declared
    version next to its module, sortable from the o cycle, and the same version
    appears next to the unit name on the detail page — so spotting a stale pin or
    confirming what's about to build is a glance, not a file open.
  • TUI auto-follow no longer yanks the cursor mid-navigation. The units list
    scrolls to whatever is actively building only when you're idle — pressing j/k
    or typing a query keeps the cursor where you put it, while b still hands
    control back to the build so you can watch what's compiling.

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.10.2

05 May 20:43
75daa8f

Choose a tag to compare

  • yoe init lists module-core last so it wins shadowing. New projects now
    order modules so module-core's source-built units (busybox, openssl, …) take
    precedence over Alpine prebuilts and over module-rpi, avoiding image-assembly
    path collisions. Existing projects can move module-core to the end of their
    modules = [...] list in PROJECT.star to get the same behavior.
  • Images with network-config and busybox build again. A path collision on
    /usr/share/udhcpc/default.script (busybox ships an example script there;
    network-config installs the real one) was aborting apk add at image-assembly
    time.

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.10.1

05 May 20:25
42de3ad

Choose a tag to compare

  • TUI flash offers sudo chown on permission denied. Previously the flash
    view just showed "permission denied" and dead-ended — matching the CLI's
    behavior, the TUI now prompts to run sudo chown $USER /dev/... and retries
    the write automatically.
  • TUI home screen has tabs. Press tab to cycle between Units (the existing
    list), Modules (declared modules with git status), and Diagnostics (shadowed
    units and duplicate provides). The diagnostics tab carries a count badge so
    issues are visible from any tab.
  • --allow-duplicate-provides is on by default. No more passing the flag on
    every yoe invocation while the linux-firmware-* fan-out keeps tripping the
    strict check.
  • Modules renamed: units-*module-*. units-core, units-rpi,
    units-alpine, and units-jetson are now module-core, module-rpi,
    module-alpine, and module-jetson. Update module(...) URLs and any
    path = "modules/units-..." entries in your PROJECT.star.
  • helix actually runs on the device. Was previously bundled as a
    glibc-linked binary that failed silently with hx: not found; now uses
    Alpine's musl build.
  • Images that include apk-tools or libcurl build again. A collision
    between the source-built ca-certificates and Alpine's
    ca-certificates-bundle was aborting apk add at image-assembly time.
  • SIZE column in the TUI updates as each unit finishes. No more waiting
    for the whole image to complete before transitive deps show their size, and
    partial sizes survive a mid-build failure.
  • Modules show their declared name. The TUI's MODULE column and any
    diagnostic that names a module now use the name set in MODULE.star's
    module_info(name = ...) instead of the path basename — so a module
    referenced via path = "modules/units-core" displays as core if that's what
    it calls itself. Falls back to the path basename when no module_info is
    declared.
  • dev-image ships helix instead of vim. Drops the editor entry that
    was unintentionally resolving to Alpine's gvim (and its X11/GTK runtime
    closure), keeping the image lean.
  • Unit detail shows what uses it and what it pulls in. The detail page now
    opens with two new sections above the build log: USED BY traces back
    through runtime_deps to show which packages you wrote in image() pulled this
    unit in, e.g. dev-image → yazi → libpango → cairo, so you can answer "why is
    this on my device?" at a glance. PULLS IN shows the unit's runtime-deps as
    a tree. Drilling into an image starts from exactly the packages you wrote in
    image() (plus machine packages), then expands each one to show what it drags
    in transitively.
  • TUI layout overhaul. Title and banners stay put when the list is long, the
    help bar is always the last line, status messages flash in its place, and
    pressing / turns the Query: header itself into the search input. Long unit
    names get an ellipsis instead of breaking column alignment.
  • Sort columns from the keyboard. Press o to cycle the unit table through
    NAME → CLASS → MODULE → SIZE → DEPS → STATUS; O flips direction. The
    active column shows or next to its label.
  • Help bar highlights shortcut keys. Each shortcut letter renders in amber
    matching [yoe], so you can scan keys without reading every word.
  • Cursor follows the work. The TUI opens with the cursor on the default
    image, jumps to whatever unit is currently building, and the cursor's full
    unit name is always visible just above the help bar.
  • Configure the default image per developer. local.star accepts
    image = "..." to override defaults.image. Pick an image from the new
    Image entry in Setup (s) and the choice is saved — and the active search
    re-anchors to in:<image>. Flows through yoe run, yoe config show, and
    the TUI.
  • More columns in the unit table. Each row now also shows the module that
    owns the unit (after shadow resolution), its install size after build (.img
    size for images), and how many units it pulls into a runtime closure — so
    bloat is easy to spot before flashing.
  • yoe --help works and lists global options. --help, -h, and help
    all print usage, including --project, --show-shadows, and
    --allow-duplicate-provides.

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.10.0

05 May 14:54
ffdfe0d

Choose a tag to compare

Errata: due to an issue in the alpine module, you must currently run with:
yoe --allow-duplicate-provides.

  • BREAKING CHANGE This project has been moved to a new Github org:
    https://github.com/yoebuild. yoe update from previous versions will not work
    and you will need to download and manually install the 0.10.0 binary.
  • TUI search is now a query language; defaults to your image's working set.
    Press / to filter by type:, module:, status:, or in: (closure of any
    unit), in addition to plain substring search. Tab completes field names and
    values. The TUI starts filtered to in:<your-default-image>, so a project
    with thousands of units shows just what your image needs. Press S to save
    the current query to local.star as the new default; press \ to snap back
    to it. The header shows Query: … Units: N/M so you always know how many of
    the project's units the current filter is showing.
  • Use apk-tools from alpine layer for now. It is built with docs.
  • yoe repo clean drops stale .apk files. Removes any .apk in the
    project's local repo whose name+version no longer matches a current unit (unit
    deleted, version bumped, release suffix changed) and re-signs the regenerated
    APKINDEX. Without this, apk add happily picks the highest- versioned
    candidate even when that candidate is leftover from a since-deleted unit —
    which is how a LUA=no-built apk-tools ("apk has been built without help")
    could keep winning over Alpine's prebuilt long after the source unit was
    removed.
  • Source-built openssl no longer collides with Alpine's libcrypto3 /
    libssl3.
    The openssl unit in units-core now declares
    provides = ["libcrypto3", "libssl3"], so any package whose runtime_deps
    reach libcrypto3 or libssl3 (e.g. units-alpine's apk-tools) routes
    back to the source-built openssl instead of pulling Alpine's split libcrypto3
    /libssl3 packages alongside. Without this, image-time apk add aborted with
    trying to overwrite usr/lib/libcrypto.so.3 owned by openssl-3.4.1-r0.
  • units-alpine now lives in its own repo. yoe init and the e2e project
    pull units-alpine and units-jetson from github.com/yoebuild/ instead of
    carrying units-alpine inside this repo. Existing projects with
    path = "modules/units-alpine" should switch to a remote module(...) ref.
  • Shadow notices are off by default. Cross-module unit shadowing and
    provides overrides no longer print a stderr notice on every load. Pass
    --show-shadows to see them when you actually want to audit which module won.
  • --allow-duplicate-provides lets multiple units share a virtual. When
    set, units in the same module may declare the same provides (apk-style "any
    of these satisfies"); the first one wins for PROVIDES lookup. Needed for
    units-alpine's linux-firmware-* fan-out, where ~100 packages all provide
    linux-firmware-any.
  • patches= resolves relative to the unit's own .star file directory. A
    unit can now ship its patches alongside its definition (e.g.
    units/bsp/foo/patches/0001-fix.patch next to units/bsp/foo.star), and the
    same patches=["patches/foo/0001-fix.patch"] works whether the unit is loaded
    from a local module override or a fetched remote module. Previously patches
    were resolved against the project root, which meant module-shipped patches
    couldn't be found unless every consumer copied them.

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.9.1

01 May 16:12
bcc7bca

Choose a tag to compare

  • yoe deploy <unit> now installs the package's runtime deps too.
    Previously it only built and published the named unit, so deploying a package
    with runtime_deps outside what the device already had on disk failed with a
    cryptic apk add error like sqlite (no such package). Deploy now walks the
    full runtime closure (the same expansion image() does at image-build time),
    so every transitive dep ends up in the feed before apk add runs.
  • Deploy refreshes the device's apk index every time. The on-device
    apk update step now uses apk --no-cache update, forcing a refetch of every
    repo's APKINDEX instead of trusting whatever is in /var/cache/apk/.
    apk-tools 2.x can otherwise hold onto a stale index across a yoe-dev rebuild
    and silently miss packages you just published.
  • Added sqlite unit

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe-NG is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.9.0

01 May 15:51

Choose a tag to compare

  • New design doc on libc and init choice. docs/libc-and-init.md lays out
    why yoe is musl + OpenRC + Alpine today, where that stack works (gateways,
    IoT, networking gear), where it doesn't (Jetson, vendor BSPs, Adaptive
    AUTOSAR), and the planned rootfs-base abstraction that would let a single yoe
    codebase serve both Alpine and Ubuntu/L4T projects. Establishes the invariant
    that yoe stays apk-native on every target — Debian-derived bases get a
    deb_pkg conversion class, not dpkg/apt on the device.
  • Pull packages straight from Alpine. A new units-alpine module wraps
    prebuilt Alpine .apk files as yoe units via the alpine_pkg() class — no
    source build, no patches, just fetch + verify + repack. musl and
    sqlite-libs ship today; add more by pinning a version and sha256.
  • musl now comes from Alpine. The hand-rolled musl unit that copied the
    dynamic linker out of the build container is gone; musl is now an Alpine apk
    wrapped by alpine_pkg(). Output is byte-identical to the Alpine package
    other projects already ship.
  • .apk URLs work as a source type. Yoe's source workspace now recognises
    .apk extensions and bare-copies them so the unit's install task can extract
    the multi-stream gzip with GNU tar. Bare-copied sources also keep their URL
    filename, so install steps can reference the file by name instead of by cache
    hash.
  • Override an upstream unit by name. Define a unit with the same name in a
    higher-priority module (or in the project itself) and it shadows the upstream
    one — no provides boilerplate needed. The project root beats every module,
    and later modules beat earlier ones. A notice on stderr tells you which one
    won.
  • Deploy from the TUI. Press D on a non-image unit to deploy it to a
    running yoe device — host prompt is pre-filled from the last-used target,
    build + ssh + apk add output stream into the view, and the host is saved back
    to local.star on success.
  • Deploy actually updates the device's apk index. yoe deploy and
    yoe device repo add previously wrote to
    /etc/apk/repositories.d/yoe-dev.list, which apk-tools 2.x ignores. They now
    append a marker block to /etc/apk/repositories so the next apk update
    actually fetches the dev feed and apk add <unit> finds the freshly built
    package.
  • TUI starts a feed automatically. When you launch yoe, it brings up the
    project's apk feed (or reuses one already running on the LAN), so devices
    configured with yoe device repo add can pull packages without any extra
    setup. Status is shown in the header.
  • SSH target shorthand. yoe deploy and yoe device repo {add,remove,list}
    accept [user@]host[:port] — e.g. yoe device repo add localhost:2222 for a
    QEMU vm or yoe deploy myapp pi@dev-pi.local:2200. The --ssh-port flag is
    gone.
  • APK live deployment tooling. yoe deploy <unit> <host> builds and
    installs a unit on a running yoe device with full apk dependency resolution.
    Pair with yoe serve and yoe device repo add to keep a device pointed at
    your dev feed for ad-hoc apk add from the device. See
    docs/feed-server.md.

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe-NG is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.8.8

01 May 15:52

Choose a tag to compare


To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe-NG is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.

v0.8.6

30 Apr 21:37
170283c

Choose a tag to compare

  • Container runtime build path documented.
    docs/containers.md now walks through what it takes to
    ship Docker, containerd, and runc on a musl yoe rootfs — why prebuilt "static"
    binaries don't work, the per-component build breakdown, and how cgo units like
    runc plug into yoe's existing Go toolchain and toolchain-musl container via
    deps instead of needing a new Go+GCC container image.
  • Rename debug units to dev.
  • Expand roadmap. Reorganized as a pointer index into the
    design docs, with new sections for the app-developer build/deploy loop,
    hardware access, testing, self-hosting, and distribution variants.
  • New testing design doc at docs/testing.md covers the
    planned yoe test driver, build-time package QA, on-device upstream tests
    (Yocto ptest analog), image smoke tests, and CI integration.
  • Kernel modules now ship in images — the linux, linux-rpi4, and
    linux-rpi5 units previously built only the in-tree kernel image, so drivers
    compiled as loadable modules (Wi-Fi, USB, sound, many filesystems) were
    silently dropped. Modules are now built and installed to
    /lib/modules/<kver>/ in the rootfs, so modprobe finds them at runtime.
  • Fix rPI4 builds package arch did not match what apk was expecting.

To update, run: yoe update
Or download the binary for your architecture and place it in your PATH.
Note: Yoe-NG is in heavy development. We recommend cleaning your build directory and re-creating projects (yoe init) with each new release.