Skip to main content
bunfig.toml is Bun’s configuration file for customizing runtime behavior, package management, and build settings.

Location

Bun searches for bunfig.toml in these locations (in order):
  1. Current directory: ./bunfig.toml
  2. Parent directories (walks up)
  3. User home: ~/.bunfig.toml or $BUN_CONFIG_PATH
  4. System-wide: /etc/bunfig.toml (Linux)
Project-specific bunfig.toml overrides user/system configuration.

Basic Structure

bunfig.toml
# Runtime configuration
preload = ["./setup.ts"]
logLevel = "info"

# Environment variables
[env]
file = [".env", ".env.local"]

# Package manager
[install]
registry = "https://registry.npmjs.org/"

# Development server
[dev]
port = 3000

Runtime Configuration

Log Level

Control console output verbosity:
Log level
logLevel = "debug" # debug, info, warn, error
Implementation: src/bunfig.zig:109-123 - Log level parsing

Preload Scripts

Execute scripts before main entry point:
Preload
preload = [
  "./setup.ts",
  "./polyfills.ts",
  "./instrumentation.ts"
]
Use cases:
  • Environment setup
  • Polyfills
  • Global initialization
  • Monkey-patching
Implementation: src/bunfig.zig:125-149 - Preload parsing

Environment Variables

Configure .env file loading:
Environment configuration
[env]
# Disable default .env loading
file = false

# Or specify custom files
file = [".env", ".env.custom"]
Environment object
[env]
file = { file = false }  # Disable
Implementation: src/bunfig.zig:151-186 - Env config parsing

Package Manager

Configure bun install behavior:

Registry

Custom npm registry:
Registry
[install]
registry = "https://registry.npmjs.org/"

# With authentication
registry = "https://username:[email protected]/"
Registry object
[install.registry]
url = "https://registry.example.com/"
username = "user"
password = "pass"
token = "npm_xxx"
Implementation: src/bunfig.zig:45-107 - Registry parsing

Scoped Registries

Different registries per scope:
Scoped registries
[install.scopes]
"@mycompany" = "https://npm.mycompany.com/"
"@other" = { url = "https://npm.other.com/", token = "xxx" }

Cache

Configure package cache:
Cache configuration
[install]
cache = "~/.bun/install/cache" # Custom cache directory
cache = false # Disable cache

Lockfile

Lockfile behavior:
Lockfile
[install]
lockfile = true  # Generate/update lockfile (default)
lockfile = false # Disable lockfile

Production

Skip devDependencies:
Production install
[install]
production = true # Skip devDependencies

Optional Dependencies

Optional deps
[install]
optional = true  # Install optionalDependencies (default)
optional = false # Skip optionalDependencies

Exact Versions

Exact versions
[install]
exact = true # Install exact versions from lockfile

Frozen Lockfile

Frozen lockfile
[install]
frozenLockfile = true # Error if lockfile would change

Dry Run

Dry run
[install]
dryRun = true # Simulate install without writing files

Development Server

Configure bun --hot:
Dev server
[dev]
port = 3000
host = "localhost"

Test Runner

Configure bun test:
Test configuration
[test]
# Test file pattern
preload = ["./test-setup.ts"]

Build Configuration

Configure bun build:
Build config
[build]
# Loader configuration
[build.loader]
".txt" = "text"
".data" = "json"
".png" = "file"

Loader Configuration

Map file extensions to loaders:
Loaders
[loader]
".js" = "jsx"       # Treat .js as JSX
".data" = "json"    # Parse .data as JSON
".txt" = "text"     # Load .txt as text
".svg" = "text"     # SVG as text
".graphql" = "text" # GraphQL as text
See Loaders documentation for available loaders.

Macro Configuration

Configure build-time macros:
Macros
[macros]
# Import replacements
"react" = "preact/compat"

Define

Replace identifiers at build time:
Define
[define]
PROCESS_ENV_NODE_ENV = '"production"'
VERSION = '"1.0.0"'
API_URL = '"https://api.example.com"'
Usage in code:
Using defines
console.log(VERSION); // "1.0.0"
console.log(API_URL); // "https://api.example.com"

if (PROCESS_ENV_NODE_ENV === "production") {
  // Production-only code
}

External Dependencies

Mark packages as external (not bundled):
External
external = ["fsevents", "lightningcss"]

Compilation

Enable/disable features:
Compilation
[compile]
# Native compilation settings

