Bun Package Manager
Bun as a package manager: bun install, bun add, bun remove, the binary lockfile (bun.lockb), workspace support, overrides, patching, publishing packages, global cache, and comparison to npm, pnpm, and yarn.
You are an expert in using Bun as a JavaScript/TypeScript package manager, covering installation workflows, lockfile management, workspace configuration, and migration from other package managers. ## Key Points - **Using `--force` in CI**: The `--force` flag bypasses the cache and re-downloads everything. Use `--frozen-lockfile` in CI instead to ensure reproducible builds. - **Running `bun install` without committing the lockfile**: Every team member and CI pipeline should use the same lockfile. Committing `bun.lockb` is not optional. - **Using `bunx npm` for everything npm does**: Bun handles install, add, remove, and update natively. Only fall back to `bunx npm` for commands Bun does not implement (like `publish` and `audit`). - **Not using `--frozen-lockfile` in production/CI**: Without this flag, Bun may update the lockfile during install, leading to inconsistent deployments.
skilldb get bun-skills/Bun Package ManagerFull skill: 304 linesBun Package Manager — Fast, Compatible Dependency Management
You are an expert in using Bun as a JavaScript/TypeScript package manager, covering installation workflows, lockfile management, workspace configuration, and migration from other package managers.
Core Concepts
Bun's package manager is built into the runtime binary. It uses a binary lockfile (bun.lockb) instead of a text-based one, a global cache with hardlinks to avoid duplicating packages on disk, and parallel network requests for downloads. These design choices make bun install dramatically faster than npm, yarn, or pnpm -- typically 10-30x for cold installs and near-instant for warm installs.
Bun is compatible with the npm registry and reads package.json the same way other package managers do. You can switch an existing project to Bun without changing your dependencies.
Installing Dependencies
# Install all dependencies from package.json
bun install
# Frozen lockfile (CI -- fails if lockfile would change)
bun install --frozen-lockfile
# Production only (skip devDependencies)
bun install --production
# Dry run (show what would be installed)
bun install --dry-run
# Force re-download everything (ignore cache)
bun install --force
# Verbose output for debugging
bun install --verbose
Adding and Removing Packages
# Add a dependency
bun add express
# Add a specific version
bun add express@4.18.2
# Add a dev dependency
bun add -d vitest
bun add --dev @types/node
# Add a peer dependency
bun add --peer react
# Add an optional dependency
bun add --optional fsevents
# Add from GitHub
bun add github:user/repo
bun add github:user/repo#branch
# Add from a tarball URL
bun add https://example.com/package.tgz
# Add from local path
bun add ./packages/my-lib
# Remove a package
bun remove express
# Update packages
bun update # update all
bun update express # update one package
The Binary Lockfile (bun.lockb)
Bun uses a binary lockfile rather than JSON or YAML. This is a deliberate performance choice -- binary parsing is faster than text parsing, and the file is smaller.
# View the lockfile contents as YARN-format text (for inspection)
bun bun.lockb
# Generate a text-based yarn.lock alongside bun.lockb
# (useful for tools that need a readable lockfile)
bun install --yarn
# The lockfile should always be committed to version control
git add bun.lockb
The lockfile records exact resolved versions, integrity hashes, and the full dependency tree. When bun.lockb exists and matches package.json, bun install skips resolution entirely and installs from the lockfile -- this is what makes repeated installs nearly instant.
Do not add bun.lockb to .gitignore. Reproducible builds require the lockfile to be shared across the team.
Workspaces
Bun supports npm-style workspaces for monorepo setups:
// package.json (root)
{
"name": "my-monorepo",
"workspaces": [
"packages/*",
"apps/*"
]
}
# Install all workspace dependencies at once
bun install
# Run a script in a specific workspace
bun run --cwd packages/shared build
# Add a dependency to a specific workspace
bun add zod --cwd packages/api
# Add a workspace package as a dependency of another
# In packages/api/package.json:
# "dependencies": { "shared": "workspace:*" }
bun install
Workspace protocol specifiers:
{
"dependencies": {
"shared": "workspace:*",
"utils": "workspace:^1.0.0",
"core": "workspace:~2.1.0"
}
}
Bun hoists shared dependencies to the root node_modules by default, similar to npm workspaces. Each workspace package can still have its own node_modules for conflicting versions.
Overrides and Resolutions
Force a specific version of a transitive dependency:
{
"overrides": {
"lodash": "4.17.21",
"webpack>terser": "5.14.0"
}
}
Bun also supports Yarn-style resolutions:
{
"resolutions": {
"lodash": "4.17.21",
"**/minimist": "1.2.8"
}
}
Use overrides to fix security vulnerabilities in transitive dependencies or to force consistent versions across a large dependency tree.
Patching Packages
Apply local patches to node_modules packages that persist across installs:
# Generate a patch file for a package
bun patch express
# This opens the package in node_modules for editing
# Make your changes, then:
bun patch --commit express
# This creates a patches/express@4.18.2.patch file
# and adds a patchedDependencies entry to package.json
// package.json after patching
{
"patchedDependencies": {
"express@4.18.2": "patches/express@4.18.2.patch"
}
}
Commit the patches/ directory to version control. Bun applies patches automatically during bun install.
Publishing Packages
# Login to npm registry
bunx npm login
# Publish a package
bunx npm publish
# Publish with tag
bunx npm publish --tag beta
# Publish scoped package as public
bunx npm publish --access public
Bun uses bunx to delegate to npm's publish command since it does not have its own publish implementation. The package is published to the standard npm registry.
Prepare your package for publishing:
{
"name": "my-library",
"version": "1.0.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"files": ["dist"]
}
Global Cache
Bun maintains a global cache of downloaded packages to avoid re-downloading:
# Default cache location
# macOS/Linux: ~/.bun/install/cache
# Windows: %USERPROFILE%\.bun\install\cache
# Clear the cache
bun pm cache rm
# View cache directory
bun pm cache
When Bun installs a package, it downloads it to the global cache and then hardlinks (or copies on Windows) the files into node_modules. This means multiple projects sharing the same dependency version share disk space.
Running Package Binaries
# Run a package binary (like npx)
bunx cowsay "Hello"
# Run without installing permanently
bunx --bun vitest run
# The --bun flag forces the binary to run with Bun runtime
# instead of Node.js (useful for tools that default to Node)
bunx --bun tsx script.ts
Comparison to npm, pnpm, and Yarn
| Feature | bun | npm | pnpm | yarn |
|---|---|---|---|---|
| Install speed | Fastest | Slowest | Fast | Medium |
| Lockfile format | Binary | JSON | YAML | YAML |
| Disk usage | Hardlinks from cache | Full copies | Content-addressable store | PnP or node_modules |
| Workspaces | Yes | Yes | Yes | Yes |
| Patching | Yes | No (use patch-package) | Yes | Yes |
| Plug'n'Play | No | No | No | Yes |
| Audit | Via bunx npm audit | Built-in | Built-in | Built-in |
Anti-Patterns
- Mixing lockfiles: Do not keep both
bun.lockbandpackage-lock.jsonin the same project. Delete the old lockfile when switching package managers. Having both causes confusion about which is authoritative. - Using
--forcein CI: The--forceflag bypasses the cache and re-downloads everything. Use--frozen-lockfilein CI instead to ensure reproducible builds. - Ignoring workspace hoisting issues: When two workspace packages need different versions of the same dependency, Bun hoists one and nests the other. If this causes issues, use
overridesto force a single version. - Running
bun installwithout committing the lockfile: Every team member and CI pipeline should use the same lockfile. Committingbun.lockbis not optional. - Using
bunx npmfor everything npm does: Bun handles install, add, remove, and update natively. Only fall back tobunx npmfor commands Bun does not implement (likepublishandaudit). - Not using
--frozen-lockfilein production/CI: Without this flag, Bun may update the lockfile during install, leading to inconsistent deployments.
Migration from npm/yarn/pnpm
# Step 1: Remove old lockfile and node_modules
rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml
# Step 2: Install with Bun
bun install
# Step 3: Commit the new lockfile
git add bun.lockb
git commit -m "Switch to bun package manager"
# Step 4: Update CI scripts
# Replace "npm ci" with "bun install --frozen-lockfile"
# Replace "npm run build" with "bun run build"
# Replace "npx" with "bunx"
Verify your scripts still work after switching. Most package.json scripts run identically, but scripts that rely on npm-specific lifecycle hooks (like preinstall running before npm install) may need adjustment since Bun supports preinstall, install, postinstall, prepare, and prepublishOnly but may run them in slightly different order for parallel installs.
Install this skill directly: skilldb add bun-skills
Related Skills
Bun Bundler
Bun's built-in bundler: Bun.build() API, entry points, output formats (esm, cjs, iife), plugins, loaders, tree shaking, code splitting, CSS bundling, HTML entries, and compile-time macros.
Bun Fundamentals
Bun runtime overview: all-in-one JavaScript runtime, bundler, test runner, and package manager. Installation, project initialization, Node.js compatibility, performance characteristics, and guidance on when to choose Bun vs Node.
Bun HTTP Server
Building HTTP servers with Bun: Bun.serve() API, routing patterns, WebSocket support, streaming responses, static file serving, TLS configuration, hot reloading, and integration with frameworks like Hono and Elysia.
Bun Node.js Migration
Migrating from Node.js to Bun: compatibility checklist, node:* module imports, native addon handling, environment variable differences, Docker setup, CI/CD pipeline changes, and common migration pitfalls.
Bun Production Patterns
Production patterns for Bun: Docker deployments, TypeScript configuration, shell scripting with Bun.$, monorepo setup, database access patterns, and deployment to Fly.io and Railway.
Bun Runtime APIs
Bun-native runtime APIs including Bun.serve(), Bun.file(), Bun.write(), Bun.spawn(), Bun.sleep(), Bun.env, FFI for calling native libraries, built-in SQLite, S3 client, glob, and semver utilities.