# Extension points — oven-sh/bun

> Canonical page: https://codevetter.com/unpack/bun/extension-points

# Extension points — oven-sh/bun

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

Extension happens at five layers. New CLI subcommands add a `Tag` variant plus a dispatch arm and an out-lined `#[cold]` body. New JS classes are declared in `*.classes.ts` and generated into paired Rust/C++ bindings, or hand-written as the three-class JSC pattern. The `Bun` global is a static hash table in `BunObject.cpp` — adding a property is a table row plus a callback. Userland extends the bundler and runtime through `Bun.plugin` (regex-filter groups of onResolve/onLoad callbacks) and native plugins via `packages/bun-native-plugin-rs`/`-api`. Frameworks extend Bake through `FrameworkRouter` and the `UserOptions` framework description. The install path is extensible through a user-supplied security scanner module and bunfig-declared registries and scopes.
- Adding a CLI command means adding a `Tag` variant, a unique crash-report `char()`, an arm in `Command::start`'s match, and an out-lined `#[cold] #[inline(never)]` exec fn — the file documents this convention so `start` stays a jump table. — [src/options_types/command_tag.rs#L12-90](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/options_types/command_tag.rs#L12-L90) [src/runtime/cli/mod.rs#L1286-1330](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/mod.rs#L1286-L1330)
- Package-manager commands are registered through a macro table mapping an exec fn to a `(Tag, handler)` pair — `exec_install => (InstallCommand, InstallCommand::exec)` and seventeen siblings — so new pm verbs plug into one list. — [src/runtime/cli/mod.rs#L1590-1607](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/cli/mod.rs#L1590-L1607)
- New JS-visible classes are declared in a `.classes.ts` file (`define({ name, proto, values, JSType })`) and `src/codegen/generate-classes.ts` emits the prototype, constructor, subspace, and Rust binding — ~25 such definitions exist under `src/runtime/api/` alone. — [src/codegen/generate-classes.ts#L1-50](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/codegen/generate-classes.ts#L1-L50) [src/runtime/api/BunObject.classes.ts#L1-50](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/api/BunObject.classes.ts#L1-L50) [src/runtime/api/Glob.classes.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/api/Glob.classes.ts)
- Properties on the `Bun` global are added as rows in the `BunObject.cpp` static hash table, choosing between `Function`, `PropertyCallback` (lazily constructed), and `CustomAccessor` — no separate registration call is needed. — [src/jsc/bindings/BunObject.cpp#L930-1030](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/jsc/bindings/BunObject.cpp#L930-L1030)
- `Bun.plugin` is implemented as `Zig::BunPlugin` holding `Group`s of JIT-compiled `JSC::RegExp` filters paired with JS callbacks plus a `VirtualModuleMap`, targeted per `BunPluginTarget` — that is the userland hook for onResolve/onLoad. — [src/jsc/bindings/BunPlugin.h#L9-40](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/jsc/bindings/BunPlugin.h#L9-L40) [src/runtime/api/JSBundler.classes.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/api/JSBundler.classes.ts)
- Native (non-JS) bundler plugins are a supported extension surface with published scaffolding: a C API in `packages/bun-native-bundler-plugin-api` and a Rust crate in `packages/bun-native-plugin-rs`. — [packages/bun-native-bundler-plugin-api](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/packages/bun-native-bundler-plugin-api) [packages/bun-native-plugin-rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/packages/bun-native-plugin-rs)
- Bake is explicitly designed as framework infrastructure rather than a framework, with `UserOptions`/`Framework` parsed `from_js` in `bake_body.rs` and routing delegated to a pluggable `FrameworkRouter` keyed by `OpaqueFileId`. — [src/runtime/bake/mod.rs#L1-10](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bake/mod.rs#L1-L10) [src/runtime/bake/mod.rs#L38-45](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bake/mod.rs#L38-L45) [src/runtime/bake/FrameworkRouter.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bake/FrameworkRouter.rs)
- Reference framework integrations ship in-tree as plugin packages — `packages/bun-plugin-svelte`, `packages/bun-plugin-yaml`, and `src/runtime/bake/bun-framework-react` — which double as the worked examples for third parties. — [packages/bun-plugin-svelte](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/packages/bun-plugin-svelte) [packages/bun-plugin-yaml](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/packages/bun-plugin-yaml) [src/runtime/bake/bun-framework-react](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/bake/bun-framework-react)
- `bun install` accepts a user-supplied security scanner module: `scanner-entry.ts` is templated with `__SCANNER_MODULE__`/`__SUPPRESS_ERROR__`, runs the module in a child process, and returns typed `Bun.Security.Advisory[]` results. — [src/install/PackageManager/scanner-entry.ts#L1-20](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager/scanner-entry.ts#L1-L20) [src/install/PackageManager/security_scanner.rs#L50-70](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/install/PackageManager/security_scanner.rs#L50-L70)
- Registries and per-scope credentials are declarative extension points in `bunfig.toml` — `[install]` `registry` and `[install.scopes]` entries each parse into an `api::NpmRegistry` accepting either a URL string or an object with `url`/`username`/`password`/`token`. — [src/bunfig/bunfig.rs#L1177-1250](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/bunfig/bunfig.rs#L1177-L1250) [src/bunfig/bunfig.rs#L1315-1325](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/bunfig/bunfig.rs#L1315-L1325)
- Node module surface is extended by adding a TypeScript file under `src/js/node/` and, when native work is needed, a paired binding in `src/runtime/node/*_binding.rs`; the bundler picks new modules up through `internal-module-registry-scanner.ts`. — [src/js/node/quic.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/js/node/quic.ts) [src/runtime/node/node_quic_binding.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/node/node_quic_binding.rs) [src/codegen/internal-module-registry-scanner.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/codegen/internal-module-registry-scanner.ts)
- Host functions callable from bundled JS are registered through `js2native` codegen: `$rust(ffi.rs, Bun__FFI__cc)` resolves to a Rust path derived from the file basename, which is why `ffi/mod.rs` re-exports `bun__ffi__cc` under a codegen-expected module path. — [src/runtime/ffi/mod.rs#L14-22](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/ffi/mod.rs#L14-L22) [src/codegen/generate-js2native.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/codegen/generate-js2native.ts) [src/runtime/generated_js2native.rs](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/runtime/generated_js2native.rs)
- Loader/target behavior is extended through `src/options_types/` (`Loader`, `Target`, `api::Target`) rather than by branching in callers, and lower crates switch on `command_tag::Tag` without importing the CLI crate. — [src/options_types/command_tag.rs#L1-8](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/options_types/command_tag.rs#L1-L8) [src/options_types](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/options_types)
- Compile-time string→value tables are generated from `*.string-map.ts` files into `*.generated.rs` via `bun run codegen:string-maps`, with a `codegen:verify` script that fails CI if the generated output is stale. — [package.json#L70-73](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/package.json#L70-L73) [src/codegen/generate-string-map.ts](https://github.com/oven-sh/bun/blob/bf80d21c69c355f6e5bae2749485674663ed13a1/src/codegen/generate-string-map.ts)

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)
