Skip to content

v0.2.1

Choose a tag to compare

@github-actions github-actions released this 06 Sep 16:04
· 37 commits to main since this release

devbox 0.2.1 — a stopped Lima box boots again, and the collector keeps every frame

If you run devbox on Lima, read this before you stop a box. A NixOS box
created by 0.2.0 — or by any earlier release — does not boot again after
devbox stop. Devbox recorded Lima's cidata mount in the guest's fstab by
UUID, and Lima regenerates that ISO, with a new UUID, on every start; the box
waits for a device that never appears and drops into emergency mode with no
sshd. It has been that way since v3, and it only bites on the second start,
which is why it took this long to surface.

  • A box that is still running repairs itself. The next devbox command that
    enters it — devbox exec <box> -- true is enough — rewrites the mount by
    label and runs one nixos-rebuild, about nine seconds. devbox status does
    not do it; it does not enter the box.
  • devbox stop does that repair for you first, and refuses to stop the box
    if the repair fails, because stopping is the step you cannot undo. It stops
    normally when the box is not running, when it cannot probe the box to judge,
    and when you pass --force — that last one with a warning.
  • A box that is already stopped and will not boot cannot be recovered.
    There is no sshd to reach it through and the line to change lives inside the
    guest's filesystem. devbox destroy it and create it again. Anything in its
    overlay that was never devbox commited is lost, which is the expensive part
    of this bug.

Unrelated to the mount: every box built before 0.2.1 does one extra
nixos-rebuild on the next command that enters it
, so it picks up this
release's guest-side changes. It happens once per box, and it is not a hang.

Fixed

  • Lima boxes did not boot after a stop — the cidata mount was pinned by a
    UUID that changes on every start. Present since v3.
  • The collector dropped frames when an agent disconnected. A failed
    keepalive cancelled the read loop through a select!, discarding frames that
    had already arrived. The read loop is now the only thing that ends a
    connection.
  • A run could come back empty without saying why. A collector handover
    killed the stdio agent it owns — the only channel a run's events travel on.
    Handovers and agent updates now wait for a run in flight; a run whose capture
    really was interrupted says so in its report, and a plain re-attach is no
    longer reported as one.
  • The guest had two homes. Devbox created /home/<user> while Lima's
    cloud-init had already made /home/<user>.guest, and sshd resolves keys from
    the passwd entry — so any ssh connection that did not ride Lima's own master
    was refused, and devbox wrote the gitconfig and tool settings where the shell
    would not read them. The passwd home now follows the login shell, and the
    guest user is read from the box rather than guessed from a uid range.
    Existing boxes repair themselves.
  • Run ids could spin forever when two threads minted one in the same
    millisecond.
  • devbox.toml with no [mounts] table produced a box whose /workspace
    was empty — mounted, but with none of your project in it — and said nothing.
    A missing table now means the default mount; an empty one still means "mount
    nothing", which is the only way to say that.
  • incus-agent no longer fails every five seconds on a Lima box.
  • Daemons are replaced by process group rather than by a single pid, so a
    takeover no longer leaves a transport attached to a guest; broker daemons are
    taken over by binary hash like the collector; a daemon holding its lock with
    an unreadable sidecar is replaced after three consecutive commands agree; a
    lock held by something that is not a devbox daemon is never signalled;
    handovers are written to the daemon log; and cargo test no longer leaves
    daemons behind (147 of them, 1.9 GB, had accumulated on one development host).
  • devbox mcp self names 2025-06-18 at initialize — the newest revision it
    actually conforms to — and answers a JSON-RPC batch with an explanation
    instead of "no method". An MCP session whose run row cannot be written now
    runs anyway, unrecorded and loudly so: the sandbox is the half worth keeping.

Added

  • devbox code receives the broker variables over ssh (SetEnv / AcceptEnv),
    so the editor's terminal reaches the broker the way devbox run does. Devbox
    probes a direct connection first, because ssh does not carry environment over
    the shared connection Lima hands out; if that probe fails it leaves the
    connection alone and says the variables will not be there.
  • devbox layer prune [--keep N] [--runs-older-than <age>] [--dry-run]. On its
    own it drops unclaimed checkpoints; --runs-older-than also releases the pair
    a run took, but only once that run has ended, aged out, and had its report
    written.
  • devbox store redact [--dry-run] rewrites exec argvs recorded before 0.2.0's
    redaction existed.
  • Runs record the file-event scope they ran under and the outcome of their start
    gate, and devbox export --run <id> carries that scope — a consumer counting
    file records needs to know what was not being watched.
  • An x86 CO-RE pair is committed, so cargo build on an x86-64 Linux host
    embeds the eBPF agent instead of falling back to the portable one.
  • Broker events carry no reading from the box's clock and sort by wall time.

Full Changelog: v0.2.0...v0.2.1