Bunv makes Bun versioning effortless.
It automatically downloads, manages, and runs the exact Bun version each project needs, so your tooling is always correct, reproducible, and fast with near‑zero overhead (see Benchmark).
curl -sL https://raw.githubusercontent.com/Aternus/bunv/main/install.sh | sh
export PATH="$HOME/.bunv/bin:$PATH"
which bunbun --version
bun i
bunx oxlint@latest- Automatic version selection for
bunandbunx - Manage installed versions with
bunv - Read the Bun version from
package.json'spackageManagerfield,.bun-version, or.tool-versions
Bunv checks for a Bun version in this order:
package.json(packageManager: "bun@x.y.z").bun-version.tool-versions- Latest locally installed version
- Latest remote release (downloaded on first use)
Use the third-party tap:
brew install simnalamburt/x/bunv- Uninstall
bunand remove~/.bun/binfrom your path - Run installer:
curl -sL https://raw.githubusercontent.com/Aternus/bunv/main/install.sh | sh - Add
~/.bunv/binto yourPATHexport PATH="$HOME/.bunv/bin:$PATH"
- Ensure
which bunoutputs~/.bunv/bin/bun
- Uninstall
bunand remove~/.bun/binfrom your path - Install Zig (>= 0.15.2)
- Build the executables (
bun,bunx,bunv)zig build -Doptimize=ReleaseFast --prefix ~/.bunv - Add
~/.bunv/binto your path:export PATH="$HOME/.bunv/bin:$PATH"
- Ensure
which bunoutputs~/.bunv/bin/bun
To use bun or bunx, just use it like normal:
$ bun i
$ bunx oxlint@latestIf 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.6 is not installed. Do you want to install it? [y/N] y
Installing...
✓ Done! Bun v1.3.6 is installedBunv also ships its own executable: bunv. Currently, it has 4 commands:
- List installed versions:
$ bunv Installed versions: v1.1.26 │ Directory: ~/.bunv/versions/1.1.26 │ Global: ~/.bunv/versions/1.1.26/install/global └─ Bin: ~/.bunv/versions/1.1.26/bin/bun v1.3.6 │ Directory: ~/.bunv/versions/1.3.6 │ Global: ~/.bunv/versions/1.3.6/install/global └─ Bin: ~/.bunv/versions/1.3.6/bin/bun ... - Remove an installed version:
bunv rm 1.1.26
- Remove Bun installations found on this machine:
bunv prune # or skip confirmation bunv prune --yes - Show help:
bunv help
If you're not in a project, Bunv will use the newest version installed locally, or if there is none, it will download and install the latest release.
Global installs are versioned. When you run bun -g, bunv sets Bun's global install directories to live under the
selected version (e.g. ~/.bunv/versions/<version>/install/global). This keeps global packages isolated per Bun
version.
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": "bun@1.3.5",
+ "packageManager": "bun@1.3.6",
...
}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 look up 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 --version1.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
hyperfine struggles 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.6
$ DEBUG=bunv bun --version
Executable: utils.Cmd.bun
Home Dir: ~
Config Dir: ~/.bunv
Checking dir: ~/path/to/project
Found v1.3.6 in ~/path/to/project/package.json
Original args: { bun, --version }
Modified args: { ~/.bunv/versions/1.3.6/bin/bun, --version }
---
1.3.6BUNV_AUTO_INSTALL=1to auto-install missing versions without prompting (useful in non-interactive shells).BUNV_INSTALLto change the base install directory (defaults to~/.bunv).
which bundoesn't show~/.bunv/bin/bun: ensure~/.bunv/binis at the front of yourPATH.bun upgradedoes nothing: update your version file instead (see Upgrading Bun).- No versions installed: run any
buncommand in a project with a version file or usebun --versionto auto-install.
# 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 help
# Build and install production executables to ~/.bunv/bin
$ zig build -Doptimize=ReleaseFast --prefix ~/.bunvTo 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.