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:
# 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:
- src/bun.js/bindings/ZigGeneratedClasses.cpp
- src/bun.js/bindings/ZigGeneratedClasses.h
- src/bun.js/bindings/generated_classes.zig To generate the code, run:
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.