oven-sh/bun
Getting started
This page is for engineers who want to build, run, and modify Bun itself. For installing the published bun binary, see bun.com/docs/installation.
Prerequisites
- ~10 GB of free disk space
- A release build of
bunalready on$PATH(Bun bootstraps with itself) - LLVM 21.1.8 — the build is pinned to this exact version
- CMake, Ninja, Go, Rust, Ruby, libtool, automake, pkg-config, autoconf
- macOS, Linux (x64/arm64), or Windows (x64/arm64). Linux kernel ≥ 5.6 recommended.
A Nix flake is provided as an alternative:
nix develop
export CMAKE_SYSTEM_PROCESSOR=$(uname -m)
bun bdFor per-distro install lists, see CONTRIBUTING.md. The Zig compiler is downloaded automatically by the build scripts; do not install it yourself.
Cloning
git clone https://github.com/oven-sh/bun
cd bunThe vendor/WebKit/ directory is not a submodule. The build downloads a prebuilt JSC archive matching the WEBKIT_VERSION pin in scripts/build/deps/webkit.ts. To compile JSC locally instead (8+ GB), see the "Building WebKit locally" section in CONTRIBUTING.md.
First build
bun run build # alias for build:debug
# or, equivalently
bun bdThis:
- Runs
scripts/build.tswhich configures CMake underbuild/debug/. - CMake invokes
zig buildagainstbuild.zigfor the Zig compilation unit. - CMake compiles the C++ side and links against vendored static libraries.
- The output is
./build/debug/bun-debug.
The first build takes 10–30 minutes depending on the machine. The Zig step is a single compilation unit and can take ~2.5 minutes by itself; C++ is incremental.
Add ./build/debug to your $PATH so you can call bun-debug directly.
Build-then-exec
bun bd accepts trailing arguments, builds, and then immediately executes:
bun bd run script.ts # debug build then `bun run script.ts`
bun bd test foo.test.ts # debug build then `bun test foo.test.ts`
bun bd -e 'console.log(Bun.version)'
bun run build:release -p 'Bun.version'When trailing args are present, build output is suppressed unless the build fails. This is the recommended workflow — never run ./build/debug/bun-debug directly.
Common build profiles
| Command | Profile | Output dir |
|---|---|---|
bun bd |
debug (ASan on by default) |
build/debug/ |
bun run build:debug:noasan |
debug-no-asan |
build/debug/ |
bun run build:release |
release |
build/release/ |
bun run build:release:lto |
release with LTO |
build/release-lto/ |
bun run build:asan |
release-asan |
build/release-asan/ |
bun run build:assert |
release-assertions |
build/release-assert/ |
bun run build:smol |
release MinSizeRel |
build/release-smol/ |
bun run build:local |
debug-local (uses local WebKit) |
build/debug-local/ |
All profiles flow through scripts/build.ts. See the file's header for argument routing rules.
Running tests
The test suite lives under test/. Run it with the debug build:
bun bd test test/js/bun/http/serve.test.ts # exact path
bun bd test http/serve.test.ts # fuzzy match
bun bd test test/js/bun/http/serve.test.ts -t "should handle"Never run bun test directly on a Bun source change — it will use the system bun, not your debug build. Same for bun foo.ts. See Testing.
The exception is type-only changes under packages/bun-types/**/*.d.ts, which can be verified by running bun test test/integration/bun-types/bun-types.test.ts directly.
Lint, format, typecheck
bun run typecheck # tsc --noEmit on the workspace and tests
bun run lint # oxlint with the repo's oxlint.json
bun run lint:fix # oxlint --fix
bun run fmt # prettier (also runs prettier-plugin-organize-imports)
bun run fmt:cpp # clang-format
bun run fmt:zig # zig fmt src/ build.zig
bun run zig:check # type-check the Zig code without producing a binary
bun run zig:check-all # zig check across all supported targets (slow)The CI runs all of these. Submitting a PR with prettier or clang-format violations will fail lint.yml / format.yml.
Environment variables for development
| Variable | Effect |
|---|---|
BUN_DEBUG_QUIET_LOGS=1 |
Suppress all Output.scoped debug logs |
BUN_DEBUG_<scope>=1 |
Enable Output.scoped(.<scope>, .hidden) for a single scope |
BUN_DEBUG=/path/to/file.log |
Tee debug logs to a file |
BUN_JSC_validateExceptionChecks=1 |
Verify JS exception scope balance (slow) |
BUN_JSC_dumpSimulatedThrows=1 |
Print stacks for simulated throws |
USE_SYSTEM_BUN=1 |
Make bun test ... invoke the system bun (used to verify a regression test actually fails on main) |
The transpiled view of any file Bun runs is dumped to /tmp/bun-debug-src/...path/to/file in debug builds.
Editor setup
VS Code is the recommended editor. Open the workspace via workspace.code-workspace. The Extensions: Show Recommended Extensions command will offer the Zig and C++ packs. ZLS is auto-configured to use vendor/zig/zig.exe (despite the .exe suffix it works on macOS / Linux).
Other editors should point ZLS at the same vendor/zig/zig.exe. The .clangd config expects compile commands at build/debug/compile_commands.json; switch to build/debug-local/... if you build against local WebKit.
CI helpers
bun run ci:status # one-screen progress summary for the current branch's build
bun run ci:errors # rendered test failures, tagged [new] vs [also on main]
bun run ci:logs # save full failed-job logs to ./tmp/ci-<build>/
bun run ci:watch # tail until completion
bun run ci:find # print the build numberThese wrap the BuildKite CLI (bk). Install it with brew install buildkite/buildkite/bk and set BUILDKITE_API_TOKEN to a read-scoped token. The repo's .bk.yaml makes -p bun unnecessary.
For PR feedback, prefer bun run pr:comments over gh pr view --comments — the former fetches issue, review, and inline comments together.
Where to go next
- For commit / PR conventions, see Development workflow.
- For idiomatic Bun code (Zig style, allocator discipline, exception scopes), see Patterns and conventions.
- For running and writing tests, see Testing.
- For debugging crashes and wrong outputs, see Debugging.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.