RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Diff/oven-sh-bun-test-claude ↔ oven-sh-bun-claude

Comparison

A · CLAUDE.md · oven-sh/bunB · CLAUDE.md · oven-sh/bun
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections111183%
Commands32348%
Section tags31438%

What each file covers

Sections

1 shared · 11 only in A · 18 only in B
  • − Testing style
  • − Spawning processes
  • − No timeouts
  • − Use port 0 to get a random port
  • − Creating temporary files
  • − Strings
  • − Nested/complex object equality
  • − Common Imports from `harness`
  • − Error Testing
  • − Avoid dynamic import & require
  • − Test Utilities
  • + Building and Running Bun
  • + Build Commands
  • + Changes that don't require a build
  • + Testing
  • + Running Tests
  • + Writing Tests
  • + Code Architecture
  • + Language Structure
  • + Core Source Organization
  • + JavaScript Class Implementation (C++)
  • + Code Generation
  • + JavaScript Modules (`src/js/`)
  • + Landing PRs: What Bun Reviewers Catch
  • + Important Development Notes
  • + Debugging CI Failures
  • + Reading PR Feedback
  • + Machine-readable output for jq pipelines — one object per entry.
  • + Resolved threads and bot noise (robobun CI status, CodeRabbit summaries) are filtered out.
  •   Test Organization

Commands

3 shared · 2 only in A · 34 only in B
  • − bun bd <...cmd>
  • − bun bd <file>
  • + bun bd test foo.test.ts
  • + bun run build test foo.test.ts
  • + bun run build:release -p 'Bun.version'
  • + bun run build:local run script.ts
  • + bun test test/integration/bun-types/bun-types.test.ts
  • + bun run ci:errors
  • + bun run ci:errors '#26173'
  • + bun run ci:status
  • + bun run ci:logs
  • + bun run ci:find
  • + bun run ci:watch
  • + bun run pr:comments
  • + bun run pr:comments 28838
  • + bun run pr:comments --include-resolved
  • + bun run pr:comments --json | jq '.[] | select(.user == "Jarred-Sumner")'
  • + bun bd
  • + bun bd <command>
  • + bun run build
  • + tsc
  • + bun bd test test/js/bun/http/serve.test.ts
  • + bun bd test http/serve.test.ts
  • + bun bd test test/js/bun/http/serve.test.ts -t "should handle"
  • + bun/
  • + bun.sys
  • + node:crypto
  • + npm.rs
  • + node:fs
  • + node:*
  • + node:path
  • + bun:ffi
  • + bun:sqlite
  • + bun <file>
  • + bun bd test
  • + bun run rust:check-all
  •   bun bd test <...test file>
  •   bun:test
  •   bun bd test <file>

Section tags

3 shared · 1 only in A · 4 only in B
  • − testing-strategy
  • + build
  • + architecture
  • + git-pr
  • + docs
  •   test
  •   code-style
  •   do-not

Line diff

+168 added−176 removed72 unchanged29.0% identical
oven-sh/bun · test/CLAUDE.md
@@ −1 @@
1To run tests:
2 
3```sh
4bun bd test <...test file>
5```
6 
7To run a command with your debug build of Bun:
8 
 
 
 
 
 
 
 
 
 
 
 
 
 
