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.
Promotes Bun-first development by auditing dependencies and recommending native APIs over external packages.
npx claudepluginhub outfitter-dev/outfitterThis skill inherits all available tools. When active, it can use any tool Claude has access to.
replacements.jsonscripts/audit-bun-usage.tsBun-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());
<rules>
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 validationActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.