Documentation Index
Fetch the complete documentation index at: https://mintlify.com/zhcndoc/bun/llms.txt
Use this file to discover all available pages before exploring further.
Workspaces allow you to manage multiple packages within a single repository (monorepo).
Configuration
Define workspaces in the root package.json:
{
"workspaces": ["packages/*"]
}
This tells Bun that every directory in packages/ is a workspace.
Glob patterns
Use glob patterns to match workspace directories:
{
"workspaces": [
"packages/*",
"apps/*",
"tools/*"
]
}
Negative patterns
Exclude specific directories:
{
"workspaces": [
"packages/*",
"!packages/ignored"
]
}
Structure
Typical monorepo structure:
my-monorepo/
├── package.json # Root package.json with workspaces
├── bun.lockb # Shared lockfile
├── node_modules/ # Shared dependencies
├── packages/
│ ├── app/
│ │ ├── package.json
│ │ └── src/
│ ├── shared/
│ │ ├── package.json
│ │ └── src/
│ └── utils/
│ ├── package.json
│ └── src/
└── apps/
└── web/
├── package.json
└── src/
Installing
Install all workspaces
From the root:
Installs dependencies for all workspace packages and links inter-workspace dependencies.
Install in specific workspace
cd packages/app
bun install
Or from root:
bun install --cwd packages/app
Inter-workspace dependencies
Reference by name
Workspace packages can depend on each other:
// packages/app/package.json
{
"name": "@myorg/app",
"dependencies": {
"@myorg/shared": "workspace:*"
}
}
The workspace: protocol tells Bun to link to the local workspace package.
Version protocols
{
"dependencies": {
"@myorg/shared": "workspace:*", // Any version
"@myorg/utils": "workspace:^1.0.0", // Semver range
"@myorg/types": "workspace:~", // Current version
}
}
Automatic linking
When you run bun install, workspace dependencies are automatically linked:
$ bun install
bun install v1.0.0
+ @myorg/shared (workspace)
+ @myorg/utils (workspace)
134 packages installed [1.83s]
Adding dependencies
Add to specific workspace
From workspace directory:
cd packages/app
bun add react
From root:
bun add react --cwd packages/app
Add workspace dependency
cd packages/app
bun add @myorg/shared@workspace:*
Or edit package.json manually:
{
"dependencies": {
"@myorg/shared": "workspace:*"
}
}
Then run bun install.
Add to root workspace
Add shared development dependencies to root:
# From root
bun add -D typescript @types/node
Root package.json:
{
"workspaces": ["packages/*"],
"devDependencies": {
"typescript": "^5.0.0",
"@types/node": "^20.0.0"
}
}
Running scripts
Run in specific workspace
cd packages/app
bun run build
Or from root:
bun --cwd packages/app run build
Run in all workspaces
Run a script across all workspaces:
# Using a script runner like Turborepo
turbo run build
# Or manually
for dir in packages/*; do
(cd "$dir" && bun run build)
done
Filtering workspaces
Run commands in specific workspaces:
# Install only for specific workspace
bun install --filter "@myorg/app"
# Update packages in specific workspace
bun update --filter "@myorg/app"
# Check outdated in specific workspace
bun outdated --filter "@myorg/app"
With patterns:
# All packages with @myorg scope
bun install --filter "@myorg/*"
# Multiple filters
bun install --filter "@myorg/app" --filter "@myorg/shared"
Workspace resolution
Bun resolves workspace dependencies in this order:
- Exact workspace match
- Version range match within workspaces
- External registry
Resolution examples
Given workspaces:
@myorg/utils version 1.0.0
@myorg/helpers version 2.0.0
{
"dependencies": {
"@myorg/utils": "workspace:*", // → @myorg/utils@1.0.0 (workspace)
"@myorg/utils": "workspace:^1.0.0", // → @myorg/utils@1.0.0 (workspace)
"@myorg/utils": "workspace:^2.0.0", // → @myorg/utils@latest (registry)
"@myorg/utils": "*" // → @myorg/utils@1.0.0 (workspace)
}
}
Publishing workspaces
Publish individual workspace
cd packages/utils
bun publish
Workspace protocol in published packages
When publishing, workspace: dependencies are converted:
Before publishing:
{
"dependencies": {
"@myorg/shared": "workspace:^1.0.0"
}
}
Published version:
{
"dependencies": {
"@myorg/shared": "^1.0.0"
}
}
Pre-publish validation
Ensure workspace dependencies exist in registry before publishing:
# Publish shared packages first
cd packages/shared && bun publish
# Then publish packages that depend on them
cd ../app && bun publish
Common patterns
Shared TypeScript config
Root tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"strict": true
}
}
Workspace tsconfig.json:
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
}
}
Install shared tools at root:
{
"devDependencies": {
"typescript": "^5.0.0",
"@biomejs/biome": "^1.0.0",
"vitest": "^1.0.0"
},
"scripts": {
"test": "vitest",
"lint": "biome check .",
"format": "biome format --write ."
}
}
Private packages
Mark workspace packages as private if not publishing:
{
"name": "@myorg/app",
"private": true
}
Benefits
Code sharing
Share code between packages without publishing:
// packages/shared/src/utils.ts
export function formatDate(date: Date) {
return date.toISOString();
}
// packages/app/src/index.ts
import { formatDate } from "@myorg/shared";
Dependency deduplication
Shared dependencies are hoisted to root node_modules:
node_modules/
├── react/ # Shared by multiple workspaces
├── react-dom/ # Shared by multiple workspaces
└── typescript/ # Shared dev dependency
Atomic changes
Make changes across multiple packages in a single commit:
# Update API in shared package
cd packages/shared
# Update code
# Update consumers
cd ../app
# Update code to match new API
# Commit everything together
git add .
git commit -m "Update API"
Troubleshooting
Workspace not found
If Bun can’t find a workspace:
- Check workspace glob patterns in root
package.json
- Ensure workspace has a
package.json with name field
- Run
bun install from root
Dependencies not linking
If workspace dependencies aren’t linking:
# Clear cache and reinstall
rm -rf node_modules bun.lockb
bun install
Version mismatches
Ensure workspace versions match dependency ranges:
// packages/shared/package.json
{
"version": "1.0.0"
}
// packages/app/package.json
{
"dependencies": {
"@myorg/shared": "workspace:^1.0.0" // Matches!
}
}
Migration from other package managers
From npm/Yarn workspaces
Bun workspaces are compatible:
// Works with Bun
{
"workspaces": ["packages/*"]
}
Replace workspace: protocols:
// Before (Yarn)
{"dependencies": {"pkg": "workspace:*"}}
// After (Bun, same!)
{"dependencies": {"pkg": "workspace:*"}}
From pnpm
Convert pnpm-workspace.yaml:
# pnpm-workspace.yaml
packages:
- 'packages/*'
To package.json:
{
"workspaces": ["packages/*"]
}
Examples
Full stack monorepo
{
"name": "my-app",
"workspaces": [
"packages/*",
"apps/*"
],
"devDependencies": {
"typescript": "^5.0.0"
}
}
Structure:
├── apps/
│ ├── web/ # React frontend
│ └── api/ # Backend API
├── packages/
│ ├── ui/ # Shared UI components
│ ├── utils/ # Shared utilities
│ └── types/ # Shared TypeScript types
└── package.json
Library monorepo
{
"name": "@mylib/monorepo",
"workspaces": ["packages/*"],
"private": true
}
Structure:
├── packages/
│ ├── core/ # @mylib/core
│ ├── react/ # @mylib/react
│ ├── vue/ # @mylib/vue
│ └── utils/ # @mylib/utils
└── package.json