Bun's bundler implements a `--compile` flag for generating a standalone binary from a TypeScript or JavaScript file. {% codetabs %} ```bash $ bun build ./cli.ts --compile --outfile mycli ``` ```ts#cli.ts console.log("Hello world!"); ``` {% /codetabs %} This bundles `cli.ts` into an executable that can be executed directly: ``` $ ./mycli Hello world! ``` All imported files and packages are bundled into the executable, along with a copy of the Bun runtime. All built-in Bun and Node.js APIs are supported. ## Cross-compile to other platforms The `--target` flag lets you compile your standalone executable for a different operating system, architecture, or version of Bun than the machine you're running `bun build` on. To build for Linux x64 (most servers): ```sh bun build --compile --target=bun-linux-x64 ./index.ts --outfile myapp # To support CPUs from before 2013, use the baseline version (nehalem) bun build --compile --target=bun-linux-x64-baseline ./index.ts --outfile myapp # To explicitly only support CPUs from 2013 and later, use the modern version (haswell) # modern is faster, but baseline is more compatible. bun build --compile --target=bun-linux-x64-modern ./index.ts --outfile myapp ``` To build for Linux ARM64 (e.g. Graviton or Raspberry Pi): ```sh # Note: the default architecture is x64 if no architecture is specified. bun build --compile --target=bun-linux-arm64 ./index.ts --outfile myapp ``` To build for Windows x64: ```sh bun build --compile --target=bun-windows-x64 ./path/to/my/app.ts --outfile myapp # To support CPUs from before 2013, use the baseline version (nehalem) bun build --compile --target=bun-windows-x64-baseline ./path/to/my/app.ts --outfile myapp # To explicitly only support CPUs from 2013 and later, use the modern version (haswell) bun build --compile --target=bun-windows-x64-modern ./path/to/my/app.ts --outfile myapp # note: if no .exe extension is provided, Bun will automatically add it for Windows executables ``` To build for macOS arm64: ```sh bun build --compile --target=bun-darwin-arm64 ./path/to/my/app.ts --outfile myapp ``` To build for macOS x64: ```sh bun build --compile --target=bun-darwin-x64 ./path/to/my/app.ts --outfile myapp ``` #### Supported targets The order of the `--target` flag does not matter, as long as they're delimited by a `-`. | --target | Operating System | Architecture | Modern | Baseline | Libc | | --------------------- | ---------------- | ------------ | ------ | -------- | ----- | | bun-linux-x64 | Linux | x64 | ✅ | ✅ | glibc | | bun-linux-arm64 | Linux | arm64 | ✅ | N/A | glibc | | bun-windows-x64 | Windows | x64 | ✅ | ✅ | - | | ~~bun-windows-arm64~~ | Windows | arm64 | ❌ | ❌ | - | | bun-darwin-x64 | macOS | x64 | ✅ | ✅ | - | | bun-darwin-arm64 | macOS | arm64 | ✅ | N/A | - | | bun-linux-x64-musl | Linux | x64 | ✅ | ✅ | musl | | bun-linux-arm64-musl | Linux | arm64 | ✅ | N/A | musl | On x64 platforms, Bun uses SIMD optimizations which require a modern CPU supporting AVX2 instructions. The `-baseline` build of Bun is for older CPUs that don't support these optimizations. Normally, when you install Bun we automatically detect which version to use but this can be harder to do when cross-compiling since you might not know the target CPU. You usually don't need to worry about it on Darwin x64, but it is relevant for Windows x64 and Linux x64. If you or your users see `"Illegal instruction"` errors, you might need to use the baseline version. ## Deploying to production Compiled executables reduce memory usage and improve Bun's start time. Normally, Bun reads and transpiles JavaScript and TypeScript files on `import` and `require`. This is part of what makes so much of Bun "just work", but it's not free. It costs time and memory to read files from disk, resolve file paths, parse, transpile, and print source code. With compiled executables, you can move that cost from runtime to build-time. When deploying to production, we recommend the following: ```sh bun build --compile --minify --sourcemap ./path/to/my/app.ts --outfile myapp ``` ### Bytecode compilation To improve startup time, enable bytecode compilation: ```sh bun build --compile --minify --sourcemap --bytecode ./path/to/my/app.ts --outfile myapp ``` Using bytecode compilation, `tsc` starts 2x faster: {% image src="https://github.com/user-attachments/assets/dc8913db-01d2-48f8-a8ef-ac4e984f9763" width="689" /%} Bytecode compilation moves parsing overhead for large input files from runtime to bundle time. Your app starts faster, in exchange for making the `bun build` command a little slower. It doesn't obscure source code. **Experimental:** Bytecode compilation is an experimental feature introduced in Bun v1.1.30. Only `cjs` format is supported (which means no top-level-await). Let us know if you run into any issues! ### What do these flags do? The `--minify` argument optimizes the size of the transpiled output code. If you have a large application, this can save megabytes of space. For smaller applications, it might still improve start time a little. The `--sourcemap` argument embeds a sourcemap compressed with zstd, so that errors & stacktraces point to their original locations instead of the transpiled location. Bun will automatically decompress & resolve the sourcemap when an error occurs. The `--bytecode` argument enables bytecode compilation. Every time you run JavaScript code in Bun, JavaScriptCore (the engine) will compile your source code into bytecode. We can move this parsing work from runtime to bundle time, saving you startup time. ## Act as the Bun CLI {% note %} New in Bun v1.2.16 {% /note %} You can run a standalone executable as if it were the `bun` CLI itself by setting the `BUN_BE_BUN=1` environment variable. When this variable is set, the executable will ignore its bundled entrypoint and instead expose all the features of Bun's CLI. For example, consider an executable compiled from a simple script: ```sh $ cat such-bun.js console.log("you shouldn't see this"); $ bun build --compile ./such-bun.js [3ms] bundle 1 modules [89ms] compile such-bun ``` Normally, running `./such-bun` with arguments would execute the script. However, with the `BUN_BE_BUN=1` environment variable, it acts just like the `bun` binary: ```sh # Executable runs its own entrypoint by default $ ./such-bun install you shouldn't see this # With the env var, the executable acts like the `bun` CLI $ BUN_BE_BUN=1 ./such-bun install bun install v1.2.16-canary.1 (1d1db811) Checked 63 installs across 64 packages (no changes) [5.00ms] ``` This is useful for building CLI tools on top of Bun that may need to install packages, bundle dependencies, run different or local files and more without needing to download a separate binary or install bun. ## Full-stack executables {% note %} New in Bun v1.2.17 {% /note %} Bun's `--compile` flag can create standalone executables that contain both server and client code, making it ideal for full-stack applications. When you import an HTML file in your server code, Bun automatically bundles all frontend assets (JavaScript, CSS, etc.) and embeds them into the executable. When Bun sees the HTML import on the server, it kicks off a frontend build process to bundle JavaScript, CSS, and other assets. {% codetabs %} ```ts#server.ts import { serve } from "bun"; import index from "./index.html"; const server = serve({ routes: { "/": index, "/api/hello": { GET: () => Response.json({ message: "Hello from API" }) }, }, }); console.log(`Server running at http://localhost:${server.port}`); ``` ```html#index.html