|$ curl https://forge-ai.dev/api/markdown?path=docs/npm/bun
$cat docs/bun-as-package-manager.md
updated Today·22-30 min read·published

Bun as Package Manager

BunRuntimePackage ManagerIntermediate🎯Free Tools
Introduction

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
1curl -fsSL https://bun.sh/install | bash
2# or: npm install -g bun (bootstrap; then use bun itself)
3bun --version
4
5# Upgrade
6bun upgrade
RequirementDetail
OSmacOS, Linux, Windows (WSL/native support improving)
CIInstall Bun action or bake version into image
Node interopOptional — 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
1bun install
2bun install --frozen-lockfile # CI: do not update lockfile
3bun install --production # omit devDependencies
4bun add express
5bun add -d typescript vitest
6bun remove lodash
7bun update
8bun 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.

FileFormatReviewabilityAction
bun.lockTextGood PR diffsPreferred; commit
bun.lockbBinaryOpaqueCommit if still generated; migrate when possible
lockfile-hygiene.sh
Bash
1# After adopting Bun
2rm -f package-lock.json yarn.lock pnpm-lock.yaml
3bun install
4git 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
1bunx cowsay "fast installs"
2bunx create-next-app@latest
3bunx eslint . --max-warnings=0
4# Equivalent:
5bun 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
1bun run dev
2bun run build
3bun test # Bun's built-in test runner
4bun ./src/index.ts # run TypeScript directly (runtime mode)
5bun --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
1bun install
2bun run --filter @acme/web build
3bun 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.

AreaUsually fineWatch carefully
Pure JS librariesYes
TypeScript toolingOftenComplex tsconfig path setups
Native addons (N-API)Many workEdge native modules, older bindings
postinstall scriptsConfigurableSecurity — trustedDependencies
Next.js / Vite appsCommon as installerProd 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 whenPrefer npm/pnpm/Yarn when
Greenfield apps valuing install speedConservative enterprise Node stdlib parity
You want runtime + tests + bundler unifiedYou only need a package manager (pnpm)
Scripts/CLIs where startup time mattersHard requirement for Corepack-only toolchain
Team can pin Bun versions in CI imagesContributors 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
8- run: npm ci && npm test
9 if: ${{ false }}
Migrating to Bun
migrate.sh
Bash
1# From npm
2rm package-lock.json
3bun install
4bun run test
5
6# From pnpm
7rm pnpm-lock.yaml
8bun install
9# re-check workspace filters — syntax differs
10
11# Enforce Bun for installs
12# package.json:
13# "scripts": { "preinstall": "npx only-allow bun" }
npmBun
npm installbun install
npm cibun install --frozen-lockfile
npxbunx
npm runbun run
overridesoverrides (package.json; verify current Bun support)
How / Why / Requirements
QuestionAnswer
Why?Speed of install + optional unified runtime/test/bundle
How?Install Bun → bun install → commit bun.lock → pin version in CI
RequirementsBun binary on PATH; team agreement on runtime vs Node; trustedDependencies for natives
Adoption Checklist
  • Pin exact Bun version in CI
  • Commit text lockfile when available
  • Delete competing lockfiles
  • List native packages in trustedDependencies
  • Run full test matrix on intended production runtime
  • Document hybrid Node/Bun decisions in README
  • Add only-allow if Bun is mandatory for installs

Community

Get help on Slack, Discord or VIP

Stuck on a guide? Join the community and ask.