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):
- Current directory:
./bunfig.toml
- Parent directories (walks up)
- User home:
~/.bunfig.toml or $BUN_CONFIG_PATH
- System-wide:
/etc/bunfig.toml (Linux)
Project-specific bunfig.toml overrides user/system configuration.
Basic Structure
# 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:
logLevel = "debug" # debug, info, warn, error
Implementation: src/bunfig.zig:109-123 - Log level parsing
Preload Scripts
Execute scripts before main entry point:
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"]
[env]
file = { file = false } # Disable
Implementation: src/bunfig.zig:151-186 - Env config parsing
Package Manager
Configure bun install behavior:
Registry
Custom npm registry:
[install]
registry = "https://registry.npmjs.org/"
# With authentication
registry = "https://username:[email protected]/"
[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:
[install.scopes]
"@mycompany" = "https://npm.mycompany.com/"
"@other" = { url = "https://npm.other.com/", token = "xxx" }
Cache
Configure package cache:
[install]
cache = "~/.bun/install/cache" # Custom cache directory
cache = false # Disable cache
Lockfile
Lockfile behavior:
[install]
lockfile = true # Generate/update lockfile (default)
lockfile = false # Disable lockfile
Production
Skip devDependencies:
[install]
production = true # Skip devDependencies
Optional Dependencies
[install]
optional = true # Install optionalDependencies (default)
optional = false # Skip optionalDependencies
Exact Versions
[install]
exact = true # Install exact versions from lockfile
Frozen Lockfile
[install]
frozenLockfile = true # Error if lockfile would change
Dry Run
[install]
dryRun = true # Simulate install without writing files
Development Server
Configure bun --hot:
[dev]
port = 3000
host = "localhost"
Test Runner
Configure bun test:
[test]
# Test file pattern
preload = ["./test-setup.ts"]
Build Configuration
Configure bun build:
[build]
# Loader configuration
[build.loader]
".txt" = "text"
".data" = "json"
".png" = "file"
Loader Configuration
Map file extensions to 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]
# Import replacements
"react" = "preact/compat"
Define
Replace identifiers at build time:
[define]
PROCESS_ENV_NODE_ENV = '"production"'
VERSION = '"1.0.0"'
API_URL = '"https://api.example.com"'
Usage in code:
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 = ["fsevents", "lightningcss"]
Compilation
Enable/disable features:
[compile]
# Native compilation settings
Example Configurations
Minimal Configuration
Development Setup
logLevel = "debug"
preload = ["./dev-setup.ts"]
[env]
file = [".env.development", ".env.local"]
[install]
cache = true
lockfile = true
[dev]
port = 3000
Production Setup
logLevel = "error"
[env]
file = ".env.production"
[install]
production = true
frozenLockfile = true
cache = "~/.bun/cache"
[define]
PROCESS_ENV_NODE_ENV = '"production"'
Monorepo Configuration
logLevel = "info"
[install]
workspace = true
hoistPattern = ["*"]
[install.scopes]
"@myorg" = "https://npm.myorg.com/"
[loader]
".tsx" = "tsx"
".graphql" = "text"
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:
# 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:
[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:
bun run app.ts
# Error: Invalid Bunfig: Unknown key "invalidKey"
Debugging Configuration
Print Loaded Config
BUN_DEBUG_QUIET_LOGS=0 bun run app.ts 2>&1 | grep -i bunfig
Check Config Location
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:
.
├── bunfig.toml # Base config
├── bunfig.dev.toml # Development overrides
├── bunfig.prod.toml # Production overrides
└── package.json
{
"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
- Check file location: Must be in project root or home directory
- Check file name: Must be exactly
bunfig.toml
- Check TOML syntax: Use TOML validator
- 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:
[install]
registry = "https://npm.company.com/"
# Or with token
[install.registry]
url = "https://npm.company.com/"
token = "npm_xxxxxxxxxxxx"