Open-Source Wikis

/

Bun

/

How to contribute

/

Development workflow

oven-sh/bun

Development workflow

How a change goes from "I want to fix this" to "merged in main".

Branch and commit

  • Branch name must start with claude/. The CI gates on the prefix; it won't run otherwise. (Yes, this is true for human contributors too.)
  • Keep commits focused. Squash on merge is the norm. The PR description does the bulk of the explaining.
  • The default branch is main.

Build the debug binary

bun bd

bd is a package.json script that calls scripts/build.ts, which configures CMake, runs codegen, then builds Zig. The output is ./build/debug/bun-debug.

bun bd <args> builds, then runs the freshly-built binary with <args>. Always use this instead of ./build/debug/bun-debug directly — it suppresses build noise on success and gives you a clean error if the build broke.

Do not set a timeout on bun bd. First builds and post-codegen rebuilds can take several minutes.

Useful flavors:

Command Purpose
bun bd test test/js/bun/http/serve.test.ts Build + run a test.
bun bd run script.ts Build + run a script.
bun run build:release -p 'Bun.version' Release build, then bun -p.
bun run build:local run script.ts Debug build with locally-built WebKit.
bun run build --build-dir=build/baseline Park a build directory to compare later.

Iterate

Most edits touch one of three areas:

  1. Zig. Triggers a Zig recompile. Usually 5–60 s.
  2. C++. Triggers a C++ recompile. Slower than Zig.
  3. src/js/*.ts. Triggers a quick bundle-modules.ts regeneration. Often tens of seconds.

Pure TypeScript-type changes under packages/bun-types/ don't need a rebuild — run bun test test/integration/bun-types/bun-types.test.ts directly.

Test

bun bd test test/js/bun/http/serve.test.ts
bun bd test http/serve.test.ts                 # fuzzy match
bun bd test test/js/bun/http/serve.test.ts -t "should handle"

Verify your test:

  • Fails on main with USE_SYSTEM_BUN=1 bun test <file>.
  • Passes on your branch with bun bd test <file>.

If the test passes with USE_SYSTEM_BUN=1, it isn't actually exercising your fix.

Debug-log scopes

Bun has thousands of bun.Output.scoped(.MyScope, ...) log sites that fire when the matching env var is set:

BUN_DEBUG_HTTP=1 bun bd run server.ts
BUN_DEBUG_QUIET_LOGS=1 bun bd test ...   # silence everything

The list of scopes is the Output.scoped(...) declarations in the source. Grep for them.

Special debug envs:

Variable Effect
BUN_DEBUG_QUIET_LOGS=1 Disable debug logging.
BUN_JSC_validateExceptionChecks=1 Strict exception-scope checks (catches unchecked exceptions).
BUN_JSC_dumpSimulatedThrows=1 Print where simulated throws originate.
BUN_DEBUG_<scope>=1 Enable a specific scope.

Open the PR

Push to your claude/... branch and open a PR against main. Include:

  • A clear description of the change and why it's needed.
  • Links to any related issue(s).
  • Honest test status. Don't claim "tested" if you didn't run the tests.

CI

The CI runs on BuildKite. Use the helper scripts:

bun run ci:errors                  # rendered test failures for current branch
bun run ci:errors '#26173'         # by PR / build number
bun run ci:status                  # progress summary
bun run ci:logs                    # save logs for failed jobs
bun run ci:watch                   # tail until done

Setup: brew install buildkite/buildkite/bk and set BUILDKITE_API_TOKEN.

Reading PR feedback

gh pr view --comments only shows issue-stream comments — review summaries and line-level review comments are silently omitted. Use:

bun run pr:comments                # current branch's PR
bun run pr:comments 28838          # by number
bun run pr:comments --include-resolved
bun run pr:comments --json | jq '...'

This script hits all three GitHub endpoints (issues, reviews, pulls/comments), prints them chronologically, and labels each entry with its real type.

Reviewer expectations

Pulled from CLAUDE.md's "Code Review Self-Check":

  • Before writing a non-obvious change, ask "why this and not the alternative?". Research until you can answer.
  • Don't take a reporter's suggested fix at face value. Verify it's the right layer.
  • If neighbouring code does something differently than you're about to, find out why before deviating. Its choices are often load-bearing.

Commit / PR honesty

Be humble & honest. NEVER overstate what you got done or what actually works in commits, PRs or in messages to the user. — CLAUDE.md

If something is incomplete, say so in the PR.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – Bun wiki | Factory