Skip to content

Releases: EstebanForge/construct-cli

The Construct CLI 1.17.19

Choose a tag to compare

@github-actions github-actions released this 01 Oct 18:33

[1.17.19] - 2026-10-01

Fixed

  • construct now verifies the host msb runtime before every microVM launch and says exactly what to fix when it cannot pair. The embedded microsandbox SDK refuses any host runtime except its own exact version with the cryptic no tested sandbox launch contract error — and since the 1.17.17 SDK bump embedded 0.7.3, a version no msb release ever shipped, every machine with any other msb failed at daemon create, often after pulling the image first. Both create entry points now fail fast before image acquisition, naming both versions and the side to update (msb update or ct sys self-update); 1.x hosts are refused as untested. The policy is shared with doctor's Host CLI/SDK Skew check (match OK, 0.x mismatch warning, 1.x error), which now reads the SDK version from the SDK itself instead of a hand-maintained constant that had silently drifted.
  • Embedded the 0.7.6 SDK, matching the current msb release, so version-matched hosts launch again.

The Construct CLI 1.17.18

Choose a tag to compare

@github-actions github-actions released this 01 Oct 16:17

[1.17.18] - 2026-10-01

Fixed

  • The microVM sandbox boots on the image ref the acquisition step verified. Image acquisition and sandbox creation resolved the boot image independently: acquisition verified the freshly pulled GHCR ref, but the create-time candidate walk could hand msb a listed-but-unusable legacy bare construct-box:latest entry instead, which msb then resolved at docker.io — registry error: Not authorized on every boot despite a fresh image, exactly what 1.17.17 upgraders hit after the migration wiped and re-pulled the cache. EnsureImage now returns the ref it verified on every path (local build, cached GHCR, fresh pull, pull-failure fallback), and the daemon and agent-install specs boot that ref directly; candidate resolution survives only as a fallback when no ref was threaded.
  • sys doctor --fix now recovers a still-starting msb daemon. The VM Backend check probed the daemon once and failed closed, while the same run's Baked Image pull auto-started the daemon two checks later and reported success — an incoherent report with no fix attempt, since msb starts its daemon on demand and a probe right after a crash can lose that race. Under --fix the check now retries bounded (3 attempts, 2 seconds apart) before declaring the backend broken and reports the recovery; a crash-looping daemon still fails with the existing suggestion, and plain doctor stays report-only.

The Construct CLI 1.17.17

Choose a tag to compare

@github-actions github-actions released this 01 Oct 14:22

[1.17.17] - 2026-10-01

Added

  • Agents pre-installed on the image can now update themselves in-guest. The image chowns the agent tier to the runtime user (/usr/local/lib/node_modules, the bin directory, and the baked binaries), so self-updaters like pi update --all, claude update, and codex update write their install prefix in place instead of failing on root-owned paths, while the system toolchain and entrypoint scripts stay image-owned and the image lane stays authoritative — a root-fs replace on image pull still reaches every machine. /usr/local/bin carries the sticky bit, so the runtime user can replace its own agent symlinks but cannot remove the root-owned entrypoint scripts the next boot runs as root.
  • pi now updates its extensions, models, and self inside the guest update routine. update-all.sh runs pi update --no-approve --models, and when the baked binary is user-writable also pi update --no-approve --all (self + extensions); on older images with a still-root-owned binary, self-update is skipped with a note while user-tier extensions and models still refresh. --no-approve keeps the non-interactive run from trusting project-local files.
  • sys update warns that in-VM updates revert on daemon recreate. Agent and OS package updates live in the VM's writable layer, which a daemon recreate (image update or config change) replaces: a successful foreground update now says so and reminds to run construct sys update again afterwards, and the recreate banner repeats the reminder at the moment the revert happens. On the compose backend the wording differs on purpose — its update runs in a throwaway --rm container, so agent and OS updates there are discarded on exit and only home-directory updates persist.

Fixed

  • Agent self-updates keep working on hosts whose uid is not 1000. The build-time chown hardcodes the image default (1000:1000) while ExecAsHostUser remaps the runtime user to the host uid on every non-1000 host, and the entrypoint re-chowned only the home tree, so the remapped user lost write access exactly where remapping is enabled. The remap branch now re-aligns the agent tier to the remapped id, probed so the recursive chown only pays when the numeric id actually changed.

The Construct CLI 1.17.16

Choose a tag to compare

@github-actions github-actions released this 01 Oct 12:32

[1.17.16] - 2026-10-01

