Skip to main content
Bun’s runtime is designed to start fast and run fast. Under the hood, Bun uses the JavaScriptCore engine, which is developed by Apple for Safari. In most cases, startup and runtime performance is faster than V8, the engine used by Node.js. On Linux, this translates into startup times roughly 4x faster than Node.js.
CommandTime
bun hello.js5.2ms
node hello.js25.1ms
Bun’s transpiler and runtime are written in Zig, a modern, high-performance systems language.

Running a file

Use bun run to execute a source file.
bun run index.js
Bun supports TypeScript and JSX out of the box. Every file is transpiled on the fly by Bun’s fast native transpiler before being executed — no build step required.
bun run index.js
bun run index.jsx
bun run index.ts
bun run index.tsx
You can omit the run keyword entirely. It behaves identically:
bun index.tsx
bun index.ts

Reading from stdin

bun run - reads JavaScript, TypeScript, TSX, or JSX from stdin and executes it without writing a temporary file.
echo "console.log('Hello')" | bun run -
All code piped via stdin is treated as TypeScript with JSX support.

Watch mode

Use the --watch flag to automatically restart the process when files change.
bun --watch run index.tsx
When using bun run, place Bun flags immediately after bun, not after the script name.
bun --watch run dev   # correct
bun run dev --watch   # incorrect — flag is passed to the script
For soft reloading without a full process restart, use --hot instead:
bun --hot run server.ts
See Watch Mode for a full comparison of --watch and --hot.

Running package.json scripts

Bun can run scripts defined in your package.json:
{
  "scripts": {
    "clean": "rm -rf dist && echo 'Done.'",
    "dev": "bun server.ts"
  }
}
bun run clean
bun run dev
The startup time for npm run on Linux is roughly 170ms; with Bun it is 6ms.
To list all available scripts, run bun run with no arguments:
bun run
quickstart scripts:

 bun run clean
   rm -rf dist && echo 'Done.'

 bun run dev
   bun server.ts

2 scripts
Bun respects lifecycle hooks. Running bun run clean will execute preclean and postclean if they are defined. If the pre<script> step fails, the main script is not executed.

Running scripts with --bun

Package.json scripts often reference locally installed CLIs (such as vite or next) that include a #!/usr/bin/env node shebang. By default, Bun respects this and invokes them with node. Use --bun to run them with Bun instead:
bun run --bun vite

Filtering in monorepos

In a monorepo with multiple packages, use --filter to run a script across all packages whose name matches a pattern:
bun run --filter 'ba*' build
This runs build in every package whose name starts with ba.

Resolution order

When you run bun run <name>, Bun resolves in this order:
  1. package.json scripts (e.g., bun run build)
  2. Source files (e.g., bun run src/main.js)
  3. Binaries from project packages (e.g., bun run eslint)
  4. System commands (e.g., bun run ls)
Absolute paths and paths starting with ./ are always executed as source files.

Configuring the runtime with bunfig.toml

Bun’s runtime behavior can be configured with a bunfig.toml file in your project root. This file is optional — Bun works without it. For Bun-specific settings not covered by package.json or tsconfig.json, bunfig.toml is the right place.

Preloading scripts

Run scripts before your entry point executes. Useful for registering plugins or setting up test environments:
preload = ["./preload.ts"]

JSX configuration

Configure JSX handling for non-TypeScript projects (TypeScript users can use tsconfig.json compilerOptions instead):
jsx = "react"
jsxFactory = "h"
jsxFragment = "Fragment"
jsxImportSource = "react"

Reducing memory usage

Use smol mode to reduce memory consumption at the cost of performance. Useful in memory-constrained environments:
smol = true
This can also be set per-run with the --smol CLI flag:
bun --smol run index.tsx

Custom file loaders

Map file extensions to Bun loaders. For example, to treat .bagel files as TSX:
[loader]
".bagel" = "tsx"

Console output depth

Control how deeply nested objects are printed by console.log. Default is 2:
[console]
depth = 3
This can also be set per-run with --console-depth:
bun --console-depth 5 run index.tsx

Environment variable loading

By default, Bun automatically loads .env files. To disable this:
env = false
Files explicitly provided via --env-file are always loaded, regardless of this setting.

Global vs. local configuration

Place bunfig.toml in your project root alongside package.json. To configure Bun globally, create .bunfig.toml at $HOME/.bunfig.toml or $XDG_CONFIG_HOME/.bunfig.toml. When both exist, local configuration shallow-merges over global. CLI flags take precedence over both.

Environment variables

Bun automatically loads .env, .env.local, .env.production, and .env.development files. Variables are available via process.env.
console.log(process.env.MY_VAR);
You can also access environment variables through import.meta.env, which is an alias for process.env:
console.log(import.meta.env.MY_VAR);

Build docs developers (and LLMs) love