Claude
Skills
Sign in
Back

use-bun

Included with Lifetime
$97 forever

Answer questions about Bun — the all-in-one JavaScript/TypeScript toolkit — and write code using its runtime, package manager, test runner, and bundler. Use when developers call Bun-native APIs (`Bun.serve`, `Bun.file`, `Bun.write`, `Bun.spawn`, `Bun.$` shell, `Bun.SQL`, `Bun.RedisClient`, `Bun.build`, `HTMLRewriter`); import `bun:*` modules (`bun:test`, `bun:sqlite`, `bun:ffi`, `bun:jsc`); run CLI commands (`bun install`/`add`/`run`/`test`/`build`, `bunx`, `bun create`, `bun --compile`); configure `bunfig.toml`, `bun.lock`, workspaces, catalogs, overrides, isolated installs, trustedDependencies, or lifecycle scripts; bundle with loaders, plugins, or macros; write `bun:test` tests (`mock`, `spyOn`, `mock.module`, snapshots, coverage); or need Node.js compatibility, JSC vs V8 differences, or migration from npm/yarn/pnpm/jest/vitest.

Backend & APIsscripts

What this skill does


## Prerequisites

Verify the `ask` CLI is available (`which ask`). It is the primary tool for reading the exact Bun version installed in the project — it fetches the version-tagged source from GitHub once and caches it at `~/.ask/`. If `ask` is not installed, fall back to the local `bun` binary's built-in help and the official docs at https://bun.com/docs (which always tracks the latest release).

Before writing Bun-specific code, detect the project's Bun version. The skill bundles a helper that resolves it in the correct priority order (`.bun-version` → `package.json.packageManager` → `engines.bun` → global `bun`):

```bash
# Resolve project pin; GitHub release tags use the `bun-vX.Y.Z` form
BUN_REF="bun-v$(${CLAUDE_SKILL_DIR}/scripts/resolve-bun-version.sh)" || exit 1
echo "$BUN_REF"   # e.g. bun-v1.3.14

# Lockfile format — Bun migrated from binary bun.lockb to text bun.lock at 1.2.0
ls bun.lock bun.lockb 2>/dev/null
```

See [`references/versions.md`](references/versions.md) for the resolution rules and the underlying script (`scripts/resolve-bun-version.sh`).

If Bun is not installed, install it once:

```bash
# Recommended — official installer
curl -fsSL https://bun.sh/install | bash

# Or via npm / brew / proto / asdf — see https://bun.com/docs/installation
```

## Critical: Do Not Trust Internal Knowledge

Bun ships fast — APIs land, change shape, or move modules between minor releases. Common pitfalls from outdated training data:

- **`Bun.serve` routes (`routes: { "/users/:id": handler }`)** — requires **Bun 1.2.3+**. Before that you wrote `fetch(req)` with manual URL parsing. Do not suggest `routes` on older versions.
- **`bun.lock` (text JSONC)** vs **`bun.lockb` (binary)** — Bun **1.2.0+** writes `bun.lock` by default (the text format was introduced as opt-in earlier and became the default at 1.2). Existing `bun.lockb` files migrate via `bun install --save-text-lockfile --frozen-lockfile --lockfile-only`. If you see both, the text one wins.
- **Catalogs (`catalog:` / `catalogs:` in `package.json` / `bunfig.toml`)** — added in **Bun 1.2+**. Not available earlier.
- **Isolated installs (`linker = "isolated"`)** — added in **Bun 1.2.x**. Earlier versions only support `hoisted`.
- **`bun:sql` / `Bun.SQL`** — Postgres client landed in **Bun 1.2+**; native MySQL/SQLite are different surfaces (`bun:sqlite` has always existed).
- **`Bun.RedisClient` / `Bun.redis`** — Valkey/Redis client is recent (**Bun 1.2.x**). Older code uses third-party libs.
- **`bun build --compile`** — single-file executables stabilised in **1.1+**; flags like `--bytecode`, `--target=bun-linux-x64-baseline`, and Windows cross-compile are newer.
- **`mock.module()`** — module mocking in `bun:test`. Stable across all current Bun releases; very old (early 1.0.x) versions only had `mock()` for function-level mocks. If you need to support a specific pre-1.1 version, verify the API against that release's docs.
- **`Bun.$` (shell)** — promoted from experimental in **Bun 1.0.24+**. API stabilised since.
- **`trustedDependencies` in `package.json`** — Bun does **not** run installed dependencies' lifecycle scripts by default for security; you must allowlist via this field. Different default than npm/yarn.

When working with Bun:

