Bun is an all-in-one JavaScript toolkit: a fast runtime (Zig + JavaScriptCore), bundler, test runner, and package manager. As a package manager it speaks the npm registry protocol, respects package.json, and produces a Bun lockfile while installing dramatically faster than npm in most benchmarks.
You can use Bun only as an installer (still run apps with Node), or go all-in on bun as runtime + installer. Decide deliberately — mixing without docs confuses CI. Manager comparison: npm vs Yarn vs pnpm vs Bun.
📝
note
Bun is not delivered by Corepack. Install from https://bun.sh or your OS package manager and pin the version in CI images.
Installing Bun
install-bun.sh
Bash
1
curl -fsSL https://bun.sh/install | bash
2
# or: npm install -g bun (bootstrap; then use bun itself)
3
bun --version
4
5
# Upgrade
6
bun upgrade
Requirement
Detail
OS
macOS, Linux, Windows (WSL/native support improving)
CI
Install Bun action or bake version into image
Node interop
Optional — many teams keep Node for production runtime
bun install
bun install resolves dependencies, writes the lockfile, and populates node_modules with an npm-compatible hoisted layout (optimized). It is usually the fastest cold/warm installer in the ecosystem.
install.sh
Bash
1
bun install
2
bun install --frozen-lockfile # CI: do not update lockfile
3
bun install --production # omit devDependencies
4
bun add express
5
bun add -d typescript vitest
6
bun remove lodash
7
bun update
8
bun outdated
ℹ
info
Prefer bun install --frozen-lockfile in CI the same way you use npm ci or pnpm i --frozen-lockfile.
bun.lock and bun.lockb
Older Bun versions wrote a binary bun.lockb. Newer Bun prefers a text bun.lock for readable diffs and better GitHub review. Commit whichever your Bun version generates — do not mix with package-lock.json.
File
Format
Reviewability
Action
bun.lock
Text
Good PR diffs
Preferred; commit
bun.lockb
Binary
Opaque
Commit if still generated; migrate when possible
lockfile-hygiene.sh
Bash
1
# After adopting Bun
2
rm -f package-lock.json yarn.lock pnpm-lock.yaml
3
bun install
4
git add bun.lock package.json
5
# Ensure only one lockfile remains
⚠
warning
Binary lockfiles make conflict resolution painful. Prefer text bun.lock on current Bun releases and teach the team not to regenerate with older Bun accidentally.
bunx
bunx is Bun's npx/dlx analogue — run a package binary without a permanent dependency.
bunx.sh
Bash
1
bunx cowsay "fast installs"
2
bunx create-next-app@latest
3
bunx eslint . --max-warnings=0
4
# Equivalent:
5
bun x eslint .
bun run
bun run executes package.json scripts. Unlike npm, Bun can omit run for known scripts and starts faster. Lifecycle scripts still matter for native addons.
scripts.sh
Bash
1
bun run dev
2
bun run build
3
bun test # Bun's built-in test runner
4
bun ./src/index.ts # run TypeScript directly (runtime mode)
5
bun --bun run vite # force script to use Bun instead of Node
package.json scripts
JSON
1
{
2
"scripts": {
3
"dev": "next dev",
4
"build": "next build",
5
"test": "bun test",
6
"start": "bun ./server.ts"
7
}
8
}
Workspaces
Bun supports npm-style workspaces via the workspaces field. Filtering is available for running scripts in subsets of the monorepo.
package.json
JSON
1
{
2
"name": "acme",
3
"private": true,
4
"workspaces": ["apps/*", "packages/*"]
5
}
workspace.sh
Bash
1
bun install
2
bun run --filter @acme/web build
3
bun add zod --filter @acme/web
📝
note
For very large monorepos with catalogs and strict isolation, pnpm remains more mature. Bun shines when speed and a unified toolchain matter more than advanced workspace policy engines.
Compatibility with npm Packages
Most packages on the npm registry install and run under Bun. Gaps appear around Node-specific native addons, obscure processAPIs, and packages that shell out expecting Node's exact behavior.
Area
Usually fine
Watch carefully
Pure JS libraries
Yes
—
TypeScript tooling
Often
Complex tsconfig path setups
Native addons (N-API)
Many work
Edge native modules, older bindings
postinstall scripts
Configurable
Security — trustedDependencies
Next.js / Vite apps
Common as installer
Prod runtime still often Node
trustedDependencies
JSON
1
{
2
"trustedDependencies": [
3
"esbuild",
4
"sharp"
5
]
6
}
⚠
warning
Bun may not run lifecycle scripts for packages unless they are listed in trustedDependencies. Missing native builds often trace back to this — not to "Bun cannot install."
When Bun Is Right
Choose Bun when
Prefer npm/pnpm/Yarn when
Greenfield apps valuing install speed
Conservative enterprise Node stdlib parity
You want runtime + tests + bundler unified
You only need a package manager (pnpm)
Scripts/CLIs where startup time matters
Hard requirement for Corepack-only toolchain
Team can pin Bun versions in CI images
Contributors must use stock Node+npm only
✓
best practice
A popular hybrid: bun install in development for speed, Node in production until Bun runtime support is proven for your stack. Document which binary runs which scripts.
Known Caveats
Not managed by Corepack — version pinning is on you.
Lockfile format changed over time (binary → text); align Bun versions across the team.
Some Node APIs remain incomplete or subtly different — run integration tests on the production runtime.
Lifecycle scripts / trustedDependencies differ from npm defaults.
Ecosystem docs and Stack Overflow answers still assume npm/yarn — translate carefully.
Monorepo policy tools (catalogs, constraints) are richer on pnpm/Yarn today.
.github/workflows/ci.yml
YAML
1
- uses: oven-sh/setup-bun@v2
2
with:
3
bun-version: 1.2.5
4
- run: bun install --frozen-lockfile
5
- run: bun run test
6
- run: bun run build
7
# Optional: also test under Node if production uses Node