9```sh
10bun bd <...cmd>
 
 
 
11```
12 
13Note that compiling Bun may take up to 2.5 minutes. It is slow!
14 
15**CRITICAL**: Do not use `bun test` to run tests. It will not have your changes. `bun bd test <...test file>` is the correct command, which compiles your code automatically.
16 
17## Testing style
18 
19Use `bun:test` with files that end in `*.test.{ts,js,jsx,tsx,mjs,cjs}`. If it's a test/js/node/test/{parallel,sequential}/\*.js without a .test.extension, use `bun bd <file>` instead of `bun bd test <file>` since those expect exit code 0 and don't use bun's test runner.
 
 
20 
21- **Do not write flaky tests**. Unless explicitly asked, **never wait for time to pass in tests**. Always wait for the condition to be met instead of waiting for an arbitrary amount of time. **Never use hardcoded port numbers**. Always use `port: 0` to get a random port.
22- **Prefer concurrent tests over sequential tests**: When multiple tests in the same file spawn processes or write files, make them concurrent with `test.concurrent` or `describe.concurrent` unless it's very difficult to make them concurrent.
23 
24### Spawning processes
25 
26#### Spawning Bun in tests
27 
28When spawning Bun processes, use `bunExe` and `bunEnv` from `harness`. This ensures the same build of Bun is used to run the test and ensures debug logging is silenced.
 
 
29 
30##### Use `-e` for single-file tests
31 
32```ts
33import { bunEnv, bunExe, tempDir } from "harness";
34import { test, expect } from "bun:test";
35 
36test("single-file test spawns a Bun process", async () => {
37 await using proc = Bun.spawn({
38 cmd: [bunExe(), "-e", "console.log('Hello, world!')"],
39 env: bunEnv,
40 });
 
 
 
41 
42 const [stdout, stderr, exitCode] = await Promise.all([
43 proc.stdout.text(),
44 proc.stderr.text(),
45 proc.exited,
46 ]);
47 
48 expect(stderr).toBe("");
49 expect(stdout).toBe("Hello, world!\n");
50 expect(exitCode).toBe(0);
51});
52```
53 
54##### When multi-file tests are required:
55 
56```ts
57import { bunEnv, bunExe, tempDir } from "harness";
58import { test, expect } from "bun:test";
 
59 
60test("multi-file test spawns a Bun process", async () => {
61 // If a test MUST use multiple files:
62 using dir = tempDir("my-test-prefix", {
63 "my.fixture.ts": `
64 import { foo } from "./foo.ts";
65 foo();
66 `,
67 "foo.ts": `
68 export function foo() {
69 console.log("Hello, world!");
70 }
71 `,
72 });
73 
74 await using proc = Bun.spawn({
75 cmd: [bunExe(), "my.fixture.ts"],
76 env: bunEnv,
77 cwd: String(dir),
 
78 });
79 
80 const [stdout, stderr, exitCode] = await Promise.all([
81 
82 // ReadableStream in Bun supports:
83 // - `await stream.text()`
84 // - `await stream.json()`
85 // - `await stream.bytes()`
86 // - `await stream.blob()`
87 proc.stdout.text(),
88 proc.stderr.text(),
89 
90 proc.exitCode,
91 ]);
92 
93 expect(stdout).toBe("Hello, world!");
94 expect(stderr).toBe("");
 
 
95 expect(exitCode).toBe(0);
 
96```
97 
98When a test file spawns a Bun process, we like for that file to end in `*-fixture.ts`. This is a convention that helps us identify the file as a test fixture and not a test itself.
 
 
 
 
 
 
 
 
 
 
99 
100Generally, `await using` or `using` is a good idea to ensure proper resource cleanup. This works in most Bun APIs like Bun.listen, Bun.connect, Bun.spawn, Bun.serve, etc.
101 
102#### Async/await in tests
103 
104Prefer async/await over callbacks.
 
 
 
105 
106When callbacks must be used and it's just a single callback, use `Promise.withResolvers` to create a promise that can be resolved or rejected from a callback.
107 
108```ts
109const ws = new WebSocket("ws://localhost:8080");
110const { promise, resolve, reject } = Promise.withResolvers<void>(); // Can specify any type here for resolution value
111ws.onopen = resolve;
112ws.onclose = reject;
113await promise;
114```
115 
116If it's several callbacks, it's okay to use callbacks. We aren't a stickler for this.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117 
118### No timeouts
119 
120**CRITICAL**: Do not set a timeout on tests. Bun already has timeouts.
121 
122### Use port 0 to get a random port
123 
124Most APIs in Bun support `port: 0` to get a random port. Never hardcode ports. Avoid using your own random port number function.
125 
126### Creating temporary files
 
 
 
 
 
 
127 
128Use `tempDirWithFiles` to create a temporary directory with files.
129 
130```ts
131import { tempDir } from "harness";
132import path from "node:path";
133 
134test("creates a temporary directory with files", () => {
135 using dir = tempDir("my-test-prefix", {
136 "file.txt": "Hello, world!",
137 });
138 
139 expect(await Bun.file(path.join(String(dir), "file.txt")).text()).toBe(
140 "Hello, world!",
141 );
142});
143```
144 
145### Strings
146 
147To create a repetitive string, use `Buffer.alloc(count, fill).toString()` instead of `"A".repeat(count)`. "".repeat is very slow in debug JavaScriptCore builds.
148 
149### Test Organization
 
 
 
 
150 
151- Use `describe` blocks for grouping related tests
152- **Add tests to the existing test file for the code you're changing** — do not create a new file. Tests are organized by module (e.g., `/test/js/bun/`, `/test/js/node/`, `/test/js/web/`).
153- `/test/regression/issue/${issueNumber}.test.ts` is **only** for bugs that have a GitHub issue number **and** are true regressions (worked in a previous release, then broke). An issue number alone does not qualify — if it was never correct, put the test in the module's existing test file instead.
154- Integration tests are in `/test/integration/`
155 
156### Nested/complex object equality
157 
158Prefer usage of `.toEqual` rather than many `.toBe` assertions for nested or complex objects.
159 
160<example>
161 
162BAD (try to avoid doing this):
 
 
 
 
 
 
 
 
 
 
 
 
 