Fixed

  • sys update no longer fails on topgrade's built-in pi step. topgrade 17.4.0 shipped a built-in pi step that runs pi update --self, and the image pins topgrade 17.7.0, so every in-guest update ran it against the baked root-owned /usr/local/bin/pi: pi refuses to self-update an npm-managed install on an unwritable path, the step fails, and topgrade exits 1, failing the whole pass. The run log naming the step pi (a [commands] entry would be named by its TOML key, Pi Coding Agent) proved the culprit was topgrade's binary detection, not the stale-config theory behind 1.17.14's derived-file refresh. The step is now disabled like claude_code (baked agents update on the image lane, never in-guest) in the shipped template, the generator, and the no-config fallback, with a test pinning the generated list. The disable list only carries step keys that exist in the pinned topgrade: an unknown key makes its config loader fall back to an empty default config and silently drop every other disable rule.
  • The host-exec shim no longer drops stdin that arrives late. The shim gated piped input on a single non-blocking peek, so a parent whose pipe write landed after shim startup shipped an empty stdin silently: a loaded CI runner hit exactly this on the 1.17.15 tag run, and any real-world writer slower than shim startup could too. The peek stays, keeping open-empty launcher pipes free of the 5s read budget, but it now polls across a 300ms grace window before concluding the pipe is empty, and a regression test writes stdin 100ms after start to pin the behavior.

The Construct CLI 1.17.14

Choose a tag to compare

@github-actions github-actions released this 01 Oct 02:34

[1.17.14] - 2026-09-30

Fixed

  • The microVM update no longer fails on a stale home topgrade.toml. msb reads topgrade.toml straight from the persistent home volume, and the update paths refreshed only the four mounted helper scripts, so the pre-1.17.0 [commands] pi self-update entry survived there: topgrade kept executing it against the baked root-owned /usr/local/bin/pi, the write failed, and one stale file failed the whole update pass. Both update paths now rewrite install_user_packages.sh and topgrade.toml from the current packages.toml before update-all.sh runs; an unreadable packages.toml skips the idle window and fails the foreground run, write failures still warn and continue, and the msb home copy of the install script stays owned by the daemon-start regeneration.
  • sys doctor reports the last failed update. The update-log check green-lit any readable log, so a run ending in update failed looked clean. It now parses the updater's log markers (anchored on the RFC3339 prefix, so tool output tee'd into the log cannot fake a run boundary), warns with the failed step names from the newest failed run, and points at construct sys update to retry.
  • sys doctor stops probing the docker API on microvm hosts. The stale-packages-volume check ran an OCI daemon probe even with backend = microvm and printed raw socket errors on hosts that opted out of container engines entirely. It now reports "Not applicable (runtime backend = microvm)" without probing.
  • Failure suggestions name a real command. Seven error paths told users to run construct doctor (never registered; the verb is construct sys doctor) and HOST-EXEC.md pointed at construct build (the verb is construct sys rebuild). All corrected.

The Construct CLI 1.17.13

Choose a tag to compare

@github-actions github-actions released this 28 Sep 17:46

[1.17.13] - 2026-09-28

Fixed

  • The microVM engine no longer boots a stale construct-box image after an image-tier template change. Three defects chained into a loop with no exit while the registry answered: msb caches a GHCR pull under the full ghcr.io ref (no tag aliasing) but the migration teardown removed only the bare local name, image acquisition pulled GitHub first and consulted the local docker store only when the pull failed, and the digest drift check compared a deliberately built localhost ref against the CI manifest digest, a comparison a local build can never win even at identical content. Together that meant construct sys rebuild composed an image nothing consumed and the sandbox kept booting the stale published image on every run. The cached-ref preference list now puts the localhost build first for both the boot image and the daemon digest label, the drift check compares the registry ref's own digest so local refs can never false-drift into a per-run re-download, sys rebuild and sys init on the microvm backend transition the fresh build into the msb cache, and the teardown removes all three cached ref forms. Migration completion notes and help text describe the real flow: both engines re-pull from GitHub Container Registry, and a local build happens only through construct sys rebuild or as the pull-failure fallback.

The Construct CLI 1.17.12

Choose a tag to compare

@github-actions github-actions released this 28 Sep 16:11

Full changelog: 1.17.11...1.17.12

The Construct CLI 1.17.11

Choose a tag to compare

@github-actions github-actions released this 28 Sep 12:03

[1.17.11] - 2026-09-28

