Bun

Development

Configuring a development environment for Bun usually takes 30-90 minutes depending on your operating system.

Linux/Windows

The best way to build Bun on Linux and Windows is with the official Dev Container. It ships with Zig, JavaScriptCore, Zig Language Server, and more pre-installed on an instance of Ubuntu.

To develop on Linux/Windows, Docker is required. If using WSL on Windows, it is recommended to use Docker Desktop for its WSL2 integration.

VSCode

If you're using VSCode, you'll need to have the Dev Containers extension installed.

To get started, open VS Code in the bun repository. The first time you try to open the dev container, the extension will automatically build it for you, based on Dockerfile.devcontainer.

To open the dev container, open the command palette (Ctrl + Shift + P) and run: Dev Containers: Reopen in Container. To later rebuild it (only needed when the devcontainer itself changes, not the Bun code), run: Dev Containers: Rebuild and Reopen in Container.

Other editors and CLI

If you're using another editor or want to manually control the dev container from the command line or a script, you'll need to install the Dev Container CLI: npm install -g @devcontainers/cli.

To create and start the dev container, in the bun repository, locally run:

# `make devcontainer-<command>` should be equivalent
# to `devcontainer <command>`, it just sets the architecture
# so if you're on ARM64, it'll do the right thing
make devcontainer-up

To just build the dev container image, run:

make devcontainer-build

To start a shell inside the container, run:

make devcontainer-sh

# if it attaches to the container non-interactively,
# instead use the regular docker exec command:
docker exec -it <container-name/id> zsh

Cloning

You will then need to clone the GitHub repository inside that container.

# First time setup
gh auth login # if it fails to open a browser, use Personal Access Token instead
gh repo clone oven-sh/bun . -- --depth=1 --progress -j8

Building

# Compile Bun dependencies (zig is already compiled)
make devcontainer

# It initializes and updates all submodules except WebKit, because WebKit
# takes a while and it's already compiled for you. To do it manually, use:
git -c submodule."src/bun.js/WebKit".update=none submodule update --init --recursive --depth=1 --progress

# Build Bun for development
make dev

# Run Bun
bun-debug

MacOS

Install LLVM 15 and homebrew dependencies:

brew install llvm@15 coreutils libtool cmake libiconv automake ninja gnu-sed pkg-config esbuild go rust

Bun (& the version of Zig) need LLVM 15 and Clang 15 (clang is part of LLVM). Make sure LLVM 15 is in your $PATH:

which clang-15

If not, run this to manually link it:

bash
# use fish_add_path if you're using fish
export PATH="$PATH:$(brew --prefix llvm@15)/bin"
export LDFLAGS="$LDFLAGS -L$(brew --prefix llvm@15)/lib"
export CPPFLAGS="$CPPFLAGS -I$(brew --prefix llvm@15)/include"

Install Zig

⚠️ Warning — You must use the same version of Zig used by Bun in oven-sh/zig. Installing with brew or via Zig's download page will not work!

Use zigup to install the version of Zig (ZIG_VERSION) specified in the official Dockerfile. For example:

zigup 0.11.0-dev.1783+436e99d13

Building

To install and build dependencies:

# without --depth=1 this will take 20+ minutes on 1gbps internet
# mostly due to WebKit
git submodule update --init --recursive --progress --depth=1 --checkout
bun install
make vendor identifier-cache webcrypto-debug

To compile the C++ bindings:

# without -j this will take 30+ minutes
make bindings -j12

Testing

To verify the build worked, lets print the version number on the development build of Bun.

packages/debug-bun-darwin-*/bun-debug --version
bun 0.x.y__dev

You will want to add packages/debug-bun-darwin-arm64/ or packages/debug-bun-darwin-x64/ (depending on your architecture) to $PATH so you can run bun-debug from anywhere.

Troubleshooting

If you see an error when compiling libarchive, run this:

brew install pkg-config

If you see an error about missing files on zig build obj, make sure you built the headers.

make headers

JavaScript builtins

When you change anything in src/bun.js/builtins/js/*, run this:

make clean-bindings generate-builtins && make bindings -j12

That inlines the JavaScript code into C++ headers using the same builtins generator script that Safari uses.

Code generation scripts

Bun leverages a lot of code generation scripts.

The ./src/bun.js/bindings/headers.h file has bindings to & from Zig <> C++ code. This file is generated by running the following:

make headers

This ensures that the types for Zig and the types for C++ match up correctly, by using comptime reflection over functions exported/imported.

TypeScript files that end with *.classes.ts are another code generation script. They generate C++ boilerplate for classes implemented in Zig. The generated code lives in:

make codegen

Lastly, we also have a code generation script for our native stream implementations. To run that, run:

make generate-sink

You probably won't need to run that one much.

Modifying ESM core modules

Certain modules like node:fs, node:path, node:stream, and bun:sqlite are implemented in JavaScript. These live in src/bun.js/*.exports.js files.

While Bun is in beta, you can modify them at runtime in release builds via the environment variable BUN_OVERRIDE_MODULE_PATH. When set, Bun will look in the override directory for <name>.exports.js before checking the files from src/bun.js (which are now baked in to the binary). This lets you test changes to the ESM modules without needing to re-compile Bun.

Troubleshooting

If you encounter error: the build command failed with exit code 9 during the build process, this means you ran out of memory or swap. Bun currently needs about 22 GB of RAM to compile.