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. 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 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.
You can omit the run keyword entirely. It behaves identically:

Reading from stdin

bun run - reads JavaScript, TypeScript, TSX, or JSX from stdin and executes it without writing a temporary file.
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.
When using bun run, place Bun flags immediately after bun, not after the script name.
For soft reloading without a full process restart, use --hot instead:
See Watch Mode for a full comparison of --watch and --hot.

Running package.json scripts

Bun can run scripts defined in your package.json:
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 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:

Filtering in monorepos

In a monorepo with multiple packages, use --filter to run a script across all packages whose name matches a pattern:
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:

JSX configuration

Configure JSX handling for non-TypeScript projects (TypeScript users can use tsconfig.json compilerOptions instead):

Reducing memory usage

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

Custom file loaders

Map file extensions to Bun loaders. For example, to treat .bagel files as TSX:

Console output depth

Control how deeply nested objects are printed by console.log. Default is 2:
This can also be set per-run with --console-depth:

Environment variable loading

By default, Bun automatically loads .env files. To disable this:
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.
You can also access environment variables through import.meta.env, which is an alias for process.env: