.agents/skills/release-devbox/SKILL.md
scripts/release.ts owns every mechanical step and the order they run in. Your
job is the judgment: read what's shipping, recommend a version, write the title
and notes, and help the user pick how to release.
Two entry points, both of which walk the whole pipeline:
| Command | What it does |
|---|---|
devbox run draft-release | Builds the release, leaves it as a draft for review |
devbox run publish-release | Builds and takes it live, or finishes an existing draft |
Read-only helpers: devbox run release-changes and devbox run release-status.
devbox run release-changes
This prints the commits since the last release grouped by kind (breaking /
features / fixes / other), the recommended version, and whether flake.nix
needs bumping. Read it before saying anything about the release.
The recommendation follows devbox's own history: it's pre-1.0, so breaking
changes take a minor bump (0.17.5 โ 0.18.0) and everything else takes a
patch bump โ 0.17.4 shipped new features as a patch. Say what the script
recommends and why, but sanity-check it against the actual diff. A release that
removes whole subsystems deserves a minor bump even if nobody wrote feat!:.
Present the three options and let the user choose โ don't assume:
devbox run draft-release) โ builds everything and stops at
a draft. Right when the notes need review, or when the release is being
coordinated with an announcement. This is the safe default.devbox run publish-release) โ same pipeline, then
takes it live. Right for routine patch releases.devbox run publish-release) โ if a draft is
already sitting there, the command lists it and offers to finish it. Check
with devbox run release-status first.The script prompts for these in $EDITOR when a human drives it. When you're
driving, write them yourself and pass them as flags โ that's the point of doing
this through an agent.
Get the raw material from GitHub's generated changelog:
gh api repos/jetify-com/devbox/releases/generate-notes \
-f tag_name=<version> -f previous_tag_name=<prev> -f target_commitish=main --jq '.body'
That's a dump of PR titles. Rewrite it into user-facing notes in the house style that 0.17.4 established:
## What's Changed
### ๐ฅ Breaking Changes
* **What was removed** โ what users must do instead, by @author ([#1234](https://github.com/jetify-com/devbox/pull/1234))
### โจ New Features
* **Short bold lead-in** โ what changed and why a user cares, by @author ([#1234](...))
### ๐ Bug Fixes
* Plain one-liners for small fixes, by @author ([#1234](...)).
* **Group related fixes** โ combine several PRs into one bullet when they share
a root cause ([#1234](...)) and ([#1235](...)), by @author.
### ๐งน Maintenance
* Dependency bumps, CI work, docs. Group aggressively; nobody reads this section
line by line.
## New Contributors
* @newperson made their first contribution in https://github.com/jetify-com/devbox/pull/1234
**Full Changelog**: https://github.com/jetify-com/devbox/compare/<prev>...<version>
Rules that matter:
by @author and its PR link.\`. goreleaser interpolates the body into the
Discord announcement template and bare backticks break it.For the title, default to the bare version (0.18.0). A short theme suffix is
fine when the release has one: 0.18.0 โ Devbox goes fully local.
Show the user the title and full notes and get explicit sign-off before running anything. That's the last checkpoint before it goes live.
Save the notes to .context/release-notes-<version>.md, then:
node scripts/release.ts --draft \
--version 0.18.0 \
--title "0.18.0" \
--notes-file .context/release-notes-0.18.0.md \
--yes
Swap --draft for --publish to go live. Notes on driving it as an agent:
--yes is required when you run it. Its confirmation prompts need a TTY,
and your shell doesn't have one โ without --yes it stops with "this step
needs an answer but stdin is not a terminal". Only pass it after the user has
signed off; it's skipping their checkpoint, not adding one.cli-release. Run it in the
background and check back, rather than letting the call time out.If flake.nix needs bumping, the script stops and tells you to open a PR. That
bump has to merge into main before the tag is pushed, otherwise the tagged
commit ships the wrong version string. Do that, wait for the merge, then re-run.
Don't work around these; they're why the script exists.
use_existing_draft and attaches
its artifacts to whatever draft it finds, keeping the body. With no draft it
creates one whose body is a bare list of commit SHAs โ that's what shipped as
the 0.17.5 release notes.docker-image-release fires on the release event
and immediately downloads the release tarballs to bake into the image.
Publishing before goreleaser uploads them fails the Docker build. That's
exactly what happened on 0.17.3 and 0.17.5, both published from the GitHub UI,
which creates the tag and publishes in one action.GITHUB_TOKEN. That's why CI-created edge releases never
trigger docker-image-release, and why publishing can't just be a CI step.devbox run release-status reports the tag, draft, asset count, cli-release
result and the current flake.nix version in one shot.
| Symptom | Cause | Fix |
|---|---|---|
cli-release never started | Tag push didn't land | Re-run the same command |
cli-release failed in tests | Red main (see below) | Fix the test, re-run |
| Draft has 0 assets | goreleaser didn't find the draft | Confirm the draft exists, re-run |
| Published but installer serves the old version | cli-post-release failed or is still running | gh run list --workflow=cli-post-release.yml |
| Docker build failed | Published before assets uploaded | Re-run docker-image-release via workflow_dispatch with the tag |
Check these are still true before blaming the release itself:
main has been red since 2026-07-02. The macOS zig-hello-world example
test fails (error running script "run_test"). build.zig uses the
pre-Zig-0.12 API (.root_source_file = .{ .path = ... }) while devbox.lock
pins zig 0.11.0. This blocks all releases โ cli-release gates on the test
suite โ and has already killed seven consecutive weekly edge builds.flake.nix drifts. It sat at 0.17.3 through both the 0.17.4 and 0.17.5
releases. Preflight catches this now.