Skip to content

Conversation

@bmwalters
Copy link
Contributor

@bmwalters bmwalters commented Jan 4, 2026

What does this PR do?

This is an RFC for the Bun team for feedback on some changes I've been working on to enable bootstrapping an initial bun binary from node + npm + esbuild.

The rationale for this is to provide an easier path to onboard to the Bun ecosystem from:

  • source-only distros
  • potentially new OS / arch combos

Concretely, this should be most of what's needed to remove sourceProvenance = ...binaryNativeCode from Bun's nixpkg.

The changes

Bun's build scripts depend on Bun for 3 key features:

  • As a package manager.
  • As a bundler.
  • As a TypeScript runtime.

PM-agnostic codegen

There are 4-5 invocations of bun install from CMake. The package.json files in the build system are 99% compatible with npm. The patch series updates CMake scripts to enable setting an env var for which package manager to install with.

Bundler-agnostic codegen

The patch series replaces Bun.build invocations in codegen with esbuild. This required understanding the bundler output format expected by bundle-modules.ts (to create the builtins passed to JSC) and ensuring esbuild can meet that (it can, with a little config).

Runtime-agnostic codegen

There are various Bun-isms that the patch series translates to runtime agnostic equivalents. For the most part these were really quick to change (e.g. Bun.file --> fs, Bun.spawnSync --> child_process, import.meta.require --> createRequire). Most of the codegen code is actually already using runtime agnostic patterns.

The only tricky one is Bun.Transpiler.scan's use in bundle-modules.ts. I opted to call es-module-lexer but another option would be to package Bun.Transpiler sources for consumption by codegen.

The other patches for runtime support are to improve compatibility with type stripping implementations like Node has. Examples of this are adding file extensions to imports that don't already specify those, and changing declarations that are actually used at runtime (namespace foo {}; foo.xyz or declare unique symbol) to be runtime values (like const foo = {} or Symbol).

Bonus: task runner fixups

These are trivial. A small handful of files are changed from ${BUN_EXECUTABLE} run ... to ${BUN_EXECUTABLE} ... when the runnable thing is a script.

CI

I haven't drafted any updates to CI scripts or CONTRIBUTING.md

How did you verify your code works?

I built bun and bun-debug locally with all these patches stacked. I used bun-debug to run the regression suite, and bun to run OpenCode.

Next steps

This is definitely an RFC, I don't want to start sending patches towards this direction unless the Bun team gets a chance to look at this :)

I'm happy to take on the work to redo some of the patches once I send them if there are better appoaches.

Let me know what you think.

Fixes: #22991

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 4, 2026

Walkthrough

README.md was updated with a new introductory paragraph clarifying this is the bmwalters fork of Bun, detailing its focus on codegen scripts and bootstrapping via node, npm, and esbuild, and providing a link to the codegen-runtime-agnostic commit history.

Changes

Cohort / File(s) Summary
Documentation
README.md
Added introductory paragraph documenting the fork's purpose and codegen capabilities with reference to upstream commit history

Pre-merge checks

✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR successfully addresses issue #22991 by enabling bootstrapping bun from node+npm+esbuild without requiring a preexisting bun executable, removing the build-time dependency on bun itself.
Out of Scope Changes check ✅ Passed The README.md change is minimal and on-scope, noting the fork's purpose for codegen scripting. All described changes align with the objective of making the build system runtime/PM/bundler-agnostic.
Title check ✅ Passed The title accurately summarizes the main objective: making Bun's codegen runtime-agnostic to enable bootstrapping from Node + npm + esbuild, which is the core purpose of this RFC.
Description check ✅ Passed The description fully addresses both required template sections with comprehensive detail on what the PR does, the changes (PM, bundler, and runtime-agnostic codegen), and verification performed (local builds and test suite runs).

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 27ff6aa and 312aea0.