163 
164```ts
165expect(result).toHaveLength(3);
166expect(result[0].optional).toBe(null);
167expect(result[1].optional).toBe("middle-value"); // CRITICAL: middle item's value must be preserved
168expect(result[2].optional).toBe(null);
169```
170 
171**GOOD (always prefer this):**
172 
173```ts
174expect(result).toEqual([
175 { optional: null },
176 { optional: "middle-value" }, // CRITICAL: middle item's value must be preserved
177 { optional: null },
178]);
179```
180 
181</example>
182 
183### Common Imports from `harness`
184 
185```ts
186import {
187 bunExe, // Path to Bun executable
188 bunEnv, // Environment variables for Bun
189 tempDirWithFiles, // Create temporary test directories with files
190 tmpdirSync, // Create empty temporary directory
191 isMacOS, // Platform checks
192 isWindows,
193 isPosix,
194 gcTick, // Trigger garbage collection
195 withoutAggressiveGC, // Disable aggressive GC for performance tests
196} from "harness";
197```
198 
199### Error Testing
200 
201Always check exit codes and test error scenarios:
202 
203```ts
204test("handles errors", async () => {
205 await using proc = Bun.spawn({
206 cmd: [bunExe(), "run", "invalid.js"],
207 env: bunEnv,
208 });
209 
210 const exitCode = await proc.exited;
211 expect(exitCode).not.toBe(0);
212 
213 // For synchronous errors
214 expect(() => someFunction()).toThrow("Expected error message");
215});
216```
217 
218### Avoid dynamic import & require
219 
220**Only** use dynamic import or require when the test is specifically testing something relataed to dynamic import or require. Otherwise, **always use module-scope import statements**.
221 
222**BAD, do not do this**:
223 
224```ts
225test("foo", async () => {
226 // BAD: Unnecessary usage of dynamic import.
227 const { readFile } = await import("node:fs");
228 
229 expect(await readFile("ok.txt")).toBe("");
230});
231```
232 
233**GOOD, do this:**
234 
235```ts
236import { readFile } from "node:fs";
237test("foo", async () => {
238 expect(await readFile("ok.txt")).toBe("");
239});
240```
241 
242### Test Utilities
243 
244- Use `describe.each()` for parameterized tests
245- Use `toMatchSnapshot()` for snapshot testing
246- Use `beforeAll()`, `afterEach()`, `beforeEach()` for setup/teardown
247- Track resources (servers, clients) in arrays for cleanup in `afterEach()`
248 
oven-sh/bun · CLAUDE.md
@@ +1 @@
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.
2 
3## Building and Running Bun
 
 
4 
5### Build Commands
6 
7- **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 changes
12- **Run any command with debug build**: `bun bd <command>`
13- **Run with JavaScript exception scope verification**: `BUN_JSC_validateExceptionChecks=1
14BUN_JSC_dumpSimulatedThrows=1 bun bd <command>`
15 
16Tip: Bun is already installed and in $PATH. The `bd` subcommand is a package.json script.
17 
18**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.
19 
20```sh
21bun bd test foo.test.ts # debug build + quiet debug logs
22bun run build test foo.test.ts # debug build
23bun run build:release -p 'Bun.version' # release build
24bun run build:local run script.ts # debug build with local WebKit
25```
26 
27When 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.
28 
29### Changes that don't require a build
30 
31Edits 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):
32 
33```sh
34bun test test/integration/bun-types/bun-types.test.ts
35```
36 
37This 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.
 
38 
39## Testing
40 
41### Running Tests
42 
43- **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"`
46 
47### Test Organization
48 
49**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.
 
 
50 
51- `test/js/bun/` - Bun-specific API tests (http, crypto, ffi, shell, etc.)
52- `test/js/node/` - Node.js compatibility tests
53- `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 tests
57- `test/napi/` - N-API compatibility tests
58- `test/v8/` - V8 C++ API compatibility tests
59 
60**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.
 
 
 
 
61 
62### Writing Tests
 
 
 
 
63 
64Tests use Bun's Jest-compatible test runner. For **single-file tests**, prefer spawning with `-e`; for **multi-file tests**, prefer `tempDir` and `Bun.spawn`:
65 
66```typescript
 
67import { test, expect } from "bun:test";
68import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness";
69 
70 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 });
83 
84 const [stdout, stderr, exitCode] = await Promise.all([
 
 
 
 
 
 
85 proc.stdout.text(),
86 proc.stderr.text(),
87 proc.exited,
 
88 ]);
89 
90 // Prefer snapshot tests over expect(stdout).toBe("hello\n");
91 expect(normalizeBunSnapshot(stdout, dir)).toMatchInlineSnapshot(`"foo"`);
92 
93 // Assert the exit code last. This gives you a more useful error message on test failure.
94 expect(exitCode).toBe(0);
95});
96```
97 
98- 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`.
109 
110## Code Architecture
111 
112### Language Structure
113 
114- **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 APIs
116- **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.
118 
119### Core Source Organization
120 
121The Rust side is a Cargo workspace of ~200 crates rooted at `Cargo.toml`. The key ones:
 
 
 
 
 
 
122 
123- `src/bun_core/` - The `bun.*`-namespace foundation: strings/`String` (`string/`), formatting (`fmt.rs`), logging (`output.rs`), feature flags, env vars, allocator helpers
124- `src/sys/` - Cross-platform syscall wrappers (`file.rs`, `dir.rs`, `fd.rs`, `Error.rs`, `tmp.rs`) — the `bun.sys` equivalent
125- `src/collections/`, `src/threading/`, `src/paths/`, `src/semver/`, `src/sourcemap/` - shared utilities
126- `src/bun_bin/` - Cargo entrypoint; produces `libbun_rust.a`, linked into the final binary
127- `src/runtime/cli/` - CLI argument parsing and command dispatch
128- `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 support
130- `src/resolver/` - Module resolution system
131- `src/ast/` - AST node types and arena allocation
132- `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 server
136- `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 management
140- `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 implementation
143- `src/css/` - CSS parser and processor
144- `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 framework
147 
148#### Vendored Dependencies (`vendor/`)
149 
150Third-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`.
151 
152### JavaScript Class Implementation (C++)
153 
154When implementing JavaScript classes in C++:
155 
1561. 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 arrays
1613. Add iso subspaces for classes with C++ fields
1624. Cache structures in `ZigGlobalObject`
163 
164### Code Generation
165 
166Code generation happens automatically as part of the build process. The main scripts are:
 
 
167 
168- `src/codegen/generate-classes.ts` - Generates Rust & C++ bindings from `*.classes.ts` files
169- `src/codegen/generate-jssink.ts` - Generates stream-related classes
170- `src/codegen/bundle-modules.ts` - Bundles built-in modules like `node:fs`
171- `src/codegen/bundle-functions.ts` - Bundles global functions like `ReadableStream`
172 
173In development, bundled JS modules can be reloaded without rebuilding native code by running `bun run build`.
 
 
 
 
174 
175## JavaScript Modules (`src/js/`)
176 
177Built-in JavaScript modules use special syntax and are organized as:
178 
179- `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 users
183- `builtins/` - Core JavaScript builtins (streams, console, etc.)
184 
185## Landing PRs: What Bun Reviewers Catch
 
 
 
186 
187The 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.
188 
189Several 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).
190 
191## Important Development Notes
192 
1931. **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 patterns
1975. **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 operations
1997. **Avoid shell commands** - Don't use `find` or `grep` in tests; use Bun's Glob and built-in tools
2008. **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 logger
20311. **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.
207 
208**ONLY** push up changes after running `bun bd test <file>` and ensuring your tests pass.
 
 
 
 
 
209 
210## Debugging CI Failures
211 
212Requires 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.
 
 
 
 
 
 
213 
214```bash
215bun 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 number
217bun 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 finishes
 
 
 
 
 
 
 
 
 
