Skip to content
View as .md

Releases

arbe ships as standalone binaries built with bun build --compile for darwin-arm64, linux-x64 (Linux ARM and Intel Mac deferred — scripts/release-build.ts TARGETS is canonical). This page is the durable contract — installer scripts, Quickstart, and release tooling all reference it. Change here first, then update consumers.

Versioning is the semver in apps/cli/package.json; commit SHA + UTC build date are baked in via --define process.env.ARBE_BUILD_COMMIT / process.env.ARBE_BUILD_DATE. arbe --version prints arbe <version> (<short-commit>, <yyyy-mm-dd>) (or arbe dev in dev). arbe upgrade compares only the version string against latest.json — commit SHA and date don’t affect the upgrade decision.

dist/release/latest/
arbe-<target>.tar.gz # single `arbe` at archive root
SHA256SUMS # one per line, sorted
release-latest.json # → arbe/latest.json (mutable, 60s cache, must-revalidate)
release-<version>.json # → arbe/<version>.json (immutable, 1y)

R2 holds two pointers to the same bytes: arbe/latest/ (mutable — newest published build) and arbe/<version>/ (pinned, never overwritten in practice). Manifests at arbe/latest.json / arbe/<version>.json follow LatestReleaseManifest (apps/cli/src/update/shared.ts) — version, commit, published_at, artifacts.<target>.{url,sha256,size} all required. Always fetch the tarball and SHA256SUMS from the same prefix together — latest/ is mutable so they can mismatch mid-publish; latest.json is the only stable metadata pointer; the commit SHA baked into the binary is authoritative for “what build do I have.”

Installer at apps/www/static/install.sh (one-liner: curl -fsSL https://arbe.0sk.ar/install.sh | sh) reads the manifest, picks target by uname, downloads + verifies sha256, drops arbe in $ARBE_INSTALL_DIR (default ~/.local/bin). POSIX sh, no jq/python — only curl/wget, tar, sha256sum/shasum. Knobs: ARBE_VERSION=latest|<x.y.z>, ARBE_TARGET=<target> (cross-arch testing), ARBE_INSTALL_DIR=<path>. Drift is bounded by the manifest schema.

Cut a release: bun run release:bump [patch|minor|major|x.y.z] bumps apps/cli/package.json, jj-commits only that file, advances the release bookmark, and pushes (--dry-run writes the version but stops, printing manual jj steps). The cli-release GitHub Action runs release:build + release:upload against R2 on pushes to the release branch. CLOUDFLARE_ACCOUNT_ID + CLOUDFLARE_API_TOKEN repo secrets do the auth — wrangler picks them up automatically; one-time setup in system/deployment.

Break-glass: bun run release:build then bun run release:upload mirror manually; local invocation needs bunx wrangler whoami authed against the right Cloudflare account. Always overwrites. Cache-Control is set per-key on upload — latest/* and latest.json get max-age=60, must-revalidate; <version>/* and <version>.json get max-age=31536000, immutable. Releases land on the edge within ~60s.

Code: scripts/release-build.ts, scripts/release-upload.ts, scripts/release-bump.ts, apps/cli/src/update/shared.ts (LatestReleaseManifest), .github/workflows/cli-release.yml.
See cli, system/deployment.