📒 Files selected for processing (1)
  • README.md
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23680
File: cmake/targets/BuildBun.cmake:822-822
Timestamp: 2025-10-15T20:19:37.256Z
Learning: In the Bun codebase, FFI (Foreign Function Interface) code is compiled separately using TinyCC (tcc), which barely supports C99. Headers like src/bun.js/api/FFI.h and src/bun.js/api/ffi-stdbool.h are only used for FFI compilation with tcc, not with the main compiler. Therefore, C standard changes to the main Bun target do not affect FFI code compilation.
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Write JS builtins for Bun's Node.js compatibility and APIs, and run `bun bd` after changes
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 23680
File: cmake/targets/BuildBun.cmake:822-822
Timestamp: 2025-10-15T20:19:38.580Z
Learning: In the Bun codebase, FFI is compiled with tcc (TinyCC), which barely supports C99. The headers `src/bun.js/api/FFI.h` and `src/bun.js/api/ffi-stdbool.h` are only used for FFI compilation with tcc, not for the main Bun target. Therefore, C23 compatibility concerns (such as bool/true/false keyword conflicts) do not apply to these FFI headers.
Learnt from: RiskyMH
Repo: oven-sh/bun PR: 24719
File: docs/bundler/executables.mdx:527-560
Timestamp: 2025-11-14T16:07:01.064Z
Learning: In the Bun repository, certain bundler features like compile with code splitting (--compile --splitting) are CLI-only and not supported in the Bun.build() JavaScript API. Tests for CLI-only features use backend: "cli" flag (e.g., test/bundler/bundler_compile_splitting.test.ts). The CompileBuildConfig interface correctly restricts these with splitting?: never;. When documenting CLI-only bundler features, add a note clarifying they're not available via the programmatic API.
Learnt from: Jarred-Sumner
Repo: oven-sh/bun PR: 23817
File: src/js/node/test.ts:282-282
Timestamp: 2025-10-18T23:43:42.502Z
Learning: In the Bun repository, the error code generation script (generate-node-errors.ts) always runs during the build process. When reviewing code that uses error code intrinsics like $ERR_TEST_FAILURE, $ERR_INVALID_ARG_TYPE, etc., do not ask to verify whether the generation script has been run or will run, as it is automatically executed.
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T00:21:32.179Z
Learning: Code generation happens automatically during the build process - bundled modules can be reloaded without rebuilding Zig by running `bun run build`
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Applies to src/js/{builtins,node,bun,thirdparty,internal}/**/*.{ts,js} : Use `process.platform` and `process.arch` for platform detection; these values are inlined and dead-code eliminated at build time
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:30.259Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : When spawning Bun processes in tests, use `bunExe` and `bunEnv` from `harness` to ensure the same build of Bun is used and debug logging is silenced
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Applies to src/bun.js/bindings/v8/test/v8/v8.test.ts : Add corresponding test cases to test/v8/v8.test.ts using checkSameOutput() function to compare Node.js and Bun output
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 24880
File: packages/bun-vscode/package.json:382-385
Timestamp: 2025-11-20T19:51:32.288Z
Learning: In the Bun repository, dependencies may be explicitly added to package.json files (even when not directly imported in code) to force version upgrades on transitive dependencies, particularly as part of Aikido security scanner remediation to ensure vulnerable transitive dependencies resolve to patched versions.
📚 Learning: 2025-11-24T18:37:11.466Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/js/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:11.466Z
Learning: Write JS builtins for Bun's Node.js compatibility and APIs, and run `bun bd` after changes

Applied to files:

  • README.md
📚 Learning: 2025-11-20T19:51:32.288Z
Learnt from: markovejnovic
Repo: oven-sh/bun PR: 24880
File: packages/bun-vscode/package.json:382-385
Timestamp: 2025-11-20T19:51:32.288Z
Learning: In the Bun repository, dependencies may be explicitly added to package.json files (even when not directly imported in code) to force version upgrades on transitive dependencies, particularly as part of Aikido security scanner remediation to ensure vulnerable transitive dependencies resolve to patched versions.

