AbsoluteJS

bvm: Bun versions

Install, switch and verify Bun versions on Linux, macOS and Windows, the way nvm does for Node. Each project runs the Bun it pins, and nothing runs until its signature checks out.

#Install

Linux, macOS and WSL. The script downloads the bvm binary for your machine, checks it against the release's signed checksum list, and sets up your shell:

BASH
curl -fsSL https://raw.githubusercontent.com/absolutejs/bvm/main/install.sh | sh

bvm works in the terminal you installed from whenever a directory already on its PATH is yours to write, such as ~/.local/bin on most Linux setups: the installer links bvm there. Otherwise it says so and prints one line that activates it in that terminal. New terminals are always set up: the installer adds bvm to the startup file of the shell you use (.bashrc, .zshrc, .bash_profile on macOS, or fish's conf.d), creating it if it does not exist yet.

BASH
# bash and zsh: activate bvm in the terminal you installed from
eval "$("$HOME/.bvm/bin/bvm" env)"

# fish
"$HOME/.bvm/bin/bvm" env --shell fish | source

Already have Bun? The installer finds it (Bun's own installer, Homebrew, npm or Scoop), installs that same version through bvm, verified, and makes it your default, so bun keeps meaning the version it meant and bvm ls is not empty. bvm's shims go ahead of the old Bun on PATH; you can remove the old install whenever you like. Output is colored on a terminal; set NO_COLOR to turn that off.

Windows (PowerShell). bvm works in the same window right away, and in new ones: the script adds it to your user PATH, tells running programs the PATH changed, and sets up the PowerShell profile your PowerShell actually loads.

BASH
powershell -c "irm https://raw.githubusercontent.com/absolutejs/bvm/main/install.ps1 | iex"

npm. The @absolutejs/bvm package installs the same signed binary for your platform, and npm's global bin directory is already on your PATH. AbsoluteJS projects already depend on it, so absolute dev can use bvm without a separate install.

BASH
npm install --global @absolutejs/bvm
# or run it once without installing
npx @absolutejs/bvm --version

#Quick start

bun and bunx become shims: each call runs the version selected for the directory you are in.

BASH
bvm -v                              # bvm 0.1.4
bvm install latest --default        # newest official Bun, used everywhere
bun --version                       # 1.4.2
bvm install 1.4.2-absolute.1        # AbsoluteJS's patched build of 1.4.2
bvm ls                              # installed versions; marks current and default

#Pin a project

bvm picks the version in this order: BVM_BUN_VERSION, the nearest .bun-version file in this directory or a parent, the nearest package.json engines.bun (the newest installed version that satisfies it), then your default. A version a project pins exactly is installed, and verified, the first time it runs there. The same .bun-version file is read by setup-bun in CI, so your machine and CI agree.

BASH
# Pin this project (and every directory below it) to one version
echo 1.4.2-absolute.1 > .bun-version
bun --version                       # runs 1.4.2-absolute.1 here

# Or require a range in package.json; bvm picks the newest installed match
# { "engines": { "bun": ">=1.4.0" } }
BASH
bvm use 1.4.2                       # this shell only (needs the bvm shell function)
bvm exec 1.4.2 -- bun test          # one command
BVM_BUN_VERSION=1.4.2 bun test      # same, by environment variable
bvm current                         # what runs here, and why

#AbsoluteJS builds

Versions such as 1.4.2-absolute.1 are official Bun with one fix: Bun.Transpiler honors reactFastRefresh, so React edits in absolute dev keep component state instead of reloading the page (oven-sh/bun#32919). They are built and published at absolutejs/patched-bun. absolute dev offers to install the right one through bvm on stock Bun; absolute bun-patch does it by hand.

#Verification

Official Bun is checked against Bun's own signed checksum list (SHASUMS256.txt.asc, PGP key F3DC C08A 8572 C074 9B3E 1888 8EAB 4D40 A7B2 2B59, the key Bun's Docker images pin). AbsoluteJS builds and bvm's own updates are checked against an Ed25519 signature by the AbsoluteJS release key. Both keys are compiled into bvm, so a mirror or a modified download cannot pass as either; a download that fails is never installed.

bvm install 1.4.2
$ bvm install 1.4.2
bvm: verifying Bun 1.4.2 (bun-linux-x64.zip) bvm: signature and checksum verified bvm: installed Bun 1.4.2

#Commands

bvm install <version> [--default]Install a version: an exact one (1.4.2, 1.4.2-absolute.1), latest (newest official Bun) or absolute (newest AbsoluteJS build). --default also makes it the default.
bvm uninstall <version> [--force]Remove an installed version. The default is refused unless you pass --force, since bun would stop working outside projects that pin a version.
bvm use <version>Use a version in this shell only. Needs the bvm shell function, which the installer sets up.
bvm default <version>Set the version used everywhere nothing else selects one.
bvm lsList installed versions, marking the one selected here and the default.
bvm ls-remote [--absolute]List versions available to install; --absolute lists AbsoluteJS builds.
bvm currentShow the version selected here, and why.
bvm which [version]Print the path of the Bun binary selected here, or of a given version.
bvm exec <version> -- <command>Run one command with a given version.
bvm env [--shell sh|fish|powershell]Print the shell code that puts bvm on PATH (eval "$(bvm env)"); --shell fish or powershell for those shells.
bvm setupInstall the bun and bunx shims and add bvm to your shell startup files. The installers run this for you.
bvm self updateReplace bvm with the newest release, after checking its signature.
bvm self uninstallRemove bvm, keeping one Bun in ~/.bun/bin. Choose it with the arrow keys, or pass --keep <version>, --keep-default or --remove-bun; --yes skips the confirmation (required without a terminal).
bvm -v, -V, --versionPrint the version of bvm itself.

#Environment variables

BVM_DIRWhere bvm keeps its shims and Bun versions. Defaults to ~/.bvm (%USERPROFILE%\.bvm on Windows).
BVM_BUN_VERSIONOverrides every other way of choosing a version; bvm use sets it for the current shell.
BVM_AUTO_INSTALLSet to 0 to stop bun from installing a version a project pins the first time it runs there.
GITHUB_TOKENOptional. bvm ls-remote lists releases through the GitHub API, which rate-limits anonymous use; install and self update do not need it.
NO_COLORTurns off colored output. CLICOLOR_FORCE=1 turns it on where bvm would not, such as a CI log.

#Updating and removing

BASH
bvm self update                     # newest signed bvm release
bvm uninstall 1.4.0                 # remove a Bun version

bvm self uninstall removes bvm and keeps one Bun where Bun's own installer puts it (~/.bun/bin, or $BUN_INSTALL), with bunx beside it, so bun and bun upgrade keep working. On a terminal you choose it with the arrow keys: your default is preselected, and a Bun you had before bvm is offered as it is. bvm shows exactly what it will change and asks before doing it. It takes its lines out of your shell startup files (on Windows, the user PATH and PowerShell profile) and leaves the rest of those files as they were. Global packages in ~/.bun are never touched.

BASH
bvm self uninstall                  # choose the Bun to keep, then confirm
bvm self uninstall --keep-default --yes   # scripts: keep the default
bvm self uninstall --keep 1.4.2 --yes     # keep a given version
bvm self uninstall --remove-bun --yes     # remove Bun too

#Troubleshooting

bvm: command not found right after installingThe installer could not link bvm into a directory on that terminal's PATH. Run the line it printed, eval "$("$HOME/.bvm/bin/bvm" env)", or open a new terminal.
bun still runs another versionAnother bun earlier on PATH (such as ~/.bun/bin) wins in a terminal opened before bvm was set up. New terminals put ~/.bvm/bin first; bvm current shows which version runs and why.
bvm use says it needs the shell functionA program cannot change its parent shell, so bvm use works through a shell function the installer adds. For a single command, use bvm exec.