Releases: jdx/aube
v1.19.0: Node runtime switching, built in
The headline feature: aube now manages your project's Node.js version and aube's own version directly — no shims, no shell activation, no corepack dance. Pin Node via devEngines.runtime, .node-version, or .nvmrc and aube injects the right binary at every script and binary spawn. Pin aube via packageManager and aube re-execs itself under the requested version. Plus three install/scripts fixes around build approvals and override warnings.
Added
-
Node runtime switching (#861 by @jdx) — Projects can pin Node through
devEngines.runtime(pnpm 10.14+/11 compatible OpenJS spec),.node-version, or.nvmrc(searched upward, stopping at$HOME). Exact versions, ranges,lts,latest, and codenames likelts/jodall resolve. Resolution is zero-network on the hot path: PATH node → installed versions (mise installs at~/.local/share/mise/installs/reused read-only, plus aube's own~/.local/share/aube/nodejs/) → download per the newruntimeInstallersetting (auto|mise|aube;autodelegates tomise install node@<exact>when mise is on PATH, falling back to a SHASUMS256-verified nodejs.org download honoringnodeDownloadMirrors.release). The switched Node is injected intoaube run/aubr,aube exec(includingnodeenv shebangs),aubx/dlx(resolved from the original cwd), root + dep lifecycle scripts, and the build jail — and exported asnpm_node_execpath/NODE. Projects with no pin behave exactly as before, with nonode --versionprobe.Engines interplay:
engines.node/engineStrictnow validate against the switched node. The newruntimeOnFailsetting (download|error|warn|ignore) is the air-gapped-CI override; version files default todownload, baredevEnginesto the spec'serror. Lockfile pins use pnpm 10.14+'s exactnode@runtime:shape with per-platform URLs andsha256-integrity — and parsing them doubles as a compat fix for pnpm-11 lockfiles aube previously misread as registry deps. -
aube runtimeCLI (#861 by @jdx) —aube runtime set node <version>(pnpm 11 parity — writesdevEngines, installs, records the pin;-gdelegates tomise use -g) andaube runtime list.aube doctorgainsnode-source,node-requested,node-provenance, andnode-binrows.aube runtime set node 22.11.0 aube runtime list -
aube self-version switching (#861 by @jdx) —
managePackageManagerVersions(previously a documented no-op, default on, pnpm 10 parity) now re-execs aube under the version requested bydevEngines.packageManager(ranges) orpackageManager: "aube@<exact>". The switch happens before dispatch — soaube installand any chained auto-installs run under the pinned binary — and preserves theaube/aubr/aubxmulticall name. A guard env degrades a broken install to a warning rather than an exec loop. Self-downloads are verified against GitHub's server-computed release asset digests (assets[].digest, tamper-evident under immutable releases), with release metadata served from mise-versions.jdx.dev (CDN-cached, no rate limits) and falling back to the GitHub API (honoringGITHUB_TOKEN/GH_TOKEN, scoped to api.github.com),.sha256siblings for custom mirrors, then TLS-only. SettingmanagePackageManagerVersions=falserestores the previous strict-validation behavior. Intel macOS has no published asset and errors with a pointer to mise.
Fixed
-
(scripts) Require exact source keys for non-registry build approvals (#858 by @jdx) — Source-backed dependencies (
file:,git:, raw tarballs) no longer inherit lifecycle build approval from bare package names orname@semverpins. They must be allowed via an exact source key — e.g.esbuild@file+abc123— with separateallowed_sources/denied_sourcessets inBuildPolicy. WorkspaceonlyBuiltDependenciesby name now correctly skipsfile:postinstalls until the source key is approved. Graph hashing also folds local source specifiers into the package id, so different file/git bytes at the same manifest version get distinct virtual-store hashes (with cascade to parents). -
(scripts) Match pnpm-style URL source keys for build approvals (#860 by @jdx) — Follow-up to #858: non-registry approval keys now use the pnpm-authored shapes (e.g.
dep@file:vendor/depordep@<tarball-url>) instead of lockfiledep_pathbases.allowBuildskeys that mix semver and URL/source specs in a||union are rejected (both orderings) with a clear error. Lifecycle-script docs and the generatedallowBuildssettings reference now spell out the exact source-key shapes. -
(install) Warn on deprecated
$override refs (#859 by @jdx) — Mergedoverrideswhose values start with pnpm's deprecated$reference syntax now logWARN_AUBE_OVERRIDE_DOLLAR_REF_DEPRECATED, pointing users toward catalog entries. Resolution and drop behavior are unchanged; the existingWARN_AUBE_OVERRIDE_MISSING_DEPpath still runs for unresolved$refs.
Changed
- Refresh benchmarks for v1.18.2 (#851 by @mise-en-dev) — Public warm-install ratios: vs Bun 7× (unchanged), vs pnpm 9× → 6×. Repeat-test: vs Bun 5× (unchanged), vs pnpm 37× → 29×. Absolute aube warm-install times moved from 272ms → 383ms on the refreshed run.
Full Changelog: v1.18.2...v1.19.0
💚 Sponsor aube
aube is part of jdx.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at jdx.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.18.2: Project moves to jdx
A maintenance release that completes aube's move from the endevco namespace to jdx. There are no behavior changes — but if you install aube from npm or Homebrew, the package coordinates have moved.
Changed
-
Project migrated to the
jdxnamespace (#845 by @jdx) — Repository, docs, package metadata, and release pipelines now live underjdx. User-visible coordinates:- npm:
@jdx/aube(previously@endevco/aube) - Homebrew tap:
jdx/homebrew-tap - Repository: github.com/jdx/aube
- Docs: aube.jdx.dev
Cargo.toml,README.md,SECURITY.md,LICENSE, generated CLI/settings/error-code references, Debian/PPA/COPR packaging, and theaube sponsorsblurb all point at the new locations. No install, resolver, or lockfile behavior changed in this release. - npm:
Upgrading
If you install aube via npm or Homebrew, update the package name on your next install:
# npm
npm install -g @jdx/aube
# Homebrew
brew install jdx/tap/aubeExisting installs continue to work; only fresh installs need the new coordinates.
Full Changelog: v1.18.1...v1.18.2
💚 Sponsor aube
aube is part of jdx.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at jdx.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.18.1: Conflict-aware lockfiles and verified tarballs
A small patch release focused on install robustness: lockfiles with Git merge conflict markers now recover gracefully, aube update --global works from anywhere, and lockfile tarball URLs are verified against the registry before download.
Fixed
-
(install) Regenerate conflicted lockfiles (#843 by @jdx) — When
aube-lock.yamlstill contains Git conflict markers (<<<<<<<,=======,>>>>>>>), install now treats it as a recoverable prefer-frozen parse failure rather than aborting. It emits the newWARN_AUBE_LOCKFILE_CONFLICT_MARKERSwarning and regenerates the lockfile frompackage.json, so a plainaube installafter a messy merge just works. -
(update) Support global updates (#840 by @jdx) —
aube update --global(andaube update -g <pkg>) now routes through the global install directory instead of requiring a projectpackage.json, so it works from any directory — including outside a repo. Each global install runs the normal update pipeline with--latestand exact manifest pins, then bin shims are relinked and stale executables removed. Named packages resolve by alias; unknown names fail withnot globally installed. When combined with a workspace--filter,--globaltakes precedence and leaves workspace manifests untouched. Fixes #839.aube update -g # update every globally installed tool aube update -g prettier # update a single global tool
Security
- (install) Verify lockfile tarball URLs (#842 by @jdx) — When the lockfile pins an explicit registry tarball URL (e.g.
lockfile-include-tarball-url=trueor npm-alias entries), install now fetches per-version registry metadata and comparesdist.tarballto the lockfile URL before downloading. Mismatches abort with the newERR_AUBE_TARBALL_URL_MISMATCH(exit 34). Exact matches pass, and lockfile URLs onregistry.npmjs.orgare still accepted on alternative hosts when the/-/…tgzpath matches, so Verdaccio and other local mirrors continue to work — but tampered paths or arbitrary hosts impersonating npm are rejected.
Changed
- Refresh benchmarks for v1.18.0 (#841 by @mise-en-dev) — Warm-install ratios improved from 5× to 7× vs. Bun; vs. pnpm holds steady at 9×.
Full Changelog: https://github.com/endevco/aube/compare/v1.18.0...v1.18.1
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.18.0: sponsors command & repository field normalization on publish
A small feature + fix release: a new aube sponsors command and a publish-time fix that normalizes the repository manifest field for stricter registries.
Added
-
aube sponsorscommand (#824 by @jdx) — A new top-level subcommand that acknowledges 37signals and links to the canonical en.dev sponsor pages. The root README also gains a "Sponsored by 37signals" line.aube sponsors
Fixed
- (publish) Normalize string
repositoryfields in the publish manifest (#826 by @jdx) — Whenpackage.jsoncontains a stringrepositoryvalue, thePUTbody now rewrites it to{ "type": "git", "url": "<normalized>" }, matching npm/pnpm 11.5.1 behavior. Shorthand forms (owner/repo,github:…,gitlab:…,bitbucket:…) expand to fullgit-suffixed HTTPS URLs; explicithttps,git@, and URL fragments are preserved, and existing object-shapedrepositoryvalues are left untouched. This unblocks publishing to registries that reject bare-string repository fields.
Changed
- Refresh benchmarks for
v1.17.1(#820 by @mise-en-dev) — Warm-install ratios vs. Bun improved from 3× to 5×, and vs. pnpm from 5× to 9×.
Full Changelog: https://github.com/endevco/aube/compare/v1.17.1...v1.18.0
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.17.1: CI runner revert
A CI-only patch with no user-facing changes — published to revert the GitHub-hosted runner migration from v1.17.0 after it slowed builds.
Changed
- (ci) Switch back to Namespace runners (#819 by @jdx) — Reverts #814, restoring Namespace profiles for CI, bench, docs, COPR/Homebrew, and release-plz jobs, including the native ARM64 Linux PGO+BOLT release job on
namespace-profile-endev-linux-arm64-large. Windows and BATS shards continue to run on GitHub-hosted runners.
No runtime or CLI behavior changed in this release; if you're already on v1.17.0 there's nothing new to pick up.
Full Changelog: https://github.com/endevco/aube/compare/v1.17.0...v1.17.1
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.17.0: Staged publishes, hoisting limits, and tarball integrity
A catch-up release for the tag that introduced staged-publish trust, linker hoisting limits, remote tarball integrity fixes, and OTP support for dist-tag writes. This release is backfilled without binary assets; use v1.17.1 or newer for downloadable artifacts.
Added
- (resolver) Trust staged publishes so packages published through staged registry flows can resolve correctly once promoted (#810 by @jdx).
- (linker) Add hoisting limits to keep dependency placement bounded in large or complex graphs (#809 by @jdx).
Fixed
- (lockfile) Preserve remote tarball integrity metadata when resolving packages from remote tarball specs (#812 by @jdx).
- (dist-tag) Support OTP-protected dist-tag writes (#811 by @jdx).
Changed
- (ci) Switch release, docs, bench, COPR/Homebrew, and most CI jobs to GitHub-hosted runners (#814 by @jdx). This was reverted in
v1.17.1after slower builds. - (release) Use trusted publishing for cargo releases (#816 by @jdx).
- (deps) Bump
tomlfrom 0.8.23 to 1.1.2+spec-1.1.0 (#796 by @dependabot). - (deps) Bump
sha2from 0.10.9 to 0.11.0 (#790 by @dependabot). - Refresh benchmarks for
v1.16.1(#808 by @jdx).
Tests
- Cover alias peer cycles in the resolver (#813 by @jdx).
- Cover remote tarball fallback lookup in lockfile handling (#815 by @jdx).
Full Changelog: https://github.com/endevco/aube/compare/v1.16.1...v1.17.0
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.16.1: Publish polish and linker hardening
A small follow-up to v1.16.0 that unblocks aube publish for mise-style version tags, broadens npm OTP detection, accepts pnpm's linkWorkspacePackages: deep, and adds defense-in-depth against unsafe package aliases in the linker.
Fixed
-
(publish) Normalize semver metadata before publish (#806 by @jdx) —
aube publishnow parsespackage.json#versionthroughnode_semverand strips leading-vand other npm-style noise before computing tarball names,versions.<v>keys, and dist-tags in the PUT body. When normalization changes the on-disk string, publish rebuilds the archive sopackage/package.jsoninside the.tgzmatches the cleaned version. This fixes registry rejections like "New versions must be valid semver" for projects (e.g. mise) that tagv2026.5.16. The same PR also widens the interactive OTP retry to detect npm'sone-time pass/one time passwording (previously onlyone-time passwordtriggered the prompt). -
(add) Accept
linkWorkspacePackages: deep(#799 by @jdx) — pnpm's tri-statelinkWorkspacePackagessetting (true/false/"deep") is now parsed across workspace YAML,settings.toml, and.npmrc.aube addenables workspace-sibling lookup whenever the resolved value isn'tfalse, sodeepprojects getworkspace:^manifest writes instead of registry specifiers. Docs no longer claimdeepis unsupported.
Security
- (linker) Reject unsafe package aliases under
node_modules(#800 by @jdx) — A newvalidate_package_link_nameguard rejects path-like package names and dependency keys (.., extra slashes, absolute paths, Windows drive prefixes, null bytes, anything that isn't a valid npmnode_modulesslot) before they're used to build install paths. The check runs during materialize, isolated top-level and workspace symlinks, and hoisted placement planning —HoistedPlacements::from_graphnow returnsResultso unsafe names fail install/rebuild instead of silently planning bad paths. Failures surface as the newERR_AUBE_UNSAFE_PACKAGE_NAME(exit code 92).
Full Changelog: https://github.com/endevco/aube/compare/v1.16.0...v1.16.1
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.16.0: pnpm 11 parity, trusted publishing, and git tarball integrity
This release brings aube's pnpm lockfile handling up to pnpm 11 parity, pins integrity for hosted git tarballs, and fixes several publish-flow gaps including npm Trusted Publishing and interactive OTP prompts. It also resolves a long-standing install error when a workspace child depends on the workspace root via workspace:*.
Added
-
(pnpm) pnpm 11 lockfile parity (#761 by @jdx) —
aube-lockfilenow reads/writes pnpm'sgitHostedmetadata and preserves non-derivable registry tarball URLs (e.g. GitHub Packages), so round-trips against pnpm 11 lockfiles stay byte-clean. The CLI also picks up several pnpm-shaped behaviors at the same time:aube auditmergesauditConfig.ignoreGhsas/auditConfig.ignoreCveswith--ignore,aube publish --jsonemits a single npm-compatible object for a single-package publish (array only for multi-package), and provenance now acceptsNPM_ID_TOKENin addition to GitHub's default OIDC token. -
(publish)
aube stagecommand (#762 by @jdx) — New visible npm-compat stub. WithoutnpmPathit exits with a clear "not implemented — usenpm stage" message; withnpmPathconfigured it delegates the call (including--registryand trailing args) to the underlying npm binary, matching howwhoamiandset-scriptalready behave. -
(publish) npm Trusted Publishing (OIDC) (#763 by @jdx) —
aube publishnow exchanges a GitHub Actions OIDC token for a short-lived npm bearer token before upload, so tokenless Trusted Publishing workflows work end-to-end. The exchange happens after theprepublishOnlylifecycle and tarball build, so it uses the final packaged name (important if a hook renames the package). If the OIDC fetch fails for any reason (network, non-2xx, malformed JSON) aube debug-logs and falls back to the existing.npmrcauth instead of erroring out. -
(publish) Interactive OTP prompt on 2FA challenge (#767 by @jdx) — When the registry rejects a publish PUT with a 401/403 that looks like an OTP/2FA challenge and
--otpwas not provided, aube now prompts for a code (masked input viademand) and retries the request once. In non-interactive runs it returns a clear--otp <CODE>hint instead of failing with a generic auth error. Plain bad-token failures are still surfaced as auth errors rather than misread as OTP prompts.
Fixed
-
(resolver) Hosted git tarball integrity is pinned and verified (#783 by @jdx) — Hosted git dependencies fetched through the codeload fast path now have a SHA-512 SRI computed on first fetch, persisted on the lockfile entry, and verified before extraction on subsequent installs. Codeload cache keys also mix in the integrity hash so tarballs with different contents can't collide on the same cache directory.
-
(update)
workspace:*against the workspace root resolves (#757 by @fu050409) — When the workspace rootpackage.jsondeclared its ownname/versionand a child package depended on it viaworkspace:*,aube update/aube installfailed withERR_AUBE_NO_MATCHING_VERSIONbecause the root was never added to the workspace version map. The root is now included in bothinstall/workspace.rsandupdate.rs, with a0.0.0fallback when no version is set. -
(lockfile) No more lossy
package-lock.jsonrewrites from override drift (#753 by @jdx, fixes #752) — Drift checks are now format-aware: npm and yarn lockfiles don't round-trip the top-level override snapshot that aube/pnpm/bun use for drift detection, so a non-emptyoverridesblock inpackage.jsonmade every npm install look stale and rewrotepackage-lock.json(potentially reshaping platform-optional package entries and peer metadata). Override-drift comparisons are now skipped for npm and yarn lockfiles, and remain strict foraube-lock.yaml,pnpm-lock.yaml, andbun.lock.
Changed
-
(deps) HTTP/TLS stack refresh (#780 by @jdx) — Workspace
reqwestbumped to 0.13 (with the renamedrustlsfeature) and thehickory-proto/hickory-resolverDNS stack moved to 0.26.1, collapsing duplicate reqwest 0.12/0.13 entries. A newaube_util::http::with_webpki_root_fallbackhelper merges Mozilla's baked-in roots withrustls-platform-verifieron Unix (except Android) and Windows, and registry clients, OSV/supply-chain probes,aube login, and the update notifier all build their HTTP clients through it so TLS trust stays consistent across the upgrade. -
(docs) Clearer
prunevsstore prune(#758 by @jdx) —aube prune --helpnow explicitly describes its lockfile-driven cleanup of the projectnode_modules(including virtual-store entries and.binlinks) and points users ataube store prunefor global store cleanup, which now has its own long help covering store-path scope, cached-index reachability, and hardlink/reflink behavior.
New Contributors
Full Changelog: https://github.com/endevco/aube/compare/v1.15.0...v1.16.0
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.15.0: Yarn Berry portal/exec/patch + deny-build
This release closes three Yarn Berry compatibility gaps (portal:, exec:, and patch: protocols), adds an aube add --deny-build flag for strictDepBuilds=true workflows, and fixes two install-correctness bugs around workspace updates and Bun patched dependencies.
Added
-
(yarn) Berry
portal:andexec:protocols (#729 by @jdx) — Yarn Berry lockfile entries usingportal:andexec:are now parsed instead of skipped, and round-trip cleanly when aube writes the lockfile back (portal:aslinkType: soft,exec:as a generated hard-link package).portal:targets materialize as local packages whose dependencies are followed (matching Yarn's documented difference fromlink:);exec:generator scripts run into a temp build directory and the generated package is imported, with versions and dependencies locked at resolve time.exec:generators require Node.js onPATH, are blocked under--ignore-scripts, and are rejected if the generator path resolves outside the project root. -
(yarn) Berry
patch:protocol (#728 by @jdx) — Berrypatch:resolutions are now parsed into aube's patched-dependency map (builtin patches are skipped), preserved on lockfile write, and threaded through install/link so the referenced Yarn patch files are actually applied during materialization. Previously these entries were silently dropped, so Berry projects relying onpatch:could install with unpatched package contents. -
(add)
aube add --deny-build=<pkg>(#730, closes #726, by @jdx) — Repeatable flag that records a dependency's lifecycle scripts as reviewed-and-denied by writingallowBuilds.<pkg>=falsebefore install. This letsstrictDepBuilds=trueworkflows explicitly skip selected package builds without failing the install, and is forwarded through global installs (aube add -g --deny-build=<pkg>). Specifying the same package in both--allow-buildand--deny-buildis rejected with the newERR_AUBE_CONFLICTING_BUILD_FLAGS.# Mark esbuild's postinstall as reviewed-and-denied, then install aube add --deny-build=esbuild esbuild
Fixed
-
(update) Workspace-member
aube updatewrites to the root lockfile (#732 by @jdx) —aube updaterun inside a workspace member previously started from the nearest project root and producedsub/aube-lock.yaml, disagreeing withaube install(which already targets the workspace root). Plain member updates now merge into the shared workspace-rootaube-lock.yamlvia the same helper used by filtered/recursive updates, carrying per-importerworkspace_extra_fieldsalongside dependency and skipped-optional metadata. -
(bun) Bun top-level
patchedDependenciesare applied at install (#724 by @jdx) — aube preserved Bun'spackage.json#patchedDependenciesinbun.lock, but install-time patch loading only readpnpm.patchedDependencies,aube.patchedDependencies, and workspace YAML entries — so Bun-only projects could install successfully while materializing unpatched package contents. Bun's top-level field is now merged into the patch sources used by install (including for BOM-prefixedpackage.json), and is correctly removed when the map becomes empty.
Full Changelog: https://github.com/endevco/aube/compare/v1.14.1...v1.15.0
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.
v1.14.1: Install module split
A maintenance release with no user-facing behavior changes. The install command's growing commands/install/mod.rs was split into focused submodules to keep the install pipeline easier to navigate. Install behavior, flags, and output are unchanged from v1.14.0.
Changed
- (install) Extracted the fetch/import pipeline (local source import, lockfile fetch wrapper, store-index classification, tarball fetch/import, contextualized-index remapping) into a new
commands/install/fetch.rsmodule (#704 by @jdx). - (install) Split the materializer, native-build critical-path heuristic, and workspace graph/lifecycle/per-project lockfile helpers into dedicated
materialize.rs,critical_path.rs, andworkspace.rsmodules (#702 by @jdx). - (install) Moved post-pipeline helpers —
--lockfile-dirimporter remapping, human install summary output,.aubecache invalidation/orphan cleanup, and skipped-build warning replay — intolockfile_dir.rs,summary.rs,sweep.rs, andunreviewed_builds.rs(#698 by @jdx).
Full Changelog: https://github.com/endevco/aube/compare/v1.14.0...v1.14.1
💚 Sponsor aube
aube is part of en.dev — an independent developer-tooling studio run by @jdx, also behind mise. Work on aube is funded entirely by sponsors.
If aube is saving your team install time or CI minutes, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project fast, free, and independent.