Fixed

  • Stale shipped defaults in config.toml are reset on update and by sys doctor --fix. The update migration replaced container templates and merged packages.toml but never rewrote config.toml, so an old shipped default survived forever disguised as a user value: a real user's workspace_max_entries = 60000 from an older template kept the large-workspace warning firing long after the ceiling rose to 500000, and a stale daemon restart could not fix it because the value lives host-side in the config file, not in daemon state. Values that exactly match a stale shipped default are now rewritten in place with inline comments and spacing preserved; anything else (a deliberately chosen 75000, other sections, commented lines) is untouched, and the rewrite is idempotent. One rewrite path serves both the update migration and construct sys doctor --fix (which warns without the flag, naming the exact key old → new finding), so the two can never diverge, and future default bumps are one row in a table. The guard's fallback budget and the template's shipped default are now asserted equal by a test: the template writes the former while the guard falls back to the latter when the key is unset, so drift between them would make "unset" and "freshly written" behave differently.

The Construct CLI 1.17.10

Choose a tag to compare

@github-actions github-actions released this 27 Sep 22:35

[1.17.10] - 2026-09-27

Added

  • Pig joins the supported agent roster. Pig, the Go implementation of pi (pi-in-go.dev), is now a default supported agent: construct pig mounts ~/.pig into the sandbox, sys agents-md writes its rules to ~/.pig/agent/AGENTS.md, harness path-argument staging covers --extension and --session (pig 0.2.0 has no --mcp-config flag), both update verification loops check the binary, and first-run setup seeds ~/.pig/agent/auth.json like pi's. The binary is baked into construct-box at /usr/local/bin and pinned: pi-in-go.dev 403s GitHub Actions runner egress, so the image build fetches the installer from the PiG repository on GitHub and pins PIG_VERSION=0.2.0. Pig reads ~/.agents/skills natively, keeps its whole config under ~/.pig, and never touches pi's ~/.pi; existing sandboxes pick the new image up through the image-digest recreate check.

Fixed

  • sys agents-md now writes pi's rules file. Pi has shipped in the image and the agent registry for several releases, but it was missing from the rules distribution list, so ~/.pi/agent/AGENTS.md was never written inside the sandbox. It is registered alongside pig, which closes the gap for both.

The Construct CLI 1.17.9

Choose a tag to compare

@github-actions github-actions released this 26 Sep 01:08

[1.17.9] - 2026-09-25

Changed

  • The large-workspace warning is asked once per folder, not forever. Runs from a folder over the entry budget printed the warning and confirmed every single time; the Yes went nowhere. Acceptance now persists per folder (subdirectories included), so the first run asks and later runs skip the guard entirely - no scan, no warning, no confirm. A No still persists nothing, headless runs still fail closed, the home directory can never be accepted (the always-ask home warning stays), roots forget clears an acceptance, and roots list shows accepted folders. The entry budget also rises from 60000 to 500000: one modern JavaScript project alone carries 50-150k files, and the old ceiling predated both that reality and current virtiofs performance. The scan's time budget doubles to 3s so timeouts do not shadow the count.
  • construct sys daemon recreate gives the wipe-and-rebuild a first-class verb. The stale-image heal previously required raw msb rm construct-cli-daemon. Recreate stops the sandbox, removes it with its guest root disk, and cold-creates from the current image - under the daemon flock, refusing while live sessions exist, with a default-NO confirm and a warning that installed tools reinstall on the next boot. The home volume is a host bind, so user-level state survives.
  • A republished construct-box now reaches running daemons. A new construct.daemon.image_digest label records the digest a sandbox was created from; when the local image digest drifts (because the digest-refresh fix pulled a newer one), the daemon recreates exactly once with reason "construct-box image changed". Daemons predating the label upgrade the same way, and an unknown local digest never forces a recreate.

Fixed

  • Image refresh no longer false-drifts on every create. 1.17.8 compared the registry's multi-arch index digest against the platform manifest digest the image store actually caches - different layers of the manifest tree that never match - so every create re-downloaded the image, on Apple Silicon hosts too. The refresh now resolves the index down to the linux/ entry, which is what the store caches on both Intel and Apple Silicon hosts, and treats any resolution failure as "keep the cached image" instead of "download again".
  • The recreate decision can no longer be silently skipped. When the sandbox's stored config cannot be read (an msb record predating config persistence, or a corrupted one), every label-drift check was invisible behind a healthy-looking reconnect. The decision now prints a loud warning naming construct sys daemon recreate as the recovery.
  • The one-shot install sandbox no longer lingers. The first-run agent install ran in a dedicated sandbox that stayed behind as a stopped record forever, pinning the construct-box image and blocking image cleanup. It is now removed right after a successful install.
  • npm global reinstalls no longer fail with ENOTEMPTY. Interrupted npm runs leave dot-prefixed temp dirs under the global node_modules, npm never cleans them up, and every later install of the affected package fails renaming onto the occupied destination. The update script sweeps them before the reinstall loop, sparing .bin and keeping broken symlinks from stopping the sweep.