From fieldguides
Bun-first development: prefer native APIs over npm packages, audit for migration opportunities, eliminate unnecessary dependencies. Use when evaluating packages, starting projects, or migrating from Node.js.
npx claudepluginhub outfitter-dev/outfitter --plugin fieldguidesThis skill uses the workspace's default tool permissions.
Bun-first philosophy: prefer native APIs over external packages.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
Bun-first philosophy: prefer native APIs over external packages.
<when_to_use>
Boundary: This skill covers when to use Bun and what it replaces. For detailed Bun API patterns and implementation examples, load the bun-fieldguide skill instead.
</when_to_use>
Use Bun directly instead of Node.js tooling:
| Instead of | Use |
|---|---|
node file.ts or ts-node file.ts | bun file.ts |
jest or vitest | bun test |
webpack or esbuild (CLI) | bun build |
npm install / yarn / pnpm | bun install |
npm run script | bun run script |
npx package | bunx package |
nodemon | bun --watch |
node --env-file=.env | bun (auto-loads .env) |
Before adding a dependency, follow this hierarchy:
Need functionality
│
├─► Does Bun have a built-in API?
│ └─► YES → Use it directly
│
├─► Can you wrap a Bun primitive?
│ └─► YES → Thin abstraction over Bun API
│
└─► External package (last resort)
└─► Document why Bun couldn't do it
Bun. or bun: in docsDocument exceptions with a code comment:
// Using date-fns: Bun has no date manipulation APIs
import { format, addDays } from "date-fns";
Bun APIs organized by category. Check these before reaching for npm.
| Bun API | Replaces |
|---|---|
bun:test | jest, vitest, mocha |
expect() | chai, expect.js |
import { describe, test, expect } from "bun:test";
| Bun API | Replaces |
|---|---|
bun:sqlite | better-sqlite3, sql.js |
Bun.sql | pg, postgres.js, mysql2 |
Bun.redis | ioredis, redis |
Bun.s3 | @aws-sdk/client-s3 |
import { Database } from "bun:sqlite";
const client = Bun.redis();
const bucket = Bun.s3("my-bucket");
| Bun API | Replaces |
|---|---|
Bun.listen() | net.createServer |
Bun.connect() | net.connect |
Bun.udpSocket() | dgram.createSocket |
Bun.dns | dns.lookup |
| Bun API | Replaces |
|---|---|
Bun.serve() | express, fastify, http |
Bun.fetch() | node-fetch, axios, got |
Bun.serve({ port: 3000, fetch: (req) => new Response("ok") });
| Bun API | Replaces |
|---|---|
Bun.$ | execa, shelljs, zx |
Bun.spawn() | child_process.spawn |
Bun.spawnSync() | child_process.spawnSync |
import { $ } from "bun";
await $`ls -la`;
| Bun API | Replaces |
|---|---|
Bun.file() | fs.readFile, fs-extra |
Bun.write() | fs.writeFile |
file.exists() | fs.existsSync |
file.stream() | fs.createReadStream |
const content = await Bun.file("./data.json").json();
await Bun.write("./out.txt", content);
| Bun API | Replaces |
|---|---|
Bun.password.hash() | bcrypt, argon2 |
Bun.hash() | xxhash, murmur, crc32 |
Bun.CryptoHasher | crypto.createHash |
Bun.Glob | glob, fast-glob, minimatch |
Bun.semver | semver |
Bun.YAML.parse() | js-yaml, yaml |
Bun.TOML.parse() | toml |
Bun.gzipSync() | zlib, pako |
Bun.zstdCompressSync() | zstd-codec |
Bun.Archive | tar, archiver |
Bun.sleep() | delay, timers-promises |
Bun.deepEquals() | lodash.isEqual, deep-equal |
Bun.escapeHTML() | escape-html |
Bun.stringWidth() | string-width |
Bun.Cookie | cookie, tough-cookie |
Bun.randomUUIDv7() | uuid |
Bun.which() | which |
const hash = await Bun.password.hash(password, { algorithm: "argon2id" });
const glob = new Bun.Glob("**/*.ts");
const valid = Bun.semver.satisfies("1.2.3", ">=1.0.0");
| Bun API | Replaces |
|---|---|
Bun.build() | esbuild, rollup, webpack |
bun build --compile | pkg, nexe |
bun build ./index.ts --outfile dist/bundle.js --minify
Bun.serve() supports HTML imports with automatic bundling. No Vite/Webpack needed.
// server.ts
import index from "./index.html";
Bun.serve({
routes: {
"/": index,
"/api/data": (req) => Response.json({ ok: true }),
},
development: { hmr: true, console: true },
});
HTML files can import .tsx/.jsx/.ts directly:
<!-- index.html -->
<html>
<body>
<div id="root"></div>
<script type="module" src="./app.tsx"></script>
</body>
</html>
Run with hot reloading:
bun --hot server.ts
Scan a codebase for Bun migration opportunities using the bundled audit script.
# From the skill directory (or adjust path as needed)
bun ./scripts/audit-bun-usage.ts [path]
# JSON output (default) - pipe to jq, use in CI
bun ./scripts/audit-bun-usage.ts ./my-project
# Markdown output - human readable
bun ./scripts/audit-bun-usage.ts ./my-project --format=md
The audit identifies:
// Before: Express
import express from "express";
const app = express();
app.get("/", (req, res) => res.send("ok"));
app.listen(3000);
// After: Bun.serve + Hono
import { Hono } from "hono";
const app = new Hono().get("/", (c) => c.text("ok"));
Bun.serve({ port: 3000, fetch: app.fetch });
// Before: Jest
import { describe, it, expect } from "@jest/globals";
// After: bun:test (drop-in compatible)
import { describe, it, expect } from "bun:test";
// Before
import Database from "better-sqlite3";
// After (same API)
import { Database } from "bun:sqlite";
// Before
import bcrypt from "bcrypt";
const hash = await bcrypt.hash(password, 10);
// After
const hash = await Bun.password.hash(password, { algorithm: "argon2id" });
// Before
import { execa } from "execa";
const { stdout } = await execa("ls", ["-la"]);
// After
import { $ } from "bun";
const result = await $`ls -la`;
console.log(result.text());
ALWAYS:
Bun.$ for shell commandsNEVER:
DOCUMENT:
Related skills:
bun-fieldguide — Detailed Bun API patterns, implementation examples, testing strategiestypescript-fieldguide — TypeScript patterns for Bun projects, strict typing, Zod validation