Applied to files:

  • README.md
📚 Learning: 2025-11-14T16:07:01.064Z
Learnt from: RiskyMH
Repo: oven-sh/bun PR: 24719
File: docs/bundler/executables.mdx:527-560
Timestamp: 2025-11-14T16:07:01.064Z
Learning: In the Bun repository, certain bundler features like compile with code splitting (--compile --splitting) are CLI-only and not supported in the Bun.build() JavaScript API. Tests for CLI-only features use backend: "cli" flag (e.g., test/bundler/bundler_compile_splitting.test.ts). The CompileBuildConfig interface correctly restricts these with splitting?: never;. When documenting CLI-only bundler features, add a note clarifying they're not available via the programmatic API.

Applied to files:

  • README.md
📚 Learning: 2025-10-19T02:52:37.412Z
Learnt from: theshadow27
Repo: oven-sh/bun PR: 23798
File: packages/bun-otel/tsconfig.json:1-15
Timestamp: 2025-10-19T02:52:37.412Z
Learning: In the Bun repository, packages under packages/ (e.g., bun-otel) can follow a TypeScript-first pattern where package.json exports point directly to .ts files (not compiled .js files). Bun natively runs TypeScript, so consumers import .ts sources directly and receive full type information without needing compiled .d.ts declaration files. For such packages, adding "declaration": true or "outDir" in tsconfig.json is unnecessary and would break the export structure.
<!-- [remove_learning]
ceedde95-980e-4898-a2c6-40ff73913664

Applied to files:

  • README.md
📚 Learning: 2025-11-24T18:37:30.259Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:30.259Z
Learning: Applies to test/**/*.test.{ts,js,jsx,tsx,mjs,cjs} : When spawning Bun processes in tests, use `bunExe` and `bunEnv` from `harness` to ensure the same build of Bun is used and debug logging is silenced

Applied to files:

  • README.md
📚 Learning: 2025-10-19T02:44:46.354Z
Learnt from: theshadow27
Repo: oven-sh/bun PR: 23798
File: packages/bun-otel/context-propagation.test.ts:1-1
Timestamp: 2025-10-19T02:44:46.354Z
Learning: In the Bun repository, standalone packages under packages/ (e.g., bun-vscode, bun-inspector-protocol, bun-plugin-yaml, bun-plugin-svelte, bun-debug-adapter-protocol, bun-otel) co-locate their tests with package source code using *.test.ts files. This follows standard npm/monorepo patterns. The test/ directory hierarchy (test/js/bun/, test/cli/, test/js/node/) is reserved for testing Bun's core runtime APIs and built-in functionality, not standalone packages.

Applied to files:

  • README.md
📚 Learning: 2025-11-24T18:37:30.259Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: test/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:37:30.259Z
Learning: Applies to test/js/node/test/{parallel,sequential}/*.js : For test/js/node/test/{parallel,sequential}/*.js files without a .test extension, use `bun bd <file>` instead of `bun bd test <file>` since these expect exit code 0 and don't use bun's test runner

Applied to files:

  • README.md
📚 Learning: 2025-11-24T18:36:59.706Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/CLAUDE.md:0-0
Timestamp: 2025-11-24T18:36:59.706Z
Learning: Applies to src/bun.js/bindings/v8/test/v8/v8.test.ts : Add corresponding test cases to test/v8/v8.test.ts using checkSameOutput() function to compare Node.js and Bun output

Applied to files:

  • README.md
📚 Learning: 2025-11-24T18:37:47.899Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: src/bun.js/bindings/v8/AGENTS.md:0-0
Timestamp: 2025-11-24T18:37:47.899Z
Learning: Applies to src/bun.js/bindings/v8/**/<UNKNOWN> : <UNKNOWN>

Applied to files:

  • README.md
