skills/bun-pm-workspaces/SKILL.md
Develop complex monorepos with multiple independent packages
npx skillsauth add jarle/bun-skills Bun WorkspacesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Develop complex monorepos with multiple independent packages
Bun supports workspaces in package.json. Workspaces make it easy to develop complex software as a monorepo consisting of several independent packages.
It's common for a monorepo to have the following structure:
<root>
├── README.md
├── bun.lock
├── package.json
├── tsconfig.json
└── packages
├── pkg-a
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── pkg-b
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
└── pkg-c
├── index.ts
├── package.json
└── tsconfig.json
In the root package.json, the "workspaces" key is used to indicate which subdirectories should be considered packages/workspaces within the monorepo. It's conventional to place all the workspace in a directory called packages.
{
"name": "my-project",
"version": "1.0.0",
"workspaces": ["packages/*"],
"devDependencies": {
"example-package-in-monorepo": "workspace:*"
}
}
<Note>
**Glob support** — Bun supports full glob syntax in `"workspaces"`, including negative patterns (e.g.
`!**/excluded/**`). See [here](/runtime/glob#supported-glob-patterns) for a comprehensive list of supported syntax.
</Note>
{
"name": "my-project",
"version": "1.0.0",
"workspaces": ["packages/**", "!packages/**/test/**", "!packages/**/template/**"]
}
Each workspace has it's own package.json. When referencing other packages in the monorepo, semver or workspace protocols (e.g. workspace:*) can be used as the version field in your package.json.
{
"name": "pkg-a",
"version": "1.0.0",
"dependencies": {
"pkg-b": "workspace:*"
}
}
bun install will install dependencies for all workspaces in the monorepo, de-duplicating packages if possible. If you only want to install dependencies for specific workspaces, you can use the --filter flag.
# Install dependencies for all workspaces starting with `pkg-` except for `pkg-c`
bun install --filter "pkg-*" --filter "!pkg-c"
# Paths can also be used. This is equivalent to the command above.
bun install --filter "./packages/pkg-*" --filter "!pkg-c" # or --filter "!./packages/pkg-c"
When publishing, workspace: versions are replaced by the package's package.json version,
"workspace:*" -> "1.0.1"
"workspace:^" -> "^1.0.1"
"workspace:~" -> "~1.0.1"
Setting a specific version takes precedence over the package's package.json version,
"workspace:1.0.2" -> "1.0.2" // Even if current version is 1.0.1
Workspaces have a couple major benefits.
package.json. If package b depends on a, bun install will install your local packages/a directory into node_modules instead of downloading it from the npm registry.a and b share a common dependency, it will be hoisted to the root node_modules directory. This reduces redundant disk usage and minimizes "dependency hell" issues associated with having multiple versions of a package installed simultaneously.--filter flag to easily run package.json scripts in multiple packages in your workspace, , or --workspaces to run scripts across all workspaces.When many packages need the same dependency versions, catalogs let you define
those versions once in the root package.json and reference them from your
workspaces using the catalog: protocol. Updating the catalog automatically
updates every package that references it. See
Catalogs for details.
npm installyarn install (v1)pnpm installdevelopment
Using TypeScript with Bun, including type definitions and compiler options
development
Learn how to write tests using Bun's Jest-compatible API with support for async tests, timeouts, and various test modifiers
testing
Learn how to use snapshot testing in Bun to save and compare output between test runs
testing
Learn about Bun test's runtime integration, environment variables, timeouts, and error handling