CLAUDE.md
CLAUDE.mdCLAUDE.mdroot
Quality
96/100
Scores the file, not the repository.Length
2,285 words
20 headings · 5 code blocksRepository
95k
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.1This is the Bun repository - an all-in-one JavaScript runtime & toolkit designed for speed, with a bundler, test runner, and Node.js-compatible package manager. It's written primarily in Rust with C++ for JavaScriptCore integration, powered by WebKit's JavaScriptCore engine.23## Building and Running Bun45### Build Commands67- **Build Bun**: `bun bd`8 - Creates a debug build at `./build/debug/bun-debug`9 - **CRITICAL**: do not set a timeout when running `bun bd`10- **Run tests with your debug build**: `bun bd test <test-file>`11 - **CRITICAL**: Never use `bun test` directly - it won't include your changes12- **Run any command with debug build**: `bun bd <command>`13- **Run with JavaScript exception scope verification**: `BUN_JSC_validateExceptionChecks=114BUN_JSC_dumpSimulatedThrows=1 bun bd <command>`1516Tip: Bun is already installed and in $PATH. The `bd` subcommand is a package.json script.1718**All build scripts support build-then-exec.** Any `bun run build*` command (and `bun bd`) accepts trailing args which are passed to the built executable after building — you never invoke `./build/debug/bun-debug` directly.1920```sh21bun bd test foo.test.ts # debug build + quiet debug logs22bun run build test foo.test.ts # debug build23bun run build:release -p 'Bun.version' # release build24bun run build:local run script.ts # debug build with local WebKit25```2627When exec args are present, build output is suppressed unless the build fails — you see only the binary's output. Build flags (e.g. `--asan=off`) go before the exec args; see `scripts/build.ts` header for the full arg routing rules.2829### Changes that don't require a build3031Edits to **TypeScript type declarations** (`packages/bun-types/**/*.d.ts`) do not touch any compiled code, so `bun bd` is unnecessary. The types test just packs the `.d.ts` files and runs `tsc` against fixtures — it never executes your build. Run it directly with the system Bun (an explicit exception to the "never use `bun test` directly" rule):3233```sh34bun test test/integration/bun-types/bun-types.test.ts35```3637This is an explicit exception to the "never use `bun test` directly" rule. There are no native changes for a debug build to pick up, so don't wait on one.3839## Testing4041### Running Tests4243- **Single test file**: `bun bd test test/js/bun/http/serve.test.ts`44- **Fuzzy match test file**: `bun bd test http/serve.test.ts`45- **With filter**: `bun bd test test/js/bun/http/serve.test.ts -t "should handle"`4647### Test Organization4849**Default: add your test to the existing test file for the code you're changing.** Do not create a new file. A fetch bug goes in `test/js/web/fetch/fetch.test.ts`, a `Bun.serve` bug goes in `test/js/bun/http/serve.test.ts`, and so on. Keeping tests next to related coverage is what makes them discoverable and prevents duplicated setup.5051- `test/js/bun/` - Bun-specific API tests (http, crypto, ffi, shell, etc.)52- `test/js/node/` - Node.js compatibility tests53- `test/js/web/` - Web API tests (fetch, WebSocket, streams, etc.)54- `test/cli/` - CLI command tests (install, run, test, etc.)55- `test/bundler/` - Bundler and transpiler tests. Use `itBundled` helper.56- `test/integration/` - End-to-end integration tests57- `test/napi/` - N-API compatibility tests58- `test/v8/` - V8 C++ API compatibility tests5960**Exception:** `test/regression/issue/${issueNumber}.test.ts` is reserved for bugs with a GitHub issue number **and** that are true regressions (worked in a previous release, then broke). If the behavior was never correct, it's not a regression — the test belongs in the existing file for that module. The issue number must be **REAL**, not a placeholder.6162### Writing Tests6364Tests use Bun's Jest-compatible test runner. For **single-file tests**, prefer spawning with `-e`; for **multi-file tests**, prefer `tempDir` and `Bun.spawn`:6566```typescript67import { test, expect } from "bun:test";68import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness";6970 const [stdout, stderr, exitCode] = await Promise.all([71test("(multi-file test) my feature", async () => {72 using dir = tempDir("test-prefix", {73 "index.js": `import { foo } from "./foo.ts"; foo();`,74 "foo.ts": `export function foo() { console.log("foo"); }`,75 });76 // For a single-file test, use: cmd: [bunExe(), "-e", `console.log("foo")`] and omit cwd.77 await using proc = Bun.spawn({78 cmd: [bunExe(), "index.js"],79 env: bunEnv,80 cwd: String(dir),81 stderr: "pipe",82 });8384 const [stdout, stderr, exitCode] = await Promise.all([85 proc.stdout.text(),86 proc.stderr.text(),87 proc.exited,88 ]);8990 // Prefer snapshot tests over expect(stdout).toBe("hello\n");91 expect(normalizeBunSnapshot(stdout, dir)).toMatchInlineSnapshot(`"foo"`);9293 // Assert the exit code last. This gives you a more useful error message on test failure.94 expect(exitCode).toBe(0);95});96```9798- Always use `port: 0`. Do not hardcode ports. Do not use your own random port number function.99- Use `normalizeBunSnapshot` to normalize snapshot output of the test.100- NEVER write tests that check for no "panic" or "uncaught exception" or similar in the test output. These tests will never fail in CI.101- Use `tempDir` from `"harness"` to create a temporary directory. **Do not** use `tmpdirSync` or `fs.mkdtempSync` to create temporary directories.102- When spawning processes, tests should expect(stdout).toBe(...) BEFORE expect(exitCode).toBe(0). This gives you a more useful error message on test failure.103- Keep tests fast: budget roughly 1s per test and 10s per file. Debug+ASAN builds run 10-100x slower than release, so a 1s local test can take a minute in CI. Use `test.concurrent` for independent subprocess-spawning tests.104- Never contact the public internet (registry.npmjs.org, github.com, CDNs). Use `VerdaccioRegistry` from `"harness"` for package installs and a local `Bun.serve({ port: 0 })` for HTTP.105- `setDefaultTimeout` is a ceiling, not a target. Leave the default and pass a per-test timeout only for the rare outlier; a 5-minute file default multiplies across retries when one test hangs.106- Leak tests branch their RSS threshold on `isASAN`/`isDebug` and keep the bound well below what the unfixed leak produces. An un-branched absolute delta flakes under ASAN quarantine and GC jitter.107- **CRITICAL**: Do not write flaky tests. Do not use `setTimeout` or `await sleep(N)` to wait for a condition; poll with a deadline or `await` the event itself. You are not testing the TIME PASSING, you are testing the CONDITION.108- **CRITICAL**: Verify your test fails with `USE_SYSTEM_BUN=1 bun test <file>` and passes with `bun bd test <file>`. Your test is NOT VALID if it passes with `USE_SYSTEM_BUN=1`.109110## Code Architecture111112### Language Structure113114- **Rust code** (`src/**/*.rs`): Core runtime, JavaScript bindings, bundler, package manager. This is what compiles and ships.115- **C++ code** (`src/jsc/bindings/*.cpp`): JavaScriptCore bindings, Web APIs116- **TypeScript** (`src/js/`): Built-in JavaScript modules with special syntax (see JavaScript Modules section)117- **Generated code**: Many `.rs` and `.cpp` files are auto-generated from `.classes.ts` and other sources. The build regenerates them automatically when their inputs change.118119### Core Source Organization120121The Rust side is a Cargo workspace of ~200 crates rooted at `Cargo.toml`. The key ones:122123- `src/bun_core/` - The `bun.*`-namespace foundation: strings/`String` (`string/`), formatting (`fmt.rs`), logging (`output.rs`), feature flags, env vars, allocator helpers124- `src/sys/` - Cross-platform syscall wrappers (`file.rs`, `dir.rs`, `fd.rs`, `Error.rs`, `tmp.rs`) — the `bun.sys` equivalent125- `src/collections/`, `src/threading/`, `src/paths/`, `src/semver/`, `src/sourcemap/` - shared utilities126- `src/bun_bin/` - Cargo entrypoint; produces `libbun_rust.a`, linked into the final binary127- `src/runtime/cli/` - CLI argument parsing and command dispatch128- `src/js_parser/`, `src/js_printer/` - JavaScript/TypeScript parsing and printing (each is its own crate; the lexer is `src/js_parser/lexer.rs`)129- `src/transpiler/` - Wrapper around the parser/printer with sourcemap support130- `src/resolver/` - Module resolution system131- `src/ast/` - AST node types and arena allocation132- `src/jsc/bindings/` - C++ JavaScriptCore bindings (generated classes from `.classes.ts` + manual bindings)133- `src/jsc/` - Rust-side JSC glue (`VirtualMachine.rs`, `web_worker.rs`, `event_loop.rs`, FFI imports)134- `src/runtime/api/` - Bun-specific JS-visible APIs (`BunObject.rs`, `JSBundler.rs`, `Glob`, `Archive`, …)135- `src/runtime/server/` - `Bun.serve` HTTP/WebSocket server136- `src/runtime/node/` - Node.js compatibility layer (fs, path, process, Buffer, …)137- `src/runtime/crypto/` - WebCrypto + `node:crypto` (`EVP.rs`, `HMAC.rs`, `CryptoHasher.rs`, …)138- `src/runtime/webcore/` - Web API implementations (`fetch.rs`, `streams.rs`, `Blob.rs`, `Response.rs`, `Request.rs`, …)139- `src/event_loop/` - Event loop and task management140- `src/bundler/` - JavaScript bundler (tree-shaking, CSS processing, HTML handling)141- `src/install/` - Package manager (`lockfile/`, `npm.rs` registry client, `lifecycle_script_runner.rs`)142- `src/shell/` - Cross-platform shell implementation143- `src/css/` - CSS parser and processor144- `src/http/` - HTTP client + `websocket_client/` (WebSocket, deflate)145- `src/sql/` - SQL database integrations (Postgres, MySQL, SQLite)146- `src/bake/` - Server-side rendering / dev server framework147148#### Vendored Dependencies (`vendor/`)149150Third-party C/C++ libraries are vendored locally and can be read from disk (not git submodules): boringssl (TLS/crypto), brotli, cares (async DNS), hdrhistogram, highway (SIMD), libarchive (tar/zip), libdeflate, libuv (Windows event loop), lolhtml (HTML rewriter), lshpack (HTTP/2 HPACK), lsqpack + lsquic (HTTP/3), mimalloc (allocator), nodejs (headers), picohttpparser, tinycc (FFI JIT, fork: oven-sh/tinycc), WebKit (JavaScriptCore), zlib (zlib-ng), zstd. Build configuration for these is in `scripts/build/deps/*.ts`.151152### JavaScript Class Implementation (C++)153154When implementing JavaScript classes in C++:1551561. Create three classes if there's a public constructor:157 - `class Foo : public JSC::JSDestructibleObject` (if has C++ fields)158 - `class FooPrototype : public JSC::JSNonFinalObject`159 - `class FooConstructor : public JSC::InternalFunction`1602. Define properties using HashTableValue arrays1613. Add iso subspaces for classes with C++ fields1624. Cache structures in `ZigGlobalObject`163164### Code Generation165166Code generation happens automatically as part of the build process. The main scripts are:167168- `src/codegen/generate-classes.ts` - Generates Rust & C++ bindings from `*.classes.ts` files169- `src/codegen/generate-jssink.ts` - Generates stream-related classes170- `src/codegen/bundle-modules.ts` - Bundles built-in modules like `node:fs`171- `src/codegen/bundle-functions.ts` - Bundles global functions like `ReadableStream`172173In development, bundled JS modules can be reloaded without rebuilding native code by running `bun run build`.174175## JavaScript Modules (`src/js/`)176177Built-in JavaScript modules use special syntax and are organized as:178179- `node/` - Node.js compatibility modules (`node:fs`, `node:path`, etc.)180- `bun/` - Bun-specific modules (`bun:ffi`, `bun:sqlite`, etc.)181- `thirdparty/` - NPM modules we replace (like `ws`)182- `internal/` - Internal modules not exposed to users183- `builtins/` - Core JavaScript builtins (streams, console, etc.)184185## Landing PRs: What Bun Reviewers Catch186187The code review rules — what blocks merges, distilled from ~2,500 merged PRs — live in `REVIEW.md`. Read it before writing code that makes a non-obvious choice.188189Several situational sections live in `.claude/docs/landing-prs.md` — read the relevant one before the work it covers: **Node/Web compat** (touching `node:*` modules, Web APIs, or `src/runtime/node/`), **API design** (adding or changing user-facing API surface), **Performance** (optimizing, touching hot paths, or making perf claims), **Cross-platform** (platform-gated code, FFI/ABI, or platform-sensitive tests), **Dependencies & vendoring** (bumping deps or touching `vendor/`), **Docs, types, and comments** (docs, `.d.ts`, JSDoc), and **PR process** (opening or responding to a PR).190191## Important Development Notes1921931. **Never use `bun test` or `bun <file>` directly** - always use `bun bd test` or `bun bd <command>`. `bun bd` compiles & runs the debug build.1942. **All changes must be tested** - if you're not testing your changes, you're not done.1953. **Get your tests to pass**. If you didn't run the tests, your code does not work.1964. **Follow existing code style** - check neighboring files for patterns1975. **Create tests in the right folder** in `test/` and the test must end in `.test.ts` or `.test.tsx`1986. **Use absolute paths** - Always use absolute paths in file operations1997. **Avoid shell commands** - Don't use `find` or `grep` in tests; use Bun's Glob and built-in tools2008. **Memory management** - Prefer RAII (`Drop`) over manual cleanup. Arena edge case: values allocated in an arena (`Arena<T>`/`bumpalo`) do **not** run `Drop` on arena reset — types owning a heap allocation or refcount must be freed/deref'd explicitly first, mirroring the original Zig `deinit()` order.2019. **Cross-platform** - Run `bun run rust:check-all` to compile across all targets (linux/macos/windows × x64/aarch64) when making platform-specific changes. `#[cfg(...)]`-gated code is not type-checked unless the matching target is built.20210. **Debug builds** - Use `BUN_DEBUG_QUIET_LOGS=1` to disable debug logging, or `BUN_DEBUG_<SCOPE>=1` to enable a specific `bun_core::output` scoped logger20311. **Be humble & honest** - NEVER overstate what you got done or what actually works in commits, PRs or in messages to the user.20412. **Branch names must start with `claude/`** - This is a requirement for the CI to work.20513. **If you need a paragraph-long comment to justify why the workaround is OK, the code is wrong — fix the code.**.20614. After every code comment you write, ask yourself, "Is this information the next Claude would spend multiple tool calls trying to understand?". If the answer isn't clearly yes, the code comment is noise - delete it.207208**ONLY** push up changes after running `bun bd test <file>` and ensuring your tests pass.209210## Debugging CI Failures211212Requires the BuildKite CLI (`brew install buildkite/buildkite/bk`) and a read-scoped token in `BUILDKITE_API_TOKEN`. The repo's `.bk.yaml` sets the org/pipeline so `-p bun` is not needed.213214```bash215bun run ci:errors # rendered test-failure output for this branch's latest build, [new] vs [also on main]216bun run ci:errors '#26173' # or a PR number / URL / branch / build number217bun run ci:status # one-screen progress summary (job counts, failed jobs, failing tests so far)218bun run ci:logs # save full logs for every failed job to ./tmp/ci-<build>/219bun run ci:find # just the build number, e.g. bk job log <job-uuid> -b $(bun run ci:find)220bun run ci:watch # watch the current branch's build until it finishes221```222223For anything else, use `bk` directly — `bk build list`, `bk api`, `bk artifacts`, etc.224225If output from these commands looks wrong (mis-parsed annotation HTML, a field BuildKite changed shape on), fix `scripts/find-build.ts` directly rather than working around it — it's a thin presenter over `bk`.226227## Reading PR Feedback228229`gh pr view --comments` silently omits review summaries and line-level review comments. For the complete picture — especially when responding to a review — use `bun run pr:comments`, which fetches issue comments, reviews, and line comments in one chronological, labelled listing.230231```bash232bun run pr:comments # current branch's PR — resolved threads hidden233bun run pr:comments 28838 # by PR number; '#28838' and full URLs also work234bun run pr:comments --include-resolved # also show threads already marked resolved235236# Machine-readable output for jq pipelines — one object per entry.237# Resolved threads and bot noise (robobun CI status, CodeRabbit summaries) are filtered out.238bun run pr:comments --json | jq '.[] | select(.user == "Jarred-Sumner")'239```240
Also in oven-sh/bun
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| oven-sh/bun.github/workflows/CLAUDE.md · 95k | CLAUDE.md | testlint-formatarchgit+2 | 81/100 | today | |
| oven-sh/bunscripts/verify-baseline-static/CLAUDE.md · 95k | CLAUDE.md | buildtesting-strategy | 65/100 | 3 days ago | |
| oven-sh/bunsrc/CLAUDE.md · 95k | CLAUDE.md | setupbuildstyletypes+2 | 76/100 | 3 days ago | |
| oven-sh/bunsrc/js/CLAUDE.md · 95k | CLAUDE.md | buildarchdo-not | 85/100 | 3 days ago | |
| oven-sh/bunsrc/jsc/bindings/v8/AGENTS.md · 95k | AGENTS.md | buildtestarchtesting-strategy+4 | 81/100 | 3 days ago | |
| oven-sh/bunsrc/jsc/bindings/v8/CLAUDE.md · 95k | CLAUDE.md | buildtestarchtesting-strategy+4 | 81/100 | 3 days ago | |
| oven-sh/buntest/CLAUDE.md · 95k | CLAUDE.md | teststyletesting-strategydo-not | 97/100 | 3 days ago | |
| oven-sh/buntest/js/node/test/parallel/CLAUDE.md · 95k | CLAUDE.md | test | 43/100 | 3 days ago |
Diff against .github/workflows/CLAUDE.md Diff against scripts/verify-baseline-static/CLAUDE.md Diff against src/CLAUDE.md Diff against src/js/CLAUDE.md Diff against src/jsc/bindings/v8/AGENTS.md Diff against src/jsc/bindings/v8/CLAUDE.md Diff against test/CLAUDE.md Diff against test/js/node/test/parallel/CLAUDE.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 3 days ago | |
| livewire/livewireCLAUDE.md · 24k | CLAUDE.md | setupbuildteststyle+4 | 100/100 | 3 days ago | |
| microsoft/playwrightCLAUDE.md · 94k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 3 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.4k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 3 days ago | |
| filamentphp/filamentCLAUDE.md · 32k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 3 days ago | |
| Adit-Jain-srm/NightmareNetCLAUDE.md · 45 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 3 days ago | |
| dotCMS/coreCLAUDE.md · 949 | CLAUDE.md | setupbuildteststyle+7 | 99/100 | today |