📚 Learning: 2025-12-16T00:21:32.179Z
Learnt from: CR
Repo: oven-sh/bun PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-16T00:21:32.179Z
Learning: Code generation happens automatically during the build process - bundled modules can be reloaded without rebuilding Zig by running `bun run build`

Applied to files:

  • README.md
🪛 markdownlint-cli2 (0.18.1)
README.md

1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

Comment on lines +1 to +2
<p>This is the bmwalters fork of Bun which enables running codegen scripts and bootstrapping an initial binary using node + npm + esbuild. See [here](https://github.com/bmwalters/bun/commits/codegen-runtime-agnostic) for the list of changes.</p>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check the actual README.md file content at the beginning
head -20 README.md

Repository: oven-sh/bun

Length of output: 1223


🏁 Script executed:

# Look for linting configuration files
find . -maxdepth 2 -type f \( -name ".markdownlintrc*" -o -name "markdownlint.config.*" -o -name ".lintstagedrc*" -o -name ".prettier*" \) | head -20

Repository: oven-sh/bun

Length of output: 109


🌐 Web query:

Is https://github.com/bmwalters/bun/commits/codegen-runtime-agnostic a valid GitHub repository URL?

💡 Result:

Yes — that URL is valid. It points to the commits page for the branch "codegen-runtime-agnostic" in the bmwalters/bun repository on GitHub. [1]

Source:
[1] GitHub — bmwalters/bun — Commits (branch: codegen-runtime-agnostic).


Remove or move the introductory HTML paragraph—file should not start with <p> tag.

The file begins with an HTML <p> tag instead of a proper markdown heading or content. While the fork information is helpful, it should either be converted to markdown format or moved below the main # Bun heading. The GitHub URL is valid and reachable.

Suggested fix

Option 1: Move below the main heading and convert to markdown

Remove lines 1-2, then add after the <h1 align="center">Bun</h1> heading:

+> **Note:** This is the bmwalters fork of Bun. It enables running codegen scripts and bootstrapping an initial binary using node + npm + esbuild. See the [codegen-runtime-agnostic branch](https://github.com/bmwalters/bun/commits/codegen-runtime-agnostic) for the list of changes.

Option 2: Convert to markdown heading

-<p>This is the bmwalters fork of Bun which enables running codegen scripts and bootstrapping an initial binary using node + npm + esbuild. See [here](https://github.com/bmwalters/bun/commits/codegen-runtime-agnostic) for the list of changes.</p>
+## About This Fork
+
+This fork enables running codegen scripts and bootstrapping an initial binary using node + npm + esbuild. See the [codegen-runtime-agnostic branch](https://github.com/bmwalters/bun/commits/codegen-runtime-agnostic) for the list of changes.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p>This is the bmwalters fork of Bun which enables running codegen scripts and bootstrapping an initial binary using node + npm + esbuild. See [here](https://github.com/bmwalters/bun/commits/codegen-runtime-agnostic) for the list of changes.</p>
## About This Fork
This fork enables running codegen scripts and bootstrapping an initial binary using node + npm + esbuild. See the [codegen-runtime-agnostic branch](https://github.com/bmwalters/bun/commits/codegen-runtime-agnostic) for the list of changes.
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

1-1: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🤖 Prompt for AI Agents
In README.md around lines 1 to 2, the file starts with an HTML <p> tag that
should be removed or relocated; delete the leading <p>…</p> block and either
convert its contents to markdown (e.g., a short paragraph or subheading and the
link) and place it appropriately (for example immediately after the main "# Bun"
heading) or move it below the primary title as plain markdown; ensure no raw
HTML remains at the top and that the fork description is formatted as standard
markdown text with the link preserved.

@bmwalters bmwalters changed the title [RFC PATCH 00/44] runtime-agnostic codegen [RFC PATCH 00/44] feat(cmake): runtime-agnostic codegen Jan 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The build of bun looks for the bun executable

1 participant