Example Configurations

Minimal Configuration

Minimal bunfig.toml
logLevel = "info"

Development Setup

Development bunfig.toml
logLevel = "debug"
preload = ["./dev-setup.ts"]

[env]
file = [".env.development", ".env.local"]

[install]
cache = true
lockfile = true

[dev]
port = 3000

Production Setup

Production bunfig.toml
logLevel = "error"

[env]
file = ".env.production"

[install]
production = true
frozenLockfile = true
cache = "~/.bun/cache"

[define]
PROCESS_ENV_NODE_ENV = '"production"'

Monorepo Configuration

Monorepo bunfig.toml
logLevel = "info"

[install]
workspace = true
hoistPattern = ["*"]

[install.scopes]
"@myorg" = "https://npm.myorg.com/"

[loader]
".tsx" = "tsx"
".graphql" = "text"

Custom Registry

Custom registry
[install.registry]
url = "https://npm.internal.company.com/"
token = "${NPM_TOKEN}"

[install.scopes]
"@company" = "https://npm.internal.company.com/"
"@public" = "https://registry.npmjs.org/"

TOML Syntax

Bun uses standard TOML format:
TOML syntax
# Comments
# Single line comment

# Strings
string = "double quotes"
singleQuote = 'single quotes'
multiline = """
Line 1
Line 2
"""

# Numbers
integer = 42
float = 3.14

# Booleans
bool = true

# Arrays
array = [1, 2, 3]
mixed = ["a", 1, true]

# Tables (objects)
[section]
key = "value"

# Nested tables
[section.subsection]
key = "value"

# Inline tables
inline = { key = "value", another = 42 }

# Array of tables
[[items]]
name = "First"

[[items]]
name = "Second"

Environment Variable Expansion

Reference environment variables:
Environment variables
[install.registry]
url = "https://npm.company.com/"
token = "${NPM_TOKEN}" # Expands process.env.NPM_TOKEN

[define]
API_URL = '"${API_URL}"' # Expands process.env.API_URL

Configuration Validation

Bun validates bunfig.toml on startup:
Validate config
bun run app.ts
# Error: Invalid Bunfig: Unknown key "invalidKey"

Debugging Configuration

Debug config
BUN_DEBUG_QUIET_LOGS=0 bun run app.ts 2>&1 | grep -i bunfig

Check Config Location

Check config
import { bunfigPath } from "bun";
console.log(bunfigPath); // Path to loaded bunfig.toml

Implementation

Configuration parsing implementation:
  • Parser: src/bunfig.zig - TOML parsing and validation
  • Options: src/options.zig - Configuration options
  • INI parser: src/ini.zig - TOML/INI parsing utilities
Bunfig structure (src/bunfig.zig:7-18)
pub const Bunfig = struct {
    pub const OfflineMode = enum {
        online,
        latest,
        offline,
    };
    pub const Prefer = bun.ComptimeStringMap(OfflineMode, .{
        &.{ "offline", OfflineMode.offline },
        &.{ "latest", OfflineMode.latest },
        &.{ "online", OfflineMode.online },
    });
};

Common Patterns

Multi-Environment Setup

Use environment-specific configs:
Project structure
.
├── bunfig.toml          # Base config
├── bunfig.dev.toml      # Development overrides
├── bunfig.prod.toml     # Production overrides
└── package.json
package.json scripts
{
  "scripts": {
    "dev": "cp bunfig.dev.toml bunfig.toml && bun run src/index.ts",
    "prod": "cp bunfig.prod.toml bunfig.toml && bun run src/index.ts"
  }
}

Workspace Configuration

Configure for monorepos:
Workspace bunfig.toml (root)
[install]
workspace = true

[install.workspaces]
packages = ["packages/*"]

Troubleshooting

Config Not Loading

  1. Check file location: Must be in project root or home directory
  2. Check file name: Must be exactly bunfig.toml
  3. Check TOML syntax: Use TOML validator
  4. Check permissions: File must be readable

Invalid Configuration

error: Invalid Bunfig: Expected "registry" to be a URL string or an object
Solution: Check TOML syntax and field types.

Registry Authentication

For private registries:
Registry auth
[install]
registry = "https://npm.company.com/"

# Or with token
[install.registry]
url = "https://npm.company.com/"
token = "npm_xxxxxxxxxxxx"

Build docs developers (and LLMs) love