221```
222 
223For anything else, use `bk` directly — `bk build list`, `bk api`, `bk artifacts`, etc.
224 
225If 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`.
226 
227## Reading PR Feedback
 
 
 
 
 
228 
229`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.
 
230 
231```bash
232bun run pr:comments # current branch's PR — resolved threads hidden
233bun run pr:comments 28838 # by PR number; '#28838' and full URLs also work
234bun run pr:comments --include-resolved # also show threads already marked resolved
235 
236# 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 
@@ −1 +1 @@
1−To run tests:
1+This 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.
22  
3−```sh
4−bun bd test <...test file>
5−```
3+## Building and Running Bun
64  
7−To run a command with your debug build of Bun:
5+### Build Commands
86  
7+- **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 changes
12+- **Run any command with debug build**: `bun bd <command>`
13+- **Run with JavaScript exception scope verification**: `BUN_JSC_validateExceptionChecks=1
14+BUN_JSC_dumpSimulatedThrows=1 bun bd <command>`
15+ 
16+Tip: Bun is already installed and in $PATH. The `bd` subcommand is a package.json script.
17+ 
18+**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.
19+ 
920 ```sh
10−bun bd <...cmd>
21+bun bd test foo.test.ts # debug build + quiet debug logs
22+bun run build test foo.test.ts # debug build
23+bun run build:release -p 'Bun.version' # release build
24+bun run build:local run script.ts # debug build with local WebKit
1125 ```
1226  
13−Note that compiling Bun may take up to 2.5 minutes. It is slow!
27+When 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.
1428  
15−**CRITICAL**: Do not use `bun test` to run tests. It will not have your changes. `bun bd test <...test file>` is the correct command, which compiles your code automatically.
29+### Changes that don't require a build
1630  
17−## Testing style
31+Edits 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):
1832  
19−Use `bun:test` with files that end in `*.test.{ts,js,jsx,tsx,mjs,cjs}`. If it's a test/js/node/test/{parallel,sequential}/\*.js without a .test.extension, use `bun bd <file>` instead of `bun bd test <file>` since those expect exit code 0 and don't use bun's test runner.
33+```sh
34+bun test test/integration/bun-types/bun-types.test.ts
35+```
2036  
21−- **Do not write flaky tests**. Unless explicitly asked, **never wait for time to pass in tests**. Always wait for the condition to be met instead of waiting for an arbitrary amount of time. **Never use hardcoded port numbers**. Always use `port: 0` to get a random port.
22−- **Prefer concurrent tests over sequential tests**: When multiple tests in the same file spawn processes or write files, make them concurrent with `test.concurrent` or `describe.concurrent` unless it's very difficult to make them concurrent.
37+This 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.
2338  
24−### Spawning processes
39+## Testing
2540  
26−#### Spawning Bun in tests
41+### Running Tests
2742  
28−When spawning Bun processes, use `bunExe` and `bunEnv` from `harness`. This ensures the same build of Bun is used to run the test and ensures debug logging is silenced.
43+- **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"`
2946  
30−##### Use `-e` for single-file tests
47+### Test Organization
3148  
32−```ts
33−import { bunEnv, bunExe, tempDir } from "harness";
34−import { test, expect } from "bun:test";
49+**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.
3550  
36−test("single-file test spawns a Bun process", async () => {
37− await using proc = Bun.spawn({
38− cmd: [bunExe(), "-e", "console.log('Hello, world!')"],
39− env: bunEnv,
40− });
51+- `test/js/bun/` - Bun-specific API tests (http, crypto, ffi, shell, etc.)
52+- `test/js/node/` - Node.js compatibility tests
53+- `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 tests
57+- `test/napi/` - N-API compatibility tests
58+- `test/v8/` - V8 C++ API compatibility tests
4159  
42− const [stdout, stderr, exitCode] = await Promise.all([
43− proc.stdout.text(),
44− proc.stderr.text(),
45− proc.exited,
46− ]);
60+**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.
4761  
48− expect(stderr).toBe("");
49− expect(stdout).toBe("Hello, world!\n");
50− expect(exitCode).toBe(0);
51−});
52−```
62+### Writing Tests
5363  
54−##### When multi-file tests are required:
64+Tests use Bun's Jest-compatible test runner. For **single-file tests**, prefer spawning with `-e`; for **multi-file tests**, prefer `tempDir` and `Bun.spawn`:
5565  
56−```ts
57−import { bunEnv, bunExe, tempDir } from "harness";
66+```typescript
5867 import { test, expect } from "bun:test";
68+import { bunEnv, bunExe, normalizeBunSnapshot, tempDir } from "harness";
5969  
60−test("multi-file test spawns a Bun process", async () => {
61− // If a test MUST use multiple files:
62− using dir = tempDir("my-test-prefix", {
63− "my.fixture.ts": `
64− import { foo } from "./foo.ts";
65− foo();
66− `,
67− "foo.ts": `
68− export function foo() {
69− console.log("Hello, world!");
70− }
71− `,
70+ const [stdout, stderr, exitCode] = await Promise.all([
71+test("(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"); }`,
7275 });
73− 
76+ // For a single-file test, use: cmd: [bunExe(), "-e", `console.log("foo")`] and omit cwd.
7477 await using proc = Bun.spawn({
75− cmd: [bunExe(), "my.fixture.ts"],
78+ cmd: [bunExe(), "index.js"],
7679 env: bunEnv,
7780 cwd: String(dir),
81+ stderr: "pipe",
7882 });
7983  
8084 const [stdout, stderr, exitCode] = await Promise.all([
81− 
82− // ReadableStream in Bun supports:
83− // - `await stream.text()`
84− // - `await stream.json()`
85− // - `await stream.bytes()`
86− // - `await stream.blob()`
8785 proc.stdout.text(),
8886 proc.stderr.text(),
89− 
90− proc.exitCode,
87+ proc.exited,
9188 ]);
9289  
93− expect(stdout).toBe("Hello, world!");
94− expect(stderr).toBe("");
90+ // Prefer snapshot tests over expect(stdout).toBe("hello\n");
91+ expect(normalizeBunSnapshot(stdout, dir)).toMatchInlineSnapshot(`"foo"`);
92+ 
93+ // Assert the exit code last. This gives you a more useful error message on test failure.
9594 expect(exitCode).toBe(0);
95+});
9696 ```
9797  
98−When a test file spawns a Bun process, we like for that file to end in `*-fixture.ts`. This is a convention that helps us identify the file as a test fixture and not a test itself.
98+- 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`.
99109  
100−Generally, `await using` or `using` is a good idea to ensure proper resource cleanup. This works in most Bun APIs like Bun.listen, Bun.connect, Bun.spawn, Bun.serve, etc.
110+## Code Architecture
101111  
102−#### Async/await in tests
112+### Language Structure
103113  
104−Prefer async/await over callbacks.
114+- **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 APIs
116+- **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.
105118  
106−When callbacks must be used and it's just a single callback, use `Promise.withResolvers` to create a promise that can be resolved or rejected from a callback.
119+### Core Source Organization
107120  
108−```ts
109−const ws = new WebSocket("ws://localhost:8080");
110−const { promise, resolve, reject } = Promise.withResolvers<void>(); // Can specify any type here for resolution value
111−ws.onopen = resolve;
112−ws.onclose = reject;
113−await promise;
114−```
121+The Rust side is a Cargo workspace of ~200 crates rooted at `Cargo.toml`. The key ones:
115122  
116−If it's several callbacks, it's okay to use callbacks. We aren't a stickler for this.
123+- `src/bun_core/` - The `bun.*`-namespace foundation: strings/`String` (`string/`), formatting (`fmt.rs`), logging (`output.rs`), feature flags, env vars, allocator helpers
124+- `src/sys/` - Cross-platform syscall wrappers (`file.rs`, `dir.rs`, `fd.rs`, `Error.rs`, `tmp.rs`) — the `bun.sys` equivalent
125+- `src/collections/`, `src/threading/`, `src/paths/`, `src/semver/`, `src/sourcemap/` - shared utilities
126+- `src/bun_bin/` - Cargo entrypoint; produces `libbun_rust.a`, linked into the final binary
127+- `src/runtime/cli/` - CLI argument parsing and command dispatch
128+- `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 support
130+- `src/resolver/` - Module resolution system
131+- `src/ast/` - AST node types and arena allocation
132+- `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 server
136+- `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 management
140+- `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 implementation
143+- `src/css/` - CSS parser and processor
144+- `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 framework
117147  
118−### No timeouts
148+#### Vendored Dependencies (`vendor/`)
119149  
120−**CRITICAL**: Do not set a timeout on tests. Bun already has timeouts.
150+Third-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`.
121151  
122−### Use port 0 to get a random port
152+### JavaScript Class Implementation (C++)
123153  
124−Most APIs in Bun support `port: 0` to get a random port. Never hardcode ports. Avoid using your own random port number function.
154+When implementing JavaScript classes in C++:
125155  
126−### Creating temporary files
156+1. 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`
160+2. Define properties using HashTableValue arrays
161+3. Add iso subspaces for classes with C++ fields
162+4. Cache structures in `ZigGlobalObject`
127163  
128−Use `tempDirWithFiles` to create a temporary directory with files.
164+### Code Generation
129165  
130−```ts
131−import { tempDir } from "harness";
132−import path from "node:path";
166+Code generation happens automatically as part of the build process. The main scripts are:
133167  
134−test("creates a temporary directory with files", () => {
135− using dir = tempDir("my-test-prefix", {
136− "file.txt": "Hello, world!",
137− });
168+- `src/codegen/generate-classes.ts` - Generates Rust & C++ bindings from `*.classes.ts` files
169+- `src/codegen/generate-jssink.ts` - Generates stream-related classes
170+- `src/codegen/bundle-modules.ts` - Bundles built-in modules like `node:fs`
171+- `src/codegen/bundle-functions.ts` - Bundles global functions like `ReadableStream`
138172  
139− expect(await Bun.file(path.join(String(dir), "file.txt")).text()).toBe(
140− "Hello, world!",
141− );
142−});
143−```
173+In development, bundled JS modules can be reloaded without rebuilding native code by running `bun run build`.
144174  
145−### Strings
175+## JavaScript Modules (`src/js/`)
146176  
147−To create a repetitive string, use `Buffer.alloc(count, fill).toString()` instead of `"A".repeat(count)`. "".repeat is very slow in debug JavaScriptCore builds.
177+Built-in JavaScript modules use special syntax and are organized as:
148178  
149−### Test Organization
179+- `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 users
183+- `builtins/` - Core JavaScript builtins (streams, console, etc.)
150184  
151−- Use `describe` blocks for grouping related tests
152−- **Add tests to the existing test file for the code you're changing** — do not create a new file. Tests are organized by module (e.g., `/test/js/bun/`, `/test/js/node/`, `/test/js/web/`).
153−- `/test/regression/issue/${issueNumber}.test.ts` is **only** for bugs that have a GitHub issue number **and** are true regressions (worked in a previous release, then broke). An issue number alone does not qualify — if it was never correct, put the test in the module's existing test file instead.
154−- Integration tests are in `/test/integration/`
185+## Landing PRs: What Bun Reviewers Catch
155186  
156−### Nested/complex object equality
187+The 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.
157188  
158−Prefer usage of `.toEqual` rather than many `.toBe` assertions for nested or complex objects.
189+Several 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).
159190  
160−<example>
191+## Important Development Notes
161192  
162−BAD (try to avoid doing this):
193+1. **Never use `bun test` or `bun <file>` directly** - always use `bun bd test` or `bun bd <command>`. `bun bd` compiles & runs the debug build.
194+2. **All changes must be tested** - if you're not testing your changes, you're not done.
195+3. **Get your tests to pass**. If you didn't run the tests, your code does not work.
196+4. **Follow existing code style** - check neighboring files for patterns
197+5. **Create tests in the right folder** in `test/` and the test must end in `.test.ts` or `.test.tsx`
198+6. **Use absolute paths** - Always use absolute paths in file operations
199+7. **Avoid shell commands** - Don't use `find` or `grep` in tests; use Bun's Glob and built-in tools
200+8. **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.
201+9. **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.
202+10. **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 logger
203+11. **Be humble & honest** - NEVER overstate what you got done or what actually works in commits, PRs or in messages to the user.
204+12. **Branch names must start with `claude/`** - This is a requirement for the CI to work.
205+13. **If you need a paragraph-long comment to justify why the workaround is OK, the code is wrong — fix the code.**.
206+14. 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.
163207  
164−```ts
165−expect(result).toHaveLength(3);
166−expect(result[0].optional).toBe(null);
167−expect(result[1].optional).toBe("middle-value"); // CRITICAL: middle item's value must be preserved
168−expect(result[2].optional).toBe(null);
169−```
208+**ONLY** push up changes after running `bun bd test <file>` and ensuring your tests pass.
170209  
171−**GOOD (always prefer this):**
210+## Debugging CI Failures
172211  
173−```ts
174−expect(result).toEqual([
175− { optional: null },
176− { optional: "middle-value" }, // CRITICAL: middle item's value must be preserved
177− { optional: null },
178−]);
179−```
212+Requires 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.
180213  
181−</example>
182− 
183−### Common Imports from `harness`
184− 
185−```ts
186−import {
187− bunExe, // Path to Bun executable
188− bunEnv, // Environment variables for Bun
189− tempDirWithFiles, // Create temporary test directories with files
190− tmpdirSync, // Create empty temporary directory
191− isMacOS, // Platform checks
192− isWindows,
193− isPosix,
194− gcTick, // Trigger garbage collection
195− withoutAggressiveGC, // Disable aggressive GC for performance tests
196−} from "harness";
214+```bash
215+bun run ci:errors # rendered test-failure output for this branch's latest build, [new] vs [also on main]
216+bun run ci:errors '#26173' # or a PR number / URL / branch / build number
217+bun run ci:status # one-screen progress summary (job counts, failed jobs, failing tests so far)
218+bun run ci:logs # save full logs for every failed job to ./tmp/ci-<build>/
219+bun run ci:find # just the build number, e.g. bk job log <job-uuid> -b $(bun run ci:find)
220+bun run ci:watch # watch the current branch's build until it finishes
197221 ```
198222  
199−### Error Testing
223+For anything else, use `bk` directly — `bk build list`, `bk api`, `bk artifacts`, etc.
200224  
201−Always check exit codes and test error scenarios:
225+If 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`.
202226  
203−```ts
204−test("handles errors", async () => {
205− await using proc = Bun.spawn({
206− cmd: [bunExe(), "run", "invalid.js"],
207− env: bunEnv,
208− });
227+## Reading PR Feedback
209228  
210− const exitCode = await proc.exited;
211− expect(exitCode).not.toBe(0);
229+`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.
212230  
213− // For synchronous errors
214− expect(() => someFunction()).toThrow("Expected error message");
215−});
216−```
231+```bash
232+bun run pr:comments # current branch's PR — resolved threads hidden
233+bun run pr:comments 28838 # by PR number; '#28838' and full URLs also work
234+bun run pr:comments --include-resolved # also show threads already marked resolved
217235  
218−### Avoid dynamic import & require
219− 
220−**Only** use dynamic import or require when the test is specifically testing something relataed to dynamic import or require. Otherwise, **always use module-scope import statements**.
221− 
222−**BAD, do not do this**:
223− 
224−```ts
225−test("foo", async () => {
226− // BAD: Unnecessary usage of dynamic import.
227− const { readFile } = await import("node:fs");
228− 
229− expect(await readFile("ok.txt")).toBe("");
230−});
236+# Machine-readable output for jq pipelines — one object per entry.
237+# Resolved threads and bot noise (robobun CI status, CodeRabbit summaries) are filtered out.
238+bun run pr:comments --json | jq '.[] | select(.user == "Jarred-Sumner")'
231239 ```
232− 
233−**GOOD, do this:**
234− 
235−```ts
236−import { readFile } from "node:fs";
237−test("foo", async () => {
238− expect(await readFile("ok.txt")).toBe("");
239−});
240−```
241− 
242−### Test Utilities
243− 
244−- Use `describe.each()` for parameterized tests
245−- Use `toMatchSnapshot()` for snapshot testing
246−- Use `beforeAll()`, `afterEach()`, `beforeEach()` for setup/teardown
247−- Track resources (servers, clients) in arrays for cleanup in `afterEach()`
248240  
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack