rules_bun
API reference, generated from the module’s .bzl docstrings (stardoc).
User-facing rules for rules_bun.
Four pieces:
-
bun_test— runsbun testas a hermetic Bazel test action with explicit srcs + deps. Returns aBunTestInfoprovider wrapping the test result file (for downstream consumers; the main consumer is the test framework, which only cares about exit codes). -
bun_run— sh_binary macro:bazel run //path:NAMEinvokesbun run <script>against the live workspace source. Intentionally non-hermetic (escapes the runfiles sandbox) for the dev loop. Counterpart tobun_test’s hermetic execution. -
bun_bundle— bundle a JS/TS entry point into one self-contained file withbun build. ReturnsBunBundleInfo. -
bun_compile— compile a JS/TS entry point into a standalone native executable withbun build --compile(Bun runtime + bundled JS). ReturnsBunBinaryInfoand isbazel run-nable.
All resolve the Bun binary via @rules_bun//bun:toolchain_type (set
up by register_toolchains("@bun//:bun_toolchain_def") in your
MODULE.bazel).
bun_bundle / bun_compile have two ways to provision node_modules:
-
Bun-native (recommended; no aspect_rules_js, no pnpm-lock): pass a
node_moduleslabel (a@<name>//:node_modulesfrom abun_deps.installtag — seeextensions.bzl) plussrcs(the entry- local modules).
bun buildruns directly via the toolchain Bun; a small shell driver stages the entry into a real tree and symlinks the closure so Bun resolves the import graph natively.
- local modules).
-
Legacy aspect_rules_js: pass a
driverjs_binary whose entry point is@rules_bun//bun:bun-build-driverand whosedatastages the build entry plus its full linked node_modules closure; aspect materializes that closure into the action runfiles.
driver and node_modules are mutually exclusive — set exactly one.
bun_test likewise takes an optional node_modules for dep resolution.
bun_bundle
load("@rules_bun//bun:defs.bzl", "bun_bundle")
bun_bundle(name, srcs, out, driver, entry, external, format, node_modules, target)
Bundle a JS/TS entry into one file via the hermetic Bun toolchain. Either Bun-native (node_modules from bun_deps.install, no aspect_rules_js) or the legacy aspect driver js_binary path.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Bun-native path. The entry file + any local modules it imports, declared as action inputs. Ignored on the legacy driver path (that stages sources via the js_binary’s data). | List of labels | optional | [] |
| out | The single bundled output file (conventionally *.mjs). | Label | required | |
| driver | LEGACY aspect_rules_js path. A js_binary whose entry point is @rules_bun//bun:bun-build-driver and whose data stages the bundle entry + its full linked node_modules closure. Mutually exclusive with node_modules; set exactly one. | Label | optional | None |
| entry | Path of the entry point relative to the workspace root (e.g. packages/aion-cli/index.js). On the native path this is the execroot-relative path; on the legacy path it is relative to the driver’s _main runfiles root (same string in practice). | String | required | |
| external | Module names to exclude from the bundle (passed as --external <name>, repeatable). Use for native addons and runtime requires that must stay external, e.g. pg-native, @aws-sdk/*, encoding, source-map-support. | List of strings | optional | [] |
| format | Bun --format. Defaults to esm so import.meta in deps stays valid under Node. | String | optional | "esm" |
| node_modules | Bun-native path. A node_modules closure (typically @<name>//:node_modules from a bun_deps.install tag). When set, bun build runs directly via the toolchain Bun (no js_binary driver, no aspect_rules_js): the closure is symlinked to the execroot root so Bun resolves the import graph by walking up from entry. Mutually exclusive with driver. Pair with srcs (the entry + local modules). | Label | optional | None |
| target | Bun --target: the intended execution environment for the bundle. Defaults to node. | String | optional | "node" |
bun_compile
load("@rules_bun//bun:defs.bzl", "bun_compile")
bun_compile(name, srcs, out, driver, entry, external, node_modules, target)
Compile a JS/TS entry into a standalone native executable (Bun runtime + bundled JS) via bun build --compile. Either Bun-native (node_modules) or the legacy aspect driver path.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Bun-native path. The entry file + any local modules it imports, declared as action inputs. Ignored on the legacy driver path. | List of labels | optional | [] |
| out | The standalone executable output. On --target bun-windows-* give it a .exe suffix. | Label | required | |
| driver | LEGACY aspect_rules_js path. A js_binary whose entry point is @rules_bun//bun:bun-build-driver and whose data stages the build entry + its full linked node_modules closure. Mutually exclusive with node_modules; set exactly one. | Label | optional | None |
| entry | Path of the entry point relative to the workspace root (e.g. apps/studio-cli/index.js). | String | required | |
| external | Module names to keep external (--external <name>, repeatable). NOTE: native .node addons are NOT embedded by --compile — list them here and provide the .node files at runtime alongside the produced binary. | List of strings | optional | [] |
| node_modules | Bun-native path. A node_modules closure (typically @<name>//:node_modules from a bun_deps.install tag). When set, bun build --compile runs directly via the toolchain Bun (no js_binary driver, no aspect_rules_js). Mutually exclusive with driver. Pair with srcs. | Label | optional | None |
| target | Bun compile target triple. Empty (the default) compiles for the host platform. Cross-compile values: bun-linux-x64, bun-linux-x64-modern, bun-linux-x64-baseline, bun-linux-arm64, bun-darwin-x64, bun-darwin-arm64, bun-windows-x64, and the *-musl libc variants (e.g. bun-linux-x64-musl). A future enhancement could derive this from the Bazel --platforms via a transition; for v1 pass the string. | String | optional | "" |
bun_test
load("@rules_bun//bun:defs.bzl", "bun_test")
bun_test(name, srcs, data, node_modules)
Run bun test over the listed source files as a Bazel test target.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| srcs | Test files (typically *.test.ts, *.test.js). Each is passed to bun test explicitly so Bazel tracks them as inputs. | List of labels | required | |
| data | Additional runtime inputs (fixtures, bunfig.toml, etc.). | List of labels | optional | [] |
| node_modules | Optional node_modules closure (typically @<name>//:node_modules from a bun_deps.install tag). Staged at the workspace runfiles root as node_modules/ so bun test resolves dependency imports without bun install. The Bun-native replacement for aspect_rules_js’s npm_link_all_packages. | Label | optional | None |
BunBinaryInfo
load("@rules_bun//bun:defs.bzl", "BunBinaryInfo")
BunBinaryInfo(binary, target)
A standalone native executable produced by bun build --compile.
FIELDS
| Name | Description |
|---|---|
| binary | File: the standalone executable. |
| target | string: the Bun compile target triple (empty = host). |
BunBundleInfo
load("@rules_bun//bun:defs.bzl", "BunBundleInfo")
BunBundleInfo(bundle, format)
A single-file bundle produced by bun build.
FIELDS
BunTestInfo
load("@rules_bun//bun:defs.bzl", "BunTestInfo")
BunTestInfo(result)
Result metadata for a bun test run.
FIELDS
bun_run
load("@rules_bun//bun:defs.bzl", "bun_run")
bun_run(name, script, args, **kwargs)
Invoke bun run <script> against the live workspace source.
Escapes the runfiles sandbox via BUILD_WORKSPACE_DIRECTORY so Bun
resolves modules + reads files from the user’s actual source tree.
Intentionally NOT hermetic — that’s bun_test’s job.
PARAMETERS
Module extensions for rules_bun.
Two extensions:
-
bun— auto-fetches a prebuilt Bun binary for the host platform. Versions are sha256-pinned inprivate/known_versions.bzl. Consumers can override via thetoolchaintag class.bun = use_extension("@rules_bun//bun:extensions.bzl", "bun") use_repo(bun, "bun") register_toolchains("@bun//:bun_toolchain_def")Pin a specific version:
bun.toolchain(version = "1.3.14") -
bun_deps— Bun-nativenode_modulesstaging. Eachinstalltag produces a repo@<name>whose:node_modulesfilegroup is abun install --frozen-lockfile-ed tree. The pure-Bun replacement for aspect_rules_js’snpm_translate_lock+npm_link_all_packages(no pnpm-lock, no aspect_rules_js):bun_deps = use_extension("@rules_bun//bun:extensions.bzl", "bun_deps") bun_deps.install( name = "npm", package_json = "//:package.json", lock = "//:bun.lock", ) use_repo(bun_deps, "npm")then
bun_test(node_modules = "@npm//:node_modules", ...)andbun_bundle(node_modules = "@npm//:node_modules", ...).
The actual release fetching is delegated to
@rules_github//github:repositories.bzl%github_binary_repository
so that the URL-shape + sha-pinning logic stays consistent across
all our rules_* repos.
bun
bun = use_extension("@rules_bun//bun:extensions.bzl", "bun")
bun.toolchain(version)
Sets up @bun as a Bazel-fetched prebuilt Bun binary.
TAG CLASSES
toolchain
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| version | Override Bun version. Defaults to the value in known_versions.bzl. | String | optional | "" |
bun_deps
bun_deps = use_extension("@rules_bun//bun:extensions.bzl", "bun_deps")
bun_deps.install(name, bun_version, ignore_scripts, install_flags, lock, package_json,
trusted_dependencies)
Bun-native node_modules staging — @<name>//:node_modules from a bun install --frozen-lockfile. Replaces aspect_rules_js’s npm_translate_lock + npm_link_all_packages for pure-Bun repos.
TAG CLASSES
install
Stage a node_modules tree from a package.json + bun.lock.
Attributes
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | Name of the generated repo. Reference its node_modules as @<name>//:node_modules. | Name | required | |
| bun_version | Bun version to fetch for the install. Empty = the toolchain extension’s default. | String | optional | "" |
| ignore_scripts | Skip dependency lifecycle scripts (--ignore-scripts). Default True. | Boolean | optional | True |
| install_flags | Extra raw flags appended to bun install. | List of strings | optional | [] |
| lock | The bun.lock pinning the install (--frozen-lockfile). | Label | required | |
| package_json | The package.json to install from. | Label | required | |
| trusted_dependencies | Packages to --trust (run lifecycle scripts for) even when ignore_scripts is True. | List of strings | optional | [] |
Toolchain rule for rules_bun.
bun_toolchain wraps a single Bun binary as a Bazel toolchain.
Consumers (the bun_test and bun_run rules) resolve Bun through
@rules_bun//bun:toolchain_type, so users can register custom Bun
binaries (locally-built fork, alternate version, baseline-CPU
variant) via register_toolchains(...) without modifying rule
attrs.
The module extension at @rules_bun//bun:extensions.bzl generates a
default toolchain (@bun//:bun_toolchain_def) wrapping the prebuilt
binary. Users register it from MODULE.bazel:
register_toolchains("@bun//:bun_toolchain_def")
bun_toolchain
load("@rules_bun//bun:toolchains.bzl", "bun_toolchain")
bun_toolchain(name, bun)
Declare a Bun binary as a Bazel toolchain.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| bun | Path to the Bun executable. | Label | required |
BunToolchainInfo
load("@rules_bun//bun:toolchains.bzl", "BunToolchainInfo")
BunToolchainInfo(bun)
The Bun binary, resolved via a toolchain.
FIELDS