1. Resolve the installed version against the project via `${CLAUDE_SKILL_DIR}/scripts/resolve-bun-version.sh` (which checks `.bun-version`, `package.json.packageManager`, `engines.bun`, then global `bun --version` in priority order).
2. Verify every API name, method signature, and CLI flag against the version-tagged source via `ask` before generating code. **Do not invent flag names** — Bun's CLI has many short forms and aliases, but only the documented ones are stable.
3. Cross-reference the upstream docs **at the matching version tag** ([`references/versions.md`](references/versions.md) for the `ask` pin recipe) — not `main`, which tracks unreleased changes.
4. Use `bun --print '<expr>'` or a quick REPL (`bun repl`) to confirm behaviour before committing complex API uses.
5. Surface meaningful trade-offs to the user instead of silently picking a side (e.g. `Bun.serve` static routes vs `fetch` handler; `bun:sqlite` vs `Bun.SQL`; `bun test` vs `vitest` for projects that already use Vitest).

If documentation cannot be found locally or remotely to back an answer, say so explicitly.

## Finding Documentation

Bun's source and docs live in one repo: `github:oven-sh/bun`. Use `ask` with the matching tag:

```bash
# Resolve project pin (see Prerequisites above) — GitHub tags use `bun-v` prefix
BUN_REF="bun-v$(${CLAUDE_SKILL_DIR}/scripts/resolve-bun-version.sh)"

# Source tree (single line — pass to rg/fd/cat)
ask src "github:oven-sh/bun@${BUN_REF}"

# Doc candidates (one per line; the docs/ folder will be first)
ask docs "github:oven-sh/bun@${BUN_REF}"

# Convenience
BUN_SRC=$(ask src "github:oven-sh/bun@${BUN_REF}")
ls "${BUN_SRC}/docs"                                   # MDX docs by topic
rg "Bun\.serve" "${BUN_SRC}/docs/runtime/http/server.mdx"
rg "fn serve" "${BUN_SRC}/src/bun.js"                  # implementation
```

When the version is unknown or the user is reading reference material:

```bash
ask docs github:oven-sh/bun@main                       # latest unreleased
ask src github:oven-sh/bun@main
```

See [`references/versions.md`](references/versions.md) for the version pinning recipe and known-stable tag list.

## Topic Map

Load the focused reference for the area you're touching — do not read all of them upfront.

| Topic | Reference | When |
|-------|-----------|------|
| Runtime APIs (`Bun.*`, `bun:*` modules) | [`references/runtime-apis.md`](references/runtime-apis.md) | Writing server code, file I/O, child processes, SQL/SQLite/Redis, FFI, shell |
| Package manager (`bun install`, workspaces, catalogs) | [`references/package-manager.md`](references/package-manager.md) | Setting up deps, monorepos, `bunfig.toml` install settings, lockfile, registries |
| Test runner (`bun:test`) | [`references/test-runner.md`](references/test-runner.md) | Writing tests, mocks, snapshots, coverage, migrating from Jest/Vitest |
| Bundler (`Bun.build`, `bun build`) | [`references/bundler.md`](references/bundler.md) | Bundling, executables (`--compile`), plugins, macros, fullstack dev server |
| Node.js compatibility | [`references/node-compat.md`](references/node-compat.md) | Migrating Node apps, checking `node:*` module support, JSC vs V8 differences |
| Version pinning recipe | [`references/versions.md`](references/versions.md) | `ask` spec to use, known-stable Bun versions, lockfile format history |

## Common Decision Points

- **Server**: prefer `Bun.serve` over `node:http` — built-in routing (`routes:` on 1.2.3+), WebSockets, TLS, hot reload via `--hot`.
- **File I/O**: prefer `Bun.file()` / `Bun.write()` over `node:fs/promises` — lazy reads, faster, returns `Blob`-compatible objects.
- **Spawning processes**: prefer `Bun.spawn()` / `Bun.$` over `node:child_process` — better defaults, streaming stdio, async iterators.
- **SQLite**: use `bun:sqlite` — synchronous, built-in, no compile step. For Postgres use `Bun.SQL`.
- **Shell scripts**: prefer `Bun.$\`cmd\`` over `child_process.exec` — safe interpolation, async iteration, JS strings as commands.
- **Package install**: `bun install` is the default; falls back gracefully on `npm`/`yarn` lockfiles but writes `bun.lock` after the first run. Warn the user if they share a repo with other PMs.
- **Tests**: `bun test` is Jest-compatible and runs `*.test.{ts,tsx,js,jsx,mjs,cjs}` by default — no config required. Migrate from `vitest` only if speed is a real bottleneck; APIs are close but not identical.
- **Bundling for browser**: `Bun.build({ target: "browser" })` is fast and adequate; for production web bundles with code splitting and asset pipelines, dedicated tools (Vite/Webpack) may still be more featureful — check the user's actual needs before recommending.
- **Bundling for CLI distribution**: `bun build --co

Related in Backend & APIs