# Contributor handoff — oven-sh/bun

> Canonical page: https://codevetter.com/unpack/bun/agent-handoff

# Contributor handoff — oven-sh/bun

Scanned commit bf80d21c69c355f6e5bae2749485674663ed13a1 (2026-09-22). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Read `CLAUDE.md`, `REVIEW.md`, `src/AGENTS.md`, and `src/js/AGENTS.md` before writing anything — they encode rules that are enforced, not suggestions. The single most important operational fact: never run `bun test` or `bun <file>` directly; use `bun bd` (which builds the debug binary and execs it with trailing args) so your native changes are actually exercised. Prefer in-tree helpers over `std` — `clippy.toml` mechanically bans `std::fs::*`, `std::env::var`, `std::thread::spawn`, and `std::mem::zeroed`. Add tests to the existing file for the module you changed, not a new file, and reserve `test/regression/issue/<n>.test.ts` for real regressions with a real issue number. Branch names must start with `claude/`. The one documented exception to the build requirement is `packages/bun-types/**/*.d.ts`, which can be tested with the system Bun.
- Build and run with `bun bd` — it builds the debug binary and passes trailing args through to it; `bun bd test <file>` is the only valid way to run tests against your changes, and `bun bd` must not be given a timeout. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [package.json#L28-31](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/package.json#L28-L31) [scripts/build.ts#L1-24](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/scripts/build.ts#L1-L24)
- Every build script supports build-then-exec with the same arg routing: build flags first, then the first unrecognized arg (or an explicit `--`) starts the exec args, and build output is suppressed unless the build fails. — [scripts/build.ts#L10-23](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/scripts/build.ts#L10-L23)
- `clippy.toml` is a hard boundary: it lists disallowed methods with replacement guidance — `std::fs::*` → `bun_sys::file`/`dir`, `std::env::var` → `bun_core::env_var`, `std::thread::spawn` → `bun_threading::spawn_named`, `std::mem::zeroed` → `MaybeUninit` (zeroed is UB for most Bun types). — [clippy.toml#L1-20](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/clippy.toml#L1-L20) [src/AGENTS.md#L30-42](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/AGENTS.md#L30-L42)
- Error handling follows a fixed shape: each crate defines a `thiserror` enum at `<crate>/error.rs` re-exported as `crate::Error`/`crate::Result`; the syscall boundary uses `bun_sys::Maybe<T>`; OOM routes through `bun_alloc::AllocError`; and `.unwrap()` is only for invariants you can prove, never for anything user input or the OS can reach. — [src/AGENTS.md#L22-28](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/AGENTS.md#L22-L28) [src/sys/Error.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/sys/Error.rs)
- `mordant.toml` runs a ratcheting Rust lint pass against `mordant-baseline.toml`: a PR fails only when it adds a new finding for an existing (lint, file) pair, so expect to either fix or regenerate the baseline via `bun run rust:mordant:baseline`. — [mordant.toml#L1-22](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/mordant.toml#L1-L22) [package.json#L66-68](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/package.json#L66-L68)
- Platform-gated code is not type-checked unless that target is built — run `bun run rust:check-all` (which drives `scripts/rust-check-all.ts` across linux/macos/windows × x64/aarch64) after touching any `#[cfg(...)]` branch. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [package.json#L63-65](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/package.json#L63-L65) [scripts/rust-check-all.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/scripts/rust-check-all.ts)
- Built-in JS in `src/js/` must be tamper-resistant: `$`-prefixed intrinsics and primordial-safe calls (`$isJSArray`, `map.$get`, `$call`), globals captured at module load, `node:`-prefixed requires, and never routing internal logic through user-overridable machinery like `Array.isArray`. — [src/js/AGENTS.md#L1-30](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/js/AGENTS.md#L1-L30) [REVIEW.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/REVIEW.md)
- Tests must copy harness conventions exactly: `tempDir` from `"harness"` (never `tmpdirSync` or `fs.mkdtempSync`), `port: 0` always, `normalizeBunSnapshot` for snapshot output, `Promise.all` to drain stdout/stderr/exited concurrently, and stdout assertions before the exit-code assertion. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [test/harness.ts#L503-512](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/test/harness.ts#L503-L512) [REVIEW.md#L14](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/REVIEW.md#L14)
- Never use `setTimeout`/`sleep` to wait for a condition in a test — poll with a deadline or await the event; reviewers treat a bare sleep of 50ms or more outside a bounded poll loop as requiring a comment naming why no observable signal exists. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [REVIEW.md#L9](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/REVIEW.md#L9)
- The single most-repeated trap in this repo's instructions: the JSC conservative stack scanner is never the cause of a bug you are debugging; a surviving object is held by a real reference, and blaming the scanner requires a heap snapshot plus a debugger session as PR artifacts. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [REVIEW.md#L33](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/REVIEW.md#L33)
- Arena allocation is a known memory trap: values in a `bumpalo`/`Arena` do not run `Drop` on reset, so anything owning a heap allocation or refcount must be freed explicitly first, mirroring the original Zig `deinit()` ordering. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [src/jsc/ModuleLoader.rs#L48-70](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/jsc/ModuleLoader.rs#L48-L70)
- Verify exception-check correctness with `BUN_JSC_validateExceptionChecks=1 BUN_JSC_dumpSimulatedThrows=1 bun bd <command>` rather than adding suppression-list entries, and silence debug logging with `BUN_DEBUG_QUIET_LOGS=1` or enable one scope with `BUN_DEBUG_<SCOPE>=1`. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [REVIEW.md#L22](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/REVIEW.md#L22)
- PR feedback is read with `bun run pr:comments` (which paginates past 100 and filters bot noise) rather than `gh`, and CI failures with `bun run ci:errors` / `ci:status` / `ci:logs`, which wrap the BuildKite CLI via `scripts/find-build.ts`. — [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md) [package.json#L20-28](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/package.json#L20-L28) [scripts/pr-comments.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/scripts/pr-comments.ts)
- Situational review rules are deliberately kept out of the main file: `.claude/docs/landing-prs.md` holds the Node/Web-compat, API-design, performance, cross-platform, vendoring, docs/types, and PR-process sections, to be read before the work each covers. — [REVIEW.md#L5](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/REVIEW.md#L5) [.claude/docs/landing-prs.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/.claude/docs/landing-prs.md) [CLAUDE.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/CLAUDE.md)
- Repo-specific skills exist for the recurring hard tasks and should be preferred over improvising: implementing JSC classes in C++ or Rust, the JSC garbage-collector reference, `bun_sys` system calls, and writing bundler and dev-server tests. — [.claude/skills](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/.claude/skills) [.claude/docs/landing-prs.md](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/.claude/docs/landing-prs.md)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
