Releases: endevco/aube
v1.9.1: Cold install overhaul, HTTP prefetch, and workspace fixes
A performance- and correctness-focused patch release. Cold installs get a streaming tarball pipeline, Linux gets an O_TMPFILE+linkat CAS fast path, and the resolver's cold path overlaps DNS, TLS, and packument prefetch with the manifest/workspace/lockfile work that used to serialize them. On the fix side, aube run once again finds node-gyp for package scripts, and aube update / aube outdated stop trying to fetch unpublished workspace: deps from the registry.
Added
-
Pre-resolver packument prefetch + shared HTTP utilities (#529 by @imjustprism) — a new
aube-util::httpmodule consolidates client-side primitives (prewarm,priority,race,resolve,ticket_cache) so leaf crates share one warm-pool surface with consistent killswitch semantics. On install entry, aube now readspackage.jsonand fires fire-and-forget packument GETs for every registry-shaped direct dep before workspace yaml load, settings resolve, lockfile parse, and resolver construction — by the time the resolver pops its first task, the packument cache and reqwest pool are warm.RegistryClient::prewarm_connectionnow covers the default registry plus every scoped (@org:registry=...) and per-uri auth registry, with parallel DNS preresolve so DNS RTT hides behind the TLS handshake. Abbreviated packument GETs also sendPriority: u=0(RFC 9218 Critical) so H2 schedulers prioritize resolver-blocking metadata over pending tarball frames. New killswitches:AUBE_DISABLE_DNS_PRERESOLVE,AUBE_DISABLE_REQUEST_RACING,AUBE_DISABLE_PREFETCH,AUBE_DISABLE_TLS_TICKET_CACHE. Prefetch is a no-op when offline or when any lockfile is present. -
Cold install pipeline overhaul (#522 by @imjustprism) — several overlapping wins on the cold-cache path:
- Streaming tarball pipeline (opt-in via
AUBE_TARBALL_STREAM=1, killswitchAUBE_DISABLE_TARBALL_STREAM) — HTTP body chunks pipe through SHA-512 + gz + tar + CAS via an mpsc bridge instead of buffering the whole tarball; non-SHA-512 SRI falls back to buffered. Bounded by the registry'starball_max_bytescap. - Linux
O_TMPFILE+linkatCAS publish withEOPNOTSUPPfallback to the tempfile path,posix_fallocateto avoid ext4 fragmentation, andposix_fadvise(DONTNEED)to free page cache after publish. Killswitch:AUBE_DISABLE_O_TMPFILE. - Materialize-stream into the lockfile fast path — both lockfile and no-lockfile branches now share the GVS prewarm materializer, hiding 30-200ms of GVS reflinks behind the in-flight download tail.
- Resolver tuning — foldhash on
graph_hashhot maps, pre-sized resolver caches, thread-localnode_semver::Versionparse cache,PARALLEL_IMPORT_THRESHOLDlowered from 256 to 16 (median npm tarball is 7 files), and pinned tokioworker_threads(cpu.min(8)) /max_blocking_threads(64)(tunable viaAUBE_TOKIO_WORKERS/AUBE_TOKIO_BLOCKING). - Windows gets
FILE_ATTRIBUTE_NOT_CONTENT_INDEXEDon the store root; cross-volume detection (drive letters on Windows,devid on Unix) is gated per-platform.
Reported same-volume Windows cold-install ratios: 1.80x-8.75x faster than Bun across svelte/vite/next/babylon.
- Streaming tarball pipeline (opt-in via
-
Per-project materialize pipelined into fetch (#527 by @imjustprism) — when GVS is off, each fetched
(canonical_key, PackageIndex)triggersmaterialize_intoagainst.aube/<dep_path>/immediately, so by the time fetch finishes the dedicated link phase only has to create top-levelnode_modules/<name>symlinks. The driver now usesJoinSetinstead ofVec<JoinHandle>, so on early-return all in-flight tasks abort instead of detaching and racing install cleanup. ~10% improvement on warm fresh installs in the local benchmark matrix.
Fixed
-
aube run/aube testfindnode-gyp(#518 by @jdx) — package scripts only hadnode_modules/.binprepended toPATH, soaube testwould fail withnode-gyp: not foundon hosts that didn't already ship it. Script execution now reuses aube's existing node-gyp bootstrap (via a lazy shim bin dir +AUBE_NODE_GYP_EXE/AUBE_NODE_GYP_PROJECT_DIR), matching pnpm/npm behavior. Ports pnpm'slifecycleScripts.ts:128coverage into the offline node-gyp bootstrap bats suite. -
workspace:deps inaube update/aube outdated(#523 by @jdx, fixes #520) —aube updatenow discovers workspace packagename/versionpairs and passes them into resolver workspace resolution soworkspace:deps frompackage.json#workspacesresolve locally instead of triggering registry packument fetches.aube outdatedfilters out direct deps withworkspace:specifiers and reports "no matching dependencies" rather than attempting a packument fetch. Adds a newWARN_AUBE_WORKSPACE_PACKAGE_MISSING_NAMEwarning code for workspace packages without anamefield. -
Resolver peer-context divergence is fatal (#522 by @imjustprism) —
apply_peer_contextshittingMAX_ITERATIONSused to log a warning and ship a broken graph; it now returns a fatalError::PeerContextDivergence(usize).state::remove_stateerrors at--forceand GVS-transition sites also propagate instead of being silently swallowed, so permission-denied or Windows-locked sidecars no longer defeat the freshness check. -
Tarball hardening (#522 by @imjustprism) — entries declared as 0 bytes with non-zero stream payload are now rejected (synthetic-entry injection guard), and GNU
LongName/LongLinkmetadata records are correctly accepted. -
Patches loaded once per cwd (#529 by @imjustprism) —
load_patches_for_linkerwalkedpatches/from disk 2-3 times per install (lockfile-prewarm, no-lockfile-prewarm, and link-phase sites). Now cached per cwd viaOnceLock<Mutex<HashMap<PathBuf, ...>>>.
Full Changelog: v1.9.0...v1.9.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.9.0: Comment-preserving workspace edits, deploy bundling, and node --inspect
A focused release: aube deploy learns to bundle workspace siblings and local-path deps into the deploy artifact, workspace-yaml writers stop eating user comments, aube-owned settings move out of .npmrc, and aube run forwards Node debugger flags.
Added
-
Aube settings move out of
.npmrc(#517 by @jdx) — known aube-owned settings now live in~/.config/aube/config.toml(XDG-aware), while registry, auth, and unknown keys keep using.npmrc.aube config get/set/list/deletereads and writes the right file automatically, and migrating a known setting cleans up the stale.npmrcentry..npmrcwrites are also atomic against the symlink target now, so dotfile setups that symlink~/.npmrcinto a managed config repo stop having the symlink replaced by a regular file. -
aube run --inspect/--inspect-brk(#515 by @jdx) — both flags accept an optional[host:]port(e.g.--inspect=9229,--inspect-brk=0.0.0.0:9230) and are forwarded as explicit Node argv when aube can identify a Node-backed target — directnode ...scripts inpackage.jsonand localnode_modules/.binfallbacks resolved through shims/symlinks. The flags are passed as argv rather than viaNODE_OPTIONS, so the debugger doesn't attach to nested Node processes spawned by the script. -
aube deploy --no-prod(#507 by @jdx) — opt out of the default--prodfilter for deploys that need devDependencies at runtime (test-harness staging, build-step artifacts). Mutually exclusive with--prod/--dev; combine with--no-optionalto keep prod + dev but drop optionals. -
Comment-preserving workspace yaml writes (#511 by @jdx) — every workspace-yaml writer (
approve-builds,patch-commit,patch-remove, the dailycleanupUnusedCatalogsinstall pass, andaube config set --location workspace) now routes throughyamlpatchinstead of round-tripping the file through a serializer. Keys, comments, and whitespace the edit didn't touch land back on disk byte-identical, so user annotations on adjacent entries survive. Empty/missing files still go through the regular serializer since there are no comments to preserve.
Fixed
-
aube deploybundles local dependencies (#507 by @jdx) — fixes two real bugs reported in #345:workspace:*siblings tried to fetch from the registry. Deploy used to rewriteworkspace:*to a concrete version and ask install to resolve it — fine for published siblings, broken for the (very common) unpublished case. Reachable workspace siblings are now copied into<target>/.aube-deploy-injected/<id>/and the manifest spec becomes a relativefile:pointer. Recursion handles sibling chains where a sibling's own deps are workspace siblings.file:deps resolved relative to the deploy output dir. Afile:../local-vendorspec used to ride along unchanged in the deployed manifest, pointing at<target>/../local-vendorinstead of the source workspace'slocal-vendor. Local-path deps now go through the same staging pipeline.
When bundling occurs the lockfile-subset path is skipped, since the rewritten
file:pointers don't appear in the source lockfile and would otherwise trip a frozen install. -
aube removepreserves dependency order (#511 by @jdx) — dropping one dep used to alphabetize the remaining entries in the affectedpackage.jsonsection as a side effect. Surviving entries now stay in their original on-disk order, matching pnpm/npm. (aube addis unaffected — sorted inserts there are intentional.)
Full Changelog: v1.8.0...v1.9.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.8.0: Stable error codes, smarter run/dlx, and a new install progress UI
A polish-and-plumbing release: install progress gets a from-scratch redesign, errors and warnings now carry stable identifiers (with bespoke exit codes and dep-chain context), aube run / aube dlx prefer locally-installed binaries, and a handful of workspace-from-subpackage and aube add ergonomics get fixed.
Added
-
Redesigned install progress UI (#501 by @jdx) — fixed 15-char bar on the left, stats on the right, phase-aware label (
resolving/fetching/linking), ETA, transfer rate, and an estimated install size derived from the resolve stream:aube 1.8.0 by en.dev █████░░░░░░░░░░ 23/142 pkgs · 4.2 MB / ~13.8 MB · 1.4 MB/s · ETA 5s ███████████████ 1230/1230 pkgs · linking ✓ resolved 1230 · reused 98 · downloaded 1132 (54.6 MB) in 6.8sInstalls that finish before the first 2s heartbeat now print a single self-identifying summary line (
✓ installed 5 packages in 423ms) instead of a partial bar. Also fixes two real bookkeeping bugs (a2/1 packagesoverflow on platform-mismatched non-optional deps, and the "stuck at 90%" undercount caused byfilter_graphdropping packages after the denominator was inflated). -
Local bins for
aube runandaube dlx(#502 by @jdx) —aube run <name>falls back tonode_modules/.bin/<name>when nopackage.jsonscript matches, andaube dlx/aubxwill execute an already-installed local binary instead of doing a throwaway install. Pass-p/--package(or a versioned spec) to force the install path. -
Stable error and warning codes (#492 by @jdx) — every error and warning aube emits now carries an
ERR_AUBE_*orWARN_AUBE_*identifier in a structured field, so CI scripts and ndjson consumers can branch on the code instead of substring-matching English messages. A curated subset maps to bespoke Unix exit codes (10–99 in 10-wide ranges by category) so shells can react to specific failures without parsing stderr — e.g.aube install --frozen-lockfilein an empty dir exits with10(ERR_AUBE_NO_LOCKFILE). Post-resolver errors that mention a specific package now also include the dependency chain back to the importer (chain: a@1 > b@2 > leaf@3) so a tarball-integrity or fetch failure tells you why your install pulled that transitive dep. The full code list lives atdocs/error-codes.md.
Fixed
-
aube why/list/queryfrom a workspace subpackage (#504 by @jdx) — these commands resolved cwd via the nearestpackage.json, so running them insidepackages/foo/errored withNo lockfile found. Run aube install first.even though the workspace lockfile sat one level up. They now walk up to the workspace root when one is present. -
Workspace lifecycle scripts and pnpm-lock npm aliases (#500 by @jdx) — recursive workspace installs now run
preinstall/install/postinstall/preparefor each linked workspace importer in dependency order (not just the root), and the build-script policy mergespnpm.allowBuilds/onlyBuiltDependencies/neverBuiltDependenciesacross all participating manifests so a member can approve its own dep's builds.pnpm-lock.yamlnow writes npm aliases in pnpm's native<real>@<version>encoding instead of leaking aube's internalaliasOffield. -
aube addauto-detects local paths (#499 by @jdx) —aube add /path/to/lib,./lib,~/lib,file:./lib, andlink:./libno longer fall through to the registry path with a confusingHTTP 405 Method Not Allowed. Bare paths default tolink:for directories andfile:for tarballs (pnpm parity); explicit prefixes are preserved. Tarball-suffix paths emit a clear "not yet supported inaube add" hint instead of a 405.
Changed
-
Per-command
--helpis bucketed (#505 by @jdx) —--frozen-lockfile/--prefer-frozen-lockfile,--registry+--fetch-*, and--disable/--enable-global-virtual-storemoved off the global flag set into per-command groups underLockfile/Network/Virtual storeheadings, and now appear only on commands that consume them. Seven pnpm-compat no-op flags (--workspace-packages,--ignore-workspace,--include-workspace-root,--aggregate-output,--stream,--use-stderr,--yes) are still parsed but hidden from--help. Pre-subcommand placement still works (aube --frozen-lockfile install,aube --registry=URL install) via an argv pre-pass.One caveat: implicit-script invocations like
aube --frozen-lockfile dev(wheredevis apackage.jsonscript) no longer apply the flag — writeaube run --frozen-lockfile devinstead.
Full Changelog: v1.7.0...v1.8.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.7.0: Local & git specs in aube add, faster cold installs
A feature-heavy release: aube add learns git and local-path specs, workspace commands gain support for yaml-only "coordinator" monorepos, aube update and aube rebuild get pnpm-parity polish, and a deep performance pass speeds up cold installs by up to ~1.9×.
Highlights
aube addis now a one-stop shop for git, GitHub-shorthand, andlink:/file:local-path dependencies — not just registry packages.- Performance pass on the install hot path (#469) lands streaming SHA-512, parallel CAS imports, TLS prewarm, fetch reordering, and a long tail of cold-path cleanups, with measured cold-install speedups up to ~1.9× vs v1.6.2.
- Workspace and pnpm parity polish across
update,rebuild, yaml-only roots, unversioned members, and nestedlink:/file:resolution.
Added
-
aube add file:./pkg/link:../sibling(#487 by @jdx) — local-path specs are routed through a non-registry branch, with the manifest key derived from the path basename (with.tgz/.tar.gzstripped) or from an explicit alias.aube add my-bundle@file:./bundle.tgzworks too. -
aube addsupports git specs (#483 by @jdx) — bare GitHub shorthand,github:/gitlab:/bitbucket:prefixes, fullgit+ssh/git+httpsURLs, and aliases. The verbatim spec is written topackage.jsonand the resolver handles the rest:aube add kevva/is-negative aube add github:kevva/is-positive aube add my-alias@git+https://github.com/kevva/is-negative.git
-
Yaml-only workspace roots (#486 by @jdx) —
install,list,run -r,query, andwhynow work in pure-coordinator monorepos that havepnpm-workspace.yaml/aube-workspace.yamlat the root but no rootpackage.json(Turborepo-style layouts). Single-project commands likeadd/removestill hard-error without a manifest. -
aube update <pkg>rewrites manifest ranges by default (#479 by @jdx) — caret/tilde ranges (^1.2.0,~1.2.0) are rewritten to track the resolved in-range max, matching pnpm. Other shapes (>=, exact pins, dist-tags, git,workspace:) stay frozen. Setupdate-rewrites-specifier=falseto keep the previous behavior. -
aube rebuild <pkg>...(#477 by @jdx) — runs lifecycle scripts only for the named deps, bypasses theallowBuilds/onlyBuiltDependenciespolicy, and skips root hooks. Composes with--filter. Bareaube rebuildcontinues to do a full policy-respecting rebuild. -
Persistent unreviewed-builds warning (#476 by @jdx) — repeat warm-path installs no longer swallow the "ignored build scripts for N package(s)" nudge; the spec keys are persisted in
.aube-stateand re-emitted on every install. -
aube update --depthno longer silently ignored (#473 by @jdx) — emits a one-line warning pointing atrm aube-lock.yaml && aube installfor the only useful semantic case.
Fixed
-
Faster cold installs (#469 by @imjustprism) — a wide hot-path pass with measurable wins on real registries:
Project v1.6.2 v1.7.0 Speedup svelte (56 pkg) 1393 ms 1386 ms 1.01× vue (117 pkg) 1590 ms 1360 ms 1.17× next.js (336 pkg) 14071 ms 9160 ms 1.54× babylon (21 pkg) ~6000 ms 3186 ms ~1.9× Highlights: streaming SHA-512 over the wire (no second buffered hash pass), two-phase parallel CAS tar import, speculative TLS/HTTP/2 prewarm behind manifest parse, native-build packages floated to the front of the fetch queue,
Accept-Encoding: gzip, br, zstdon packuments, in-process DNS cache viahickory-dns, mmap+rayon BLAKE3 over 4 MiB, network concurrency default raised 64 → 128, and zero-copy packument parsing. Every change ships with anAUBE_DISABLE_*killswitch (AUBE_DISABLE_STREAMING_SHA512,AUBE_DISABLE_SPECULATIVE_TLS,AUBE_DISABLE_CRITICAL_PATH,AUBE_DISABLE_PARALLEL_IMPORT,AUBE_DISABLE_MMAP_BLAKE3,AUBE_DISABLE_SNAPSHOTS) plus anAUBE_CONCURRENCY=Nclamp. -
Nested
link:/file:resolution (#470 by @jdx) — fixes thetransitive local specifier link:./libs/foo cannot be resolved without the parent package source rootinstall error in two cases: afile:/link:parent declaring a transitivelink:, and a rootpnpm.overridesrewriting a registry dep to a local path. Override paths now anchor at the project root like pnpm does. -
Workspace members without
version(#480 by @jdx) — fall back to0.0.0instead of hard-erroring.workspace:*/^/~siblings still link locally; specific ranges likeworkspace:^2.0.0still correctly fail to satisfy. Unblocks repos like tuist/tuist#10584. -
Bare
user/repoparsed as GitHub shorthand (#472 by @jdx) in lockfile/spec parsing, withupdate --latestnow skipping git-spec deps so they can't be silently rewritten into registry pins. -
CLI short help wraps cleanly (#478 by @jdx) — many flags across
add,install,publish,update,view, etc. had multi-line doc comments that clap merged into 120+ char paragraphs for-h. Now each flag has a one-line summary followed by the longer prose, restoring readable short help on standard terminals.
Full Changelog: v1.6.2...v1.7.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.
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.6.2: Engines coverage catches up to pnpm
A small patch release that closes engine-validation gaps with pnpm.
Fixed
- Broader engines coverage (#458 by @jdx) — aube now honors engine constraints it previously skipped:
engines.aubeandengines.pnpmon root and workspace project manifests are checked against the running aube version (aube positions itself as a pnpm-compatible drop-in, soengines.pnpmis honored as if aube were that pnpm).engines.nodeis now enforced on workspace project manifests, not just the root.- Warning output labels which engine triggered the mismatch (e.g.
wanted node >=20,wanted aube >=99999,wanted pnpm >=8), and theengine-stricterror message stays compatible with existing assertions. engines.{aube,pnpm}on transitive deps remain skipped on purpose, since wild packages routinely pin author toolchains.
Full Changelog: v1.6.1...v1.6.2
💚 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.6.1
Fixed
- Unblocked the
v1.6.0publishing path so missing Linux release assets and downstream package publishes could be backfilled (#460). - Made the resolver build script tolerate environments where the primer generator exists but
nodeis not installed, falling back to an empty primer with a Cargo warning instead of panicking (#460). - Moved npm publishing and PPA upload jobs back to GitHub-hosted runners where npm provenance and Launchpad FTP uploads work correctly (#460).
Other
- Refreshed benchmarks for the 1.5.2 baseline (#459).
v1.6.0
Highlights
- Added broader pnpm compatibility for
aube add,aube update, pnpmfile hooks, catalog saves, workspace protocol parsing, and lockfile directory configuration. - Added generic
--config.<key>=<value>overrides plus fetch timeout, retry, backoff,--pnpmfile, and--global-pnpmfileflags. - Improved install, resolver, registry, linker, manifest, settings, and state hot paths with shared caches, cheaper hashes, fewer repeated filesystem probes, and compressed packument fetches.
- Expanded pnpm parity coverage across update, hooks, allow-build review, monorepo filter, prefer-offline, and misc install behavior.
Added
aube updatenow parses<pkg>@<spec>arguments and can update indirect dependencies (#446).aube addcan bootstrap a missingpackage.json, matching pnpm behavior covered by newly ported misc tests (#417).--config.<key>=<value>flags provide generic CLI config overrides (#447).--lockfile-dir/lockfileDirsupport allows commands to target a foreign lockfile directory when valid (#431).- Fetch controls were added for timeout, retry count, and retry backoff behavior (#436).
--pnpmfileand--global-pnpmfileflags were added, with pnpmfile hooks wired into update andpreResolutionsupport (#439, #423).- pnpmfile
ctx.logrecords now emit aspnpm:hookNDJSON on stdout (#440). --save-catalog,workspace:*parsing, andsharedWorkspaceLockfile=falsesupport landed together (#418).- Empty
--allow-buildvalues now use pnpm's verbatim error wording (#444).
Fixed
AUBE_VIRTUAL_STORE_DIRis honored from the environment, with additional pnpm misc parity coverage (#456).aube update --latestpreserves prerelease pins that are already higher than the latest stable version (#445)..is rejected as a foreign--lockfile-dirimporter and the related docs were corrected (#442).- npm
package-lock.jsonworkspace importers are preserved when parsing and writing lockfiles (#443). - Lifecycle script behavior closed three pnpm parity gaps (#421).
- The resolver now ships an empty bundled metadata primer when the generator script cannot run, instead of failing the build (#425).
Performance
- Cached hot-path work across install, resolver, registry, linker, manifest parsing, settings lookup, and install state freshness checks (#453).
- Deduplicated and cached repeated install/resolver work, including graph hashing, patch fingerprints, lockfile parsing, env capture, script policy lookup, workspace-root scans, and registry auth token matching (#449).
- Refreshed benchmark results for the 1.5.2 baseline (#448, #452).
Testing and Parity
v1.5.1: POSIX colon tarball filenames
A small patch release fixing tarball installs that contain : in entry filenames on POSIX platforms (e.g. redos-detector@6.1.4's dist/__mocks__/package-json:version.d.ts).
Fixed
- POSIX colon tarball filenames — the store tarball validator and the linker's
validate_index_keypreviously rejected:on every platform to defend against Windows drive-prefix and NTFS alternate-data-stream ambiguity. That guard was too broad for POSIX, where colon is a valid filename character, and caused installs of packages likeredos-detector@6.1.4to fail. Both guards are now platform-gated::is still rejected on Windows, but accepted on Linux and macOS. (#386 by @jdx)
Full Changelog: v1.5.0...v1.5.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.5.0: Dependency graph queries and patch/lockfile fixes
This release adds aube query for selector-based dependency graph inspection, fixes patch application against CRLF tarball files, repairs npm-aliased catalog dependencies in pnpm-generated lockfiles, and unifies how aube decides where to write workspace settings.
Added
aube query— a vlt-inspired dependency-graph query command. Supply a selector expression (attribute predicates plus pseudo-selectors like:scripts,:bin,:peer,:type(...),:license(...)), optionally scope with workspace--filter/--prod/--devroots, and emit human-readable,--parseable, or--jsonoutput. Reads only the local lockfile. (#380 by @jdx)
Fixed
-
Patches against CRLF text files — tarballs published from Windows editors (e.g.
gifuct-js@2.1.2/index.d.ts) ship CRLF, but git/pnpm-style patches always emit LF, and diffy refused to match LF hunks against CRLF context. aube now normalizes the original to LF before applying and restores CRLF on write — matching pnpm's approach — with a\r\r\ncollapse so a literal\rbyte mid-line doesn't gain a second carriage return. (#384 by @jdx) -
aube patch-commitdestination — previously wrote unconditionally topnpm.patchedDependenciesinpackage.jsoneven on projects already using the pnpm v10+ workspace-yaml home. A single rule now applies to every command that mutates a setting which can live in either the workspace yaml orpackage.json#{pnpm,aube}.<key>:- If a workspace yaml exists on disk → write there.
- Otherwise, if
package.json#pnpmis already declared → writepnpm.<key>(preserve the user's namespace). - Otherwise → write
aube.<key>.
aube patch-removenow strips entries from every place they could live and reports the files actually rewritten. The same rule coversaube approve-buildsand install-time auto-deny seeding. (#384 by @jdx) -
npm-aliased catalog deps from pnpm lockfiles —
aube install --frozen-lockfilepreviously accepted a pnpm lockfile withbeamcoder: npm:beamcoder-prebuild@…declared viapnpm-workspace.yaml#catalogand silently produced an emptynode_modules, because the importer's specifier was'catalog:'and alias detection only fired onspecifier.starts_with("npm:"). Aliases are now detected purely from the canonical<real>@<resolved>version:shape, with a peer-suffix strip soversion: 18.2.0(react@18.2.0)isn't misclassified. (#384 by @jdx) -
Bounded resolver stream — the resolved-package stream is now a bounded Tokio channel sized from the same network concurrency used by fetch workers, with awaited sends so resolver/fetch overlap applies backpressure instead of accumulating an unbounded queue. (#377 by @jdx)
Changed
aube-workspace.yamlis the default-write filename — when neitheraube-workspace.yamlnorpnpm-workspace.yamlexists,aube approve-builds(and the install-time auto-seed of unreviewed build scripts) now createsaube-workspace.yamlso it pairs withaube-lock.yamlinstead of leaving mixed vendor namespaces side by side. Existingpnpm-workspace.yamlfiles keep being mutated in place. (#382 by @jdx)- Comment-preserving workspace-yaml writes — yaml writes now skip the rewrite when the closure produces no structural change, so user comments survive every no-op update to
allowBuilds,patchedDependencies, and catalog cleanup. (#384 by @jdx) - Install phase timing sink — set
AUBE_BENCH_PHASES_FILEto append per-phase install timings (resolve/fetch/link/scripts/state/sweep) as JSONL, optionally tagged withAUBE_BENCH_SCENARIO. The benchmark harness samples aube install-shaped scenarios andbenchmarks/generate-phase-results.mjsturns the JSONL into a Markdown table plus a structured JSON artifact. (#381 by @jdx)
Full Changelog: v1.4.0...v1.5.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.4.0: Linux build jails, pnpm 11 audit/allowBuilds parity, and a security roundup
This release brings aube closer to pnpm 11 parity — audit --fix=update, the allowBuilds review map, and ESM pnpmfiles all land — extends jailed dependency builds to Linux with native Landlock + seccomp enforcement, and ships a roundup of critical/high security and correctness fixes.
Highlights
- pnpm 11 parity across audit fixing, build-script approval, and pnpmfile loading.
- Jailed builds on Linux, with kernel-enforced filesystem and network isolation that fails closed.
- Security & correctness roundup tightening the seccomp/Landlock policy, workspace pattern containment, resolver convergence hashing, patch atomicity, and install-state hashing.
Added
aube audit --fix=update— fix advisories by updating through the lockfile instead of writing overrides, matching pnpm 11.--fixis now an optional method form: bare--fixdefaults tooverride, and--fix=override/--fix=updateare both accepted.aube audit -idefaults to override fix mode to match pnpm's interactive flow. The resolver also learned advisory-range avoidance, so update mode steers sibling reuse, lockfile reuse, and version picking away from vulnerable versions when a safe alternative exists. (#363 by @jdx)- pnpm 11
allowBuildsreview map — build-script approvals now persist asallowBuilds: { pkg: true | false }inpnpm-workspace.yaml.aube installauto-seeds unreviewed dependency builds asfalse, andaube approve-buildsflips selected entries totrue. LegacyonlyBuiltDependencies/neverBuiltDependenciesremain read-compatible. (#364 by @jdx) - ESM pnpmfiles —
.pnpmfile.mjsis now preferred over.pnpmfile.cjsduring default discovery and loaded via dynamicimport(), while CommonJS pnpmfiles continue to load viarequire(). BothafterAllResolvedandreadPackagehooks are supported on.mjs. (#362 by @jdx) - Jailed builds on Linux —
--jail-builds/jailBuilds/AUBE_JAIL_BUILDSnow enforce isolation natively on Linux using Landlock for filesystem writes and a seccomp filter for network sockets. The jail is set up in the child process viapre_execso the parentaubestays unrestricted, and scripts fail closed if the kernel can't fully enforce the policy.TMPDIR/TMP/TEMPare redirected into the per-package temporary jail home, andnetwork: trueremains the per-package escape hatch. (#350 by @jdx)
Fixed
- npm install reliably exposes commands — the published npm package now keeps stable extensionless
bin/aube,bin/aubr,bin/aubxentries. On Unix the native binaries are still copied/hardlinked directly to those paths; on Windows, sibling.exefiles are written and the extensionless paths become tiny shebang shims pointing at them, giving npm's generated.cmdshims a stable target. The native CLI also normalizes npm's interpreter-shim argv shape so multicall dispatch keeps working. (#369 by @jdx) - Critical/high audit roundup (#361 by @imjustprism):
- Scripts: seccomp denylist now covers AF_NETLINK, AF_PACKET, AF_VSOCK, AF_XDP, AF_ALG, AF_BLUETOOTH, AF_RDS, AF_CAN, AF_TIPC, AF_IB, and AF_NFC in addition to AF_INET/AF_INET6 (AF_UNIX stays allowed for node-gyp IPC).
/tmpwas dropped from the Landlock allow-list to prevent symlink races and tmp-file reads on shared CI hosts. - Workspace:
pnpm-workspace.yamlpatterns that escape the project root (e.g.- "../sibling") are now rejected via a canonicalized containment check, instead of leaking foreign directories into the workspace package list. - Resolver: the peer-context convergence hash now walks
(key, [(dep_name, dep_tail), ...])for every package, so peer rewrites that change a dep tail without adding a new key can no longer ship stale linker targets. - CLI:
aube patch-commitis now atomic — the.patchfile is written viaatomic_write, prior bytes are snapshotted, and a manifest write failure rolls the patch back instead of leaving an orphan invisible toload_patches. - Install: the install state digest now hashes user-level
~/.npmrcin addition to the project.npmrc, so a token swap orregistry=change in the home file invalidates the "Already up to date" fast path.
- Scripts: seccomp denylist now covers AF_NETLINK, AF_PACKET, AF_VSOCK, AF_XDP, AF_ALG, AF_BLUETOOTH, AF_RDS, AF_CAN, AF_TIPC, AF_IB, and AF_NFC in addition to AF_INET/AF_INET6 (AF_UNIX stays allowed for node-gyp IPC).
- Resolver excludes provenance churn packages by default — built-in
trustPolicyExcludeentries cover npm packages with known provenance metadata churn that previously broke benchmark fixture resolution; user-supplied entries are merged on top. (#360 by @jdx) - Workspace bins linked into dependents — when workspace package A declares
binand B depends on A viaworkspace:*, A's bins are now symlinked intoB/node_modules/.bin/so B's npm scripts can call them. Previously the linker readpackage.jsonfrom a non-existent.aube/<dep_path>/...location and silently produced no shim. A newlink_bins_for_workspace_dephelper reads from the workspace package's own directory (cached across importers). (#353 by @jdx) - README on the published
aubecrate —[workspace.package]now setsreadme = "README.md"and the binary crate inherits it, so crates.io renders the project README starting with this release. (#349 by @jdx)
Changed
- Install docs sharpened — the installation page and README now warn that the npm package depends on its
preinstalllifecycle script (so--ignore-scriptsor PowerShell blockingnpm.ps1can leave commands unwired), use--ignore-scripts=falsein examples, and recommend mise as the primary install path with a tip onmise settings add idiomatic_version_file_enable_tools nodefor.nvmrc/.node-versionsupport. (#368 by @jdx)
New Contributors
- @imjustprism made their first contribution in #361
Full Changelog: v1.3.0...v1.4.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.
💚 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.