# Behavior traces — oven-sh/bun

> Canonical page: https://codevetter.com/unpack/bun/behavior-traces

# Behavior traces — oven-sh/bun

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

Three flows walked end to end. Startup (`bun foo.ts`): C runtime → `main` → allocator/crash/stdio init → `Cli::start` → `Command::start` → fast-path detection of a run entrypoint → `init` → `RunCommand::exec_with_cfg` → `boot` → `VirtualMachine::init_with_module_graph` → `Run::start` → `load_entry_point` → event-loop drain → `on_before_exit`. Install: `Tag::InstallCommand` → `InstallCommand::exec` → `PackageManager::init` → `install_with_manager` → lockfile load → resolution → task run → scanner → installer → lifecycle scripts → `save_lockfile`. Serve/dev: `Bun.serve` constructs a monomorphized `NewServer`, uWS delivers a request into `RequestContext`, and under Bake the DevServer checks the Host header, resolves a route through `FrameworkRouter`, incrementally bundles, and pushes HMR events over a WebSocket.
- Startup step 0 is argv capture (`bun_core::init_argv`) explicitly before `bun_crash_handler::init()`, because the crash handler's panic path prints the command line from `bun_core::argv()`. — [src/runtime/bin_entry/mod.rs#L160-171](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bin_entry/mod.rs#L160-L171)
- On Linux, `main()` calls `pregrow_fd_table()` — a `dup_at_least(stdin, 1023)` followed by `close` — before any thread exists, because `expand_fdtable()` waits for an RCU grace period once the process is multi-threaded. — [src/runtime/bin_entry/mod.rs#L200-225](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bin_entry/mod.rs#L200-L225)
- `Cli::start` sets the main-thread id for crash reporting, records the start time, initializes a process-lifetime `Log` and a `CLI_ARENA` mimalloc arena via `RacyCell` (sound because it runs single-threaded), then calls `Command::start(log)` and routes any error through `handle_root_error` after printing accumulated diagnostics. — [src/runtime/cli/mod.rs#L549-578](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/mod.rs#L549-L578)
- `Command::start` short-circuits: if `argv[1]` `looks_like_run_entrypoint`, it jumps straight to `exec_auto_or_run(Tag::AutoCommand)` without decoding the subcommand keyword table at all, and only otherwise calls `which()` to classify. — [src/runtime/cli/mod.rs#L1260-1286](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/mod.rs#L1260-L1286)
- `RunCommand::boot` calls `VirtualMachine::init_with_module_graph`, then moves preloads and passthrough argv onto the VM, leaks the entry path to `'static` (because `vm.main` is a backref and the runner never returns), wires the transpiler from the context, calls `configure_defines()`, and loads env into the HTTP client before constructing `Run` and calling `.start()`. — [src/runtime/cli/run_command.rs#L1150-1225](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1150-L1225)
- `Run::start` takes the JSC API lock and never drops it (the function is `-> !`), then in order: enables CPU/heap profilers, adds conditional globals (`Bun__ExposeNodeModuleGlobals` for `--eval`, `addGc` for `--expose-gc`), performs optional Redis and SQL preconnects under the lock, enables the hot/watch reloader, and only then loads the entry point. — [src/runtime/cli/run_command.rs#L1287-1413](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1287-L1413)
- After the entry graph evaluates, `Run::start` runs one opportunistic `release_weak_refs()` + `run_gc(false)` to drop transpiler garbage — but skips it for standalone executables, whose code blocks came from an embedded bytecode cache and would only need re-decoding. — [src/runtime/cli/run_command.rs#L1466-1482](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1466-L1482)
- The core run-loop has two shapes: under `--watch`/`--hot` it loops forever (`tick` → `auto_tick_active` → `on_before_exit` → `tick_possibly_forever`) so a rejected entry keeps the process alive; otherwise it drains until the loop is no longer alive, optionally prints the entry result for `--print`, and calls `on_before_exit` once. — [src/runtime/cli/run_command.rs#L1487-1556](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1487-L1556)
- For `--print` with a pending top-level promise, the runner attaches `Bun__onResolveEntryPointResult`/`Bun__onRejectEntryPointResult` (C-ABI shims emitted by `generate-host-exports.ts`), re-drains the loop, and then prints through `ConsoleObject::message_with_type_and_level`. — [src/runtime/cli/run_command.rs#L1512-1550](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/run_command.rs#L1512-L1550) [src/codegen/generate-host-exports.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/codegen/generate-host-exports.ts)
- `bun install` begins by prefetching DNS for the default registry — but only when there is no HTTP proxy, the mode is not offline, and the registry hostname is not already an IP address. — [src/install/PackageManager/install_with_manager.rs#L56-70](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager/install_with_manager.rs#L56-L70)
- Lockfile loading uses a single raw-pointer provenance root with an explicit SAFETY note, because `load_from_cwd` needs `manager`, `manager.lockfile`, and `manager.log` borrowed simultaneously and borrowck cannot express the disjointness. — [src/install/PackageManager/install_with_manager.rs#L72-90](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager/install_with_manager.rs#L72-L90)
- The install path decides whether to force a lockfile rewrite by OR-ing four conditions — an explicit force flag, a changed config version, a migration from another package manager, and a binary lockfile encountered while `save-text-lockfile` is set. — [src/install/PackageManager/install_with_manager.rs#L100-118](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager/install_with_manager.rs#L100-L118)
- Standalone-executable boot forces lazy argv init before reading `bun_options_argc()`, temporarily narrows `bun.argv` to executable + parsed options so user flags like `--version` are not intercepted by Bun's own parser, restores full argv, then computes the passthrough offset and calls `RunCommand::boot_standalone`. — [src/runtime/cli/mod.rs#L1340-1405](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/mod.rs#L1340-L1405)
- The dev server gates every request on `is_allowed_host_header`, which accepts a missing-Host request never, then allows `localhost`, any `*.localhost` suffix, any bare IP literal (after stripping IPv6 brackets), or an exact case-insensitive match against the configured bind hostname — a DNS-rebinding guard on the local dev origin. — [src/runtime/bake/DevServer.rs#L1365-1396](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bake/DevServer.rs#L1365-L1396)

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)
