aklinker1/bunv
Corepack for Bun. PoC for implementing a version manager inside bun itself.
curl -sL https://raw.githubusercontent.com/aklinker1/bunv/main/install.sh | sh
Zero config wrapper around Bun that automatically downloads, manages, and executes the version of bun required by each of your projects.
Basically corepack for Bun! But written in Zig for basically zero overhead.
bun and bunxbunvpackage.json's packageManager field (just like Corepack).bun-version.tool-versionsGoal of bunv is to provide a PoC for what version management might look like built into Bun. At the time of writing, that's basically done.
Use the third-party tap:
brew install simnalamburt/x/bunv
bun and/or remove ~/.bun/bin from your pathcurl -sL https://raw.githubusercontent.com/aklinker1/bunv/main/install.sh | sh
~/.bunv/bin to your PATHwhich bun outputs ~/.bunv/bin/bunbun or remove ~/.bun/bin from your pathbun, bunx, bunv)zig build -Doptimize=ReleaseFast --prefix ~/.bunv
~/.bunv/bin to your path:export PATH="$HOME/.bunv/bin:$PATH"
which bun outputs ~/.bunv/bin/bunTo use bun or bunx, just use it like normal:
$ bun i
$ bunx oxlint@latest
If you haven't installed the version of Bun required by your project, you'll be prompted to install it when running any bun or bunx commands.
$ bun run main.ts
Bun v1.3.0 is not installed. Do you want to install it? [y/N] y
Installing...
✓ Done! Bun v1.3.0 is installed
Bunv also ships its own executable: bunv. Right now, it has 2 commands:
$ bunv
Installed versions:
v1.1.26
│ Directory: ~/.bunv/versions/1.1.26
│ Bin Dir: ~/.bunv/versions/1.1.26/bin
└─ Bin: ~/.bunv/versions/1.1.26/bin/bun
v1.3.0
│ Directory: ~/.bunv/versions/1.3.0
│ Bin Dir: ~/.bunv/versions/1.3.0/bin
└─ Bin: ~/.bunv/versions/1.3.0/bin/bun
...
bunv rm 1.1.26
# or just delete the directory
rm -rf ~/.bunv/versions/1.1.26
If you're not in a project, Bunv will use the newest version installed locally or if there are none, it will download and install the latest release.
With bunv, bun upgrade doesn't do anything.
Instead, update the version of bun in your package.json, .bun-version, or .tool-versions file and it will be installed the next time you run a bun command.
// package.json
{
...
- "packageManager": "[email protected]",
+ "packageManager": "[email protected]",
...
}
The oven-sh/setup-bun action already supports all the version files Bunv supports - that means you don't have to install Bunv in CI - just use it locally.
# .github/workflows/validate
on:
pull_request:
jobs:
validate:
runs_on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: "package.json" # or ".tool-versions" or ".bun-version"
# ...
If you're using Bun, you probably love the CLI's incredible speed - so do I. That's why the only benchmark I focused on is how much overhead it takes for Bunv to lookup and execute the correct version of Bun.
So this benchmark measures the time it takes for bun --version to run.
$ hyperfine -N --warmup 10 --runs 1000 '~/.bunv/versions/1.1.26/bin/bun --version' '~/.bunv/bin/bun --version'
Benchmark 1: ~/.bunv/versions/1.1.26/bin/bun --version
Time (mean ± σ): 1.5 ms ± 0.1 ms [User: 1.0 ms, System: 0.4 ms]
Range (min … max): 1.3 ms … 2.3 ms 1000 runs
Benchmark 2: ~/.bunv/bin/bun --version
Time (mean ± σ): 2.0 ms ± 0.1 ms [User: 1.0 ms, System: 0.9 ms]
Range (min … max): 1.7 ms … 2.3 ms 1000 runs
Summary
~/.bunv/versions/1.1.26/bin/bun --version ran
1.37 ± 0.12 times faster than ~/.bunv/bin/bun --version
1.5ms without bunv vs 2.0ms with it. While it's technically 1.37x slower, it's only 0.5ms of overhead - unnoticeable to a human.
NOTE
hyperfinestruggles to accurately benchmark commands that exit in less than 5ms... If anyone knows a better way to benchmark this, please open a PR!
To print debug logs, set the DEBUG environment variable to bunv:
$ bun --version
1.3.0
$ DEBUG=bunv bun --version
Executable: utils.Cmd.bun
Home Dir: ~
Config Dir: ~/.bunv
Checking dir: ~/path/to/project
Found v1.2.11 in ~/path/to/project/package.json
Original args: { bun, --version }
Modified args: { ~/.bunv/versions/1.2.11/bin/bun, --version }
---
1.3.0
# Build all executables (bun, bunx, bunv) to ./zig-out/bin
$ zig build
# Build and run an executable
$ zig build bun
$ zig build bunx
$ zig build bunv
# Pass args to the executable
$ zig build
$ ./zig-out/bin/bun --version
$ ./zig-out/bin/bunx --version
$ ./zig-out/bin/bunv --version
# Build and install production executables to ~/.bunv/bin
$ zig build --release=fast --prefix ~/.bunv
To create a release, run the "Release" action.
This project uses conventional commits, so the release workflow will bump the version and create the GitHub release automatically.