Basic --compile flag usage
The `--compile` flag generates a standalone binary from a TypeScript or JavaScript file. Example CLI usage: `bun build ./cli.ts --compile --outfile mycli`. In JavaScript API: `await Bun.build({ entrypoints: ["./cli.ts"], compile: { outfile: "./mycli" } });`. The resulting executable bundles all imported files, packages, and the Bun runtime, supporting all built-in Bun and Node.js APIs.
Cross-compile targets supported
Bun.build compile option supports these target strings: bun-linux-x64, bun-linux-x64-baseline, bun-linux-x64-modern, bun-linux-arm64, bun-linux-x64-musl, bun-linux-arm64-musl, bun-windows-x64, bun-windows-x64-baseline, bun-windows-x64-modern, bun-windows-arm64, bun-darwin-x64, bun-darwin-x64-baseline, bun-darwin-arm64. Use `--target` flag in CLI or `target` property in compile object. Segments can appear in any order delimited by hyphens.
Supported compile targets table
| --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 | ✅ | N/A | - |
| 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 |
CPU baseline vs modern optimization
Baseline builds support CPUs from before 2013 (Nehalem) and lack AVX2 SIMD optimizations. Modern builds (Haswell) explicitly support CPUs from 2013 and later and are faster but require AVX2. On x64 platforms, Bun uses SIMD optimizations requiring AVX2. If users see "Illegal instruction" errors, they likely need the baseline version. Mostly matters on Windows x64 and Linux x64, rarely on Darwin x64.
Build-time constants with --define
Use `--define` flag to inject build-time constants into executables. CLI example: `bun build --compile --define BUILD_VERSION='"1.2.3"' --define BUILD_TIME='"2024-01-15T10:30:00Z"' src/cli.ts --outfile mycli`. In JavaScript API, pass `define` object with keys as constant names and values as JSON-stringified values. Constants are inlined at build time for dead code elimination and zero runtime cost.
Production deployment recommendations
For production, use: `bun build --compile --minify --sourcemap ./path/to/app.ts --outfile myapp`. The `--minify` flag reduces transpiled output code size (can save megabytes for large apps). The `--sourcemap` flag embeds zstd-compressed sourcemaps so errors point to original locations. Both flags improve start time and reduce binary size.
Embedding runtime arguments with --compile-exec-argv
Use `--compile-exec-argv="args"` flag to embed runtime arguments available in `process.execArgv`. CLI example: `bun build --compile --compile-exec-argv="--smol --user-agent=MyBot" ./app.ts --outfile myapp`. In JavaScript API: `compile: { execArgv: ["--smol", "--user-agent=MyBot"], outfile: "./myapp" }`. In compiled app, access via `process.execArgv`.
Runtime arguments via BUN_OPTIONS environment variable
Standalone executables read the `BUN_OPTIONS` environment variable to pass runtime flags without recompiling. Example: `BUN_OPTIONS="--cpu-prof" ./myapp` enables CPU profiling, `BUN_OPTIONS="--heap-prof-md" ./myapp` enables heap profiling with markdown output. Multiple flags can be combined: `BUN_OPTIONS="--smol --cpu-prof-md" ./myapp`.
Automatic config loading in standalone executables
By default: tsconfig.json and package.json loading is disabled (only needed at dev time, bundler already uses them). .env and bunfig.toml loading is enabled (contain runtime config that varies per deployment). Future Bun versions may disable .env and bunfig.toml by default for deterministic behavior.
Enabling config loading at runtime flags
CLI flags to enable tsconfig.json/package.json loading: `--compile-autoload-tsconfig` and `--compile-autoload-package-json`. In JavaScript API, use `autoloadTsconfig: true` and `autoloadPackageJson: true` in compile object. Example: `bun build --compile --compile-autoload-tsconfig --compile-autoload-package-json ./app.ts --outfile myapp`.
Disabling config loading at runtime flags
CLI flags to disable .env/bunfig.toml loading: `--no-compile-autoload-dotenv` and `--no-compile-autoload-bunfig`. In JavaScript API, use `autoloadDotenv: false` and `autoloadBunfig: false` in compile object. Example: `bun build --compile --no-compile-autoload-dotenv --no-compile-autoload-bunfig ./app.ts --outfile myapp`.
BUN_BE_BUN environment variable behavior
New in Bun v1.2.16. Setting `BUN_BE_BUN=1` makes a standalone executable act as the `bun` CLI itself, ignoring its bundled entrypoint and exposing the full bun CLI. Allows CLI tools built on Bun to install packages, bundle dependencies, or run files without downloading separate binaries or installing Bun.
Full-stack executables with HTML imports
New in Bun v1.2.17. Use `--compile` to create standalone executables containing both server and client code. When importing an HTML file in server code, Bun bundles frontend assets (JavaScript, CSS, etc.) and embeds them into the executable. Single file contains: server code, Bun runtime, all frontend assets, and npm packages. HTML import replaced with manifest object that `Bun.serve` uses to serve pre-bundled assets.
Adding workers to standalone executables
Add worker entrypoints to the build: `bun build --compile ./index.ts ./my-worker.ts --outfile myapp`. In JavaScript API: `entrypoints: ["./index.ts", "./my-worker.ts"]`. Reference workers in code with any of: `new Worker("./my-worker.ts")`, `new Worker(new URL("./my-worker.ts", import.meta.url))`, or `new Worker(new URL("./my-worker.ts", import.meta.url).href)`. Each entrypoint bundled separately into executable. If using relative path not in entrypoints, Bun loads from disk relative to working directory and errors if missing.
Using bun:sqlite with --compile
You can use `bun:sqlite` imports with `bun build --compile`. By default, database is resolved relative to current working directory of the process. Example: `import db from "./my.db" with { type: "sqlite" };`. If executable at `/usr/bin/hello` and user in `/home/me/Desktop`, Bun looks for `/home/me/Desktop/my.db`.
Embed files with import attribute type:file
Use `with { type: "file" }` import attribute to embed files into binary. Example: `import icon from "./icon.png" with { type: "file" };`. During development returns file path, after compilation returns internal path like `/$bunfs/root/icon-a1b2c3d4.png`. Bun reads file contents, embeds data into executable, replaces import with internal path.
Reading embedded files with Bun.file()
Recommended method to read embedded files. `Bun.file(icon)` returns Blob. Methods include: `.arrayBuffer()` for ArrayBuffer, `.text()` for string, direct Blob access, or stream in Response. Example: `const bytes = await file(icon).arrayBuffer();` or `return new Response(file(icon), { headers: { "Content-Type": "image/png" } });`.
Reading embedded files with Node.js fs
Embedded files work with Node.js file system APIs. Synchronous: `const iconBuffer = readFileSync(icon);`. Async: `const configData = await fs.readFile(config, "utf-8");`. File stats: `const stats = await fs.stat(icon); console.log(stats.size);`. Import: `import { readFileSync, promises as fs } from "node:fs";`.
Embed SQLite databases with type:sqlite and embed:true
To embed SQLite database into compiled executable, set `type: "sqlite"` and `embed: "true"` in import attribute. Database file must exist on disk at build time. Example: `import myEmbeddedDb from "./my.db" with { type: "sqlite", embed: "true" };`. In compiled executable, database is read-write but changes lost on exit (stored in memory). When running with `bun run`, database loaded from disk normally.
Embed N-API addons into executables
You can embed `.node` files into executables. Example: `const addon = require("./addon.node"); console.log(addon.hello());`. If using `@mapbox/node-pre-gyp` or similar tools, `.node` file must be required directly or it won't bundle correctly.
Embed directories with --asset flag
Use `--asset` (or `compile.assets` in JavaScript API) to embed file or directory tree into executable under original relative path. Embedded files live under `import.meta.dir` at runtime, reachable via `node:fs` (`existsSync`, `statSync`, `readdirSync`, `readFileSync`) and `Bun.file()`. CLI example: `bun build --compile ./index.ts --asset ./public --outfile myapp`. Pass `--asset` multiple times for several directories. Only regular files embedded; symlinks and empty subdirectories skipped.
Asset naming with --asset-naming
By default, embedded files have content hash appended for cache invalidation: `icon-a1b2c3d4.png`. To keep original name, configure asset naming. CLI: `bun build --compile --asset-naming="[name].[ext]" ./index.ts`. JavaScript API: `naming: { asset: "[name].[ext]" }`. Imported assets renamed according to this pattern (default `[name]-[hash].[ext]`).
Detect standalone executable mode at runtime
Use `Bun.isStandaloneExecutable` to check if process running from compiled binary. Returns boolean. Unlike `Bun.embeddedFiles.length > 0`, this does not allocate Blob objects for each embedded file, safe to call at startup in binaries with large assets. Example: `if (Bun.isStandaloneExecutable) { /* running from compile output */ }`.
List embedded files with Bun.embeddedFiles
`Bun.embeddedFiles` exposes all embedded files as Blob objects with `name` property. Type: `ReadonlyArray<Blob>`. Example: `for (const blob of embeddedFiles) { console.log(blob.name, blob.size); }`. Output example: `icon-a1b2c3d4.png - 4096 bytes`. Excludes bundled source code (`.ts`, `.js`) to protect application source.
Minification for executable size reduction
Enable minification with `--minify` flag: `bun build --compile --minify ./index.ts --outfile myapp`. In JavaScript API: `minify: true` for all minification, or granular control: `minify: { whitespace: true, syntax: true, identifiers: true }`. Uses Bun's minifier to reduce code size. Trims down executable size.
Windows-specific compile options
Platform-specific options for customizing generated `.exe` file. CLI: `--windows-icon=path/to/icon.ico` for custom icon, `--windows-hide-console` to hide console (GUI apps). JavaScript API `windows` object with properties: `icon` (path to .ico), `hideConsole` (boolean), `title`, `publisher`, `version`, `description`, `copyright`. Except `hideConsole`, these cannot be used when cross-compiling (depend on Windows APIs).
Code signing on macOS with codesign
To codesign standalone executable on macOS (fixes Gatekeeper warnings), use `codesign` command: `codesign --deep --force -vvvv --sign "XXXXXXXXXX" ./myapp`. Recommend including `entitlements.plist` with JIT permissions. To codesign with JIT: `codesign --deep --force -vvvv --sign "XXXXXXXXXX" --entitlements entitlements.plist ./myapp`. Verify with: `codesign -vvv --verify ./myapp`. Requires Bun v1.2.4 or newer.
Code splitting in standalone executables
Standalone executables support code splitting. Use `--compile` with `--splitting`: `bun build --compile --splitting ./src/entry.ts --outfile ./build/entry`. In JavaScript API: `compile: true, splitting: true`. Creates executable that loads code-split chunks at runtime instead of monolithic bundle.
Using plugins with standalone executables
Plugins work with standalone executables to transform files during build. Example plugin transforms .env.json files into validated config objects. Pass plugins array to `Bun.build()` with `compile` option. Use cases: compile YAML/TOML configs, inline SQL queries, generate type-safe API clients, preprocess templates. See plugin documentation for details.
Unsupported CLI arguments with --compile
The `--compile` flag does not support: `--outdir` (use `outfile` instead), `--public-path`, `--target=node`, `--target=browser` without HTML entrypoints, `--no-bundle` (Bun always bundles everything into executable).
CompileBuildOptions interface
Interface for compile option in Bun.build(): `target?: Bun.Build.CompileTarget` (cross-compilation target), `outfile?: string` (output executable path), `assets?: string[]` (files/directories to embed under import.meta.dir), `execArgv?: string[]` (runtime arguments for process.execArgv), `autoloadTsconfig?: boolean` (load tsconfig.json, default false), `autoloadPackageJson?: boolean` (load package.json, default false), `autoloadDotenv?: boolean` (load .env files, default true), `autoloadBunfig?: boolean` (load bunfig.toml, default true), `windows?: { icon?, hideConsole?, title?, publisher?, version?, description?, copyright? }`.
Compile option three forms in Bun.build()
The `compile` option accepts three forms: Boolean `compile: true` (compile for current platform, uses entrypoint name as output), Target string `compile: "bun-linux-x64"` (cross-compile, uses entrypoint name as output), Full options object `compile: { target: "bun-linux-x64", outfile: "./myapp" }` (specify outfile and other options).
Standalone HTML compilation
You can bundle your entire frontend into a single self-contained .html file with no external dependencies using `--compile --target=browser`. All JavaScript, CSS, and images are inlined directly into the HTML. Example: `bun build --compile --target=browser ./index.html --outdir=dist`
compile option creates standalone executable
The `compile` option creates a standalone executable containing a copy of the Bun binary. Used with bytecode for ESM format. CLI: `bun build ./cli.tsx --outfile mycli --compile`.
Standalone HTML CLI command
Use `bun build --compile --target=browser ./index.html --outdir=dist` to create a standalone HTML file. The output is a single .html file with no relative paths, no external files, and no server required.