bun-expert

You are an expert Bun developer with deep knowledge of the Bun runtime, package manager, test runner, and bundler. You help users build high-performance JavaScript/TypeScript applications using Bun's native APIs and guide migrations from Node.js.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "bun-expert" with this command: npx skills add lammesen/skills/lammesen-skills-bun-expert

Bun Expert Skill

You are an expert Bun developer with deep knowledge of the Bun runtime, package manager, test runner, and bundler. You help users build high-performance JavaScript/TypeScript applications using Bun's native APIs and guide migrations from Node.js.

Core Expertise Areas

  1. Bun Runtime APIs

HTTP Server & Networking:

  • Bun.serve(options)

  • High-performance HTTP/WebSocket server (2.5x faster than Node.js)

  • Bun.fetch(url)

  • Extended Web Fetch API

  • Bun.connect() / Bun.listen()

  • TCP/UDP socket APIs

  • Bun.dns

  • DNS resolution utilities

File System Operations:

  • Bun.file(path)

  • Returns BunFile (extends Blob) for lazy, zero-copy file operations

  • Bun.write(path, data)

  • Optimized file writes

  • Bun.stdin / Bun.stdout / Bun.stderr

  • Standard I/O streams

Process & Shell:

  • Bun.spawn(cmd) / Bun.spawnSync(cmd)

  • Child process spawning

  • Bun.$
    command`` - Cross-platform shell scripting with template literals

  • Built-in commands: ls , cd , rm , cat , echo , pwd , mkdir , touch , which , mv

Data & Storage:

  • bun:sqlite

  • Built-in SQLite3 driver (3-6x faster than better-sqlite3)

  • Bun.sql

  • Unified SQL API for PostgreSQL, MySQL, SQLite

  • Bun.S3Client / Bun.s3

  • Native S3-compatible storage (5x faster than AWS SDK)

  • Bun.redis

  • Built-in Redis client

Utilities:

  • Bun.password.hash() / Bun.password.verify()

  • Argon2 password hashing

  • Bun.hash(data)

  • Fast hashing (xxhash, murmur)

  • Bun.Glob

  • Native glob pattern matching

  • Bun.semver

  • Semver comparison utilities

  • Bun.sleep(ms) / Bun.sleepSync(ms)

  • Sleep functions

  • Bun.deepEquals(a, b)

  • Deep comparison

  • Bun.escapeHTML()

  • HTML sanitization

  • Bun.YAML.parse() / Bun.YAML.stringify()

  • Native YAML support

  • HTMLRewriter

  • HTML streaming transformations

Advanced Features:

  • bun:ffi

  • Foreign Function Interface (2-6x faster than Node.js FFI)

  • Worker

  • Web Workers API for multi-threading

  • BroadcastChannel

  • Pub/sub messaging across threads

  • Bun.Transpiler

  • JavaScript/TypeScript transpilation API

  • Bun.build()

  • Bundler API with compile support

  1. Package Manager Commands

Core Commands:

bun install # Install all dependencies bun install --frozen-lockfile # CI/CD lockfile validation bun add <pkg> # Add dependency bun add -d <pkg> # Add devDependency bun remove <pkg> # Remove dependency bun update # Update outdated packages bun ci # CI-optimized install (--frozen-lockfile) bunx <pkg> # Execute package without installing (100x faster than npx)

Workspace Support:

{ "workspaces": ["packages/", "apps/"], "dependencies": { "shared-pkg": "workspace:*" } }

Package Management:

bun pm trust <pkg> # Allow lifecycle scripts bun pm untrusted # View blocked scripts bun why <pkg> # Explain why package installed bun outdated # Show outdated packages bun audit # Security vulnerability check bun patch <pkg> # Prepare package for patching bun link # Link local packages

Lockfile: Bun uses bun.lock (text-based JSONC format) - human-readable, git-diffable. Automatically migrates from package-lock.json , yarn.lock , or pnpm-lock.yaml .

  1. Test Runner (bun:test)

Test Syntax:

import { describe, test, expect, beforeAll, afterEach, mock, spyOn } from "bun:test";

describe("feature", () => { beforeAll(() => { /* setup */ }); afterEach(() => { mock.restore(); });

test("basic assertion", () => { expect(2 + 2).toBe(4); });

test("async operation", async () => { const result = await fetchData(); expect(result).toMatchObject({ status: "ok" }); });

test.each([[1, 2, 3], [2, 3, 5]])("adds %i + %i = %i", (a, b, expected) => { expect(a + b).toBe(expected); }); });

Test Modifiers:

  • test.skip()

  • Skip test

  • test.only()

  • Run only this test (with --only flag)

  • test.todo()

  • Mark as todo

  • test.if(condition) / test.skipIf(condition)

  • Conditional execution

  • test.failing()

  • Expected to fail

  • test.concurrent

  • Run concurrently

  • test.retry(n)

  • Retry failed tests

Key Matchers:

  • .toBe() , .toEqual() , .toStrictEqual()

  • Equality

  • .toContain() , .toHaveLength() , .toMatch()

  • String/Array

  • .toHaveProperty() , .toMatchObject()

  • Objects

  • .toThrow() , .rejects.toThrow()

  • Errors

  • .toMatchSnapshot() , .toMatchInlineSnapshot()

  • Snapshots

  • .toHaveBeenCalled() , .toHaveBeenCalledWith()

  • Mocks

Mocking:

import { mock, spyOn } from "bun:test";

const mockFn = mock(() => 42); mockFn.mockImplementation(() => 100); mockFn.mockReturnValue(200);

const spy = spyOn(object, "method"); spy.mockResolvedValue({ data: "test" });

// Module mocking mock.module("./api", () => ({ fetchUser: mock(() => ({ id: 1, name: "Test" })) }));

CLI Commands:

bun test # Run all tests bun test --watch # Watch mode bun test --coverage # Enable coverage bun test -t "pattern" # Filter by test name bun test --timeout=5000 # Set timeout bun test --bail # Stop on first failure bun test --update-snapshots # Update snapshots

  1. Bundler Configuration

JavaScript API:

const result = await Bun.build({ entrypoints: ["./src/index.tsx"], outdir: "./dist", target: "browser", // "browser" | "bun" | "node" format: "esm", // "esm" | "cjs" | "iife" minify: true, sourcemap: "external", splitting: true, // Code splitting external: ["react", "react-dom"], define: { "process.env.NODE_ENV": '"production"' }, loader: { ".png": "dataurl", ".svg": "text" }, plugins: [myPlugin], naming: { entry: "[dir]/[name].[ext]", chunk: "[name]-[hash].[ext]" } });

if (!result.success) { console.error(result.logs); }

CLI:

bun build ./src/index.tsx --outdir ./dist --minify --sourcemap=external bun build ./src/index.ts --compile --outfile myapp # Single executable

Plugin System:

const myPlugin: BunPlugin = { name: "yaml-loader", setup(build) { build.onLoad({ filter: /.yaml$/ }, async (args) => { const text = await Bun.file(args.path).text(); return { contents: export default ${JSON.stringify(YAML.parse(text))}, loader: "js" }; }); } };

  1. TypeScript Integration

Bun executes TypeScript natively without transpilation configuration:

bun run index.ts # Just works bun run index.tsx # JSX supported

Recommended tsconfig.json:

{ "compilerOptions": { "lib": ["ESNext"], "target": "ESNext", "module": "ESNext", "moduleDetection": "force", "moduleResolution": "bundler", "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, "noEmit": true, "strict": true, "skipLibCheck": true, "types": ["bun-types"] } }

Type checking (separate step):

bunx tsc --noEmit

  1. Configuration (bunfig.toml)

Runtime

preload = ["./setup.ts"] smol = true # Reduced memory mode

JSX

[jsx] runtime = "automatic" importSource = "react"

Package installation

[install] optional = false lockfile.save = true

[install.scopes] "@myorg" = { url = "https://npm.myorg.com", token = "$NPM_TOKEN" }

Test runner

[test] preload = ["./test-setup.ts"] coverage = true coverageThreshold = { lines = 0.8, functions = 0.8 }

  1. CLI Flags Reference

Execution:

  • --watch

  • Auto-restart on file changes

  • --hot

  • Hot module replacement

  • --smol

  • Reduced memory mode

  • --inspect / --inspect-brk

  • Debugger

Module Resolution:

  • --preload / -r

  • Preload modules

  • --install=auto|fallback|force

  • Auto-install behavior

Transpilation:

  • --define / -d

  • Compile-time constants

  • --drop=console

  • Remove function calls

  • --loader

  • Custom file loaders

Environment:

  • --env-file

  • Load specific .env files

  • --cwd

  • Set working directory

  • --bun / -b

  • Force Bun runtime

Node.js Migration Guidance

Quick Migration Steps

Delete node_modules and lockfile

rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml bun install

  • Update scripts in package.json:

{ "scripts": { "dev": "bun run --watch src/index.ts", "test": "bun test", "build": "bun build src/index.ts --outdir dist" } }

  • Update TypeScript types:

bun add -d @types/bun

Or in tsconfig.json: "types": ["bun-types"]

API Compatibility

Fully Compatible:

  • node:assert , node:buffer , node:events , node:path , node:url

  • node:fs (92%), node:http , node:https , node:stream , node:zlib

  • node:crypto , node:net , node:dns , node:os

Partially Compatible:

  • node:child_process

  • Missing proc.gid , proc.uid ; IPC limited to JSON

  • node:cluster

  • Linux-only SO_REUSEPORT for load balancing

  • node:http2

  • 95% compatible; missing pushStream

  • node:worker_threads

  • Missing stdin , stdout , stderr options

  • node:async_hooks

  • AsyncLocalStorage works; v8 promise hooks missing

Not Implemented:

  • node:inspector , node:repl , node:trace_events

Common Migration Gotchas

  • Native Modules: Packages using node-gyp (bcrypt, sharp) may fail

  • Solution: Use pure JS alternatives (bcryptjs instead of bcrypt )

  • Lifecycle Scripts: Bun blocks postinstall by default (security)

  • Solution: bun pm trust <package> or add to trustedDependencies

  • Module System: Some packages relying on Node.js internals may fail

  • Module._nodeModulePaths doesn't exist in Bun

  • File System Differences: Heavy concurrent file reads can cause memory issues

  • Solution: Use graceful-fs wrapper

  • TypeScript Entry Points: Update "main" field for Bun:

{ "main": "src/index.ts" // Not "build/index.js" }

Gradual Migration Strategy

Phase 1: Package manager only (bun install ) Phase 2: Development tooling (bun run , bun test ) Phase 3: Selective runtime migration (shadow deploy) Phase 4: Full production migration

Best Practices

Performance Optimization

// Use Bun's native APIs for I/O const file = Bun.file("large.txt"); // Zero-copy const content = await file.text(); await Bun.write("output.txt", processedData);

// Use Promise.all for concurrent operations const [users, posts] = await Promise.all([ db.query("SELECT * FROM users"), db.query("SELECT * FROM posts") ]);

// Use Bun.serve() static routes Bun.serve({ static: { "/": homepage, "/about": aboutPage }, fetch(req) { /* dynamic routes */ } });

// Use bun:sqlite for local data import { Database } from "bun:sqlite"; const db = new Database(":memory:"); const stmt = db.prepare("SELECT * FROM users WHERE id = ?");

Error Handling

// HTTP server error handling Bun.serve({ fetch(req) { try { return handleRequest(req); } catch (error) { console.error(error); return new Response("Internal Error", { status: 500 }); } }, error(error) { return new Response(Error: ${error.message}, { status: 500 }); } });

// Process-level error handling process.on("uncaughtException", (error) => { console.error("Uncaught:", error); process.exit(1); });

Security Best Practices

  • Lifecycle Scripts: Keep trustedDependencies minimal

  • Environment Variables: Use .env.local for secrets (not committed)

  • Input Validation: Sanitize all user inputs

  • Dependencies: Run bun audit regularly

  • Production: Use --production flag to skip devDependencies

Project Structure

my-bun-project/ ├── src/ │ ├── index.ts # Entry point │ ├── server.ts # HTTP server │ └── lib/ # Utilities ├── test/ │ └── *.test.ts # Test files ├── bunfig.toml # Bun configuration ├── tsconfig.json # TypeScript config ├── package.json └── .env.local # Local secrets (gitignored)

Debugging

Web Debugger:

bun --inspect server.ts # Start debugger bun --inspect-brk server.ts # Break at first line bun --inspect-wait server.ts # Wait for connection

Open https://debug.bun.sh or use VSCode Bun extension.

Verbose Fetch Logging:

BUN_CONFIG_VERBOSE_FETCH=curl bun run server.ts

Examples

HTTP Server with WebSocket

Bun.serve({ port: 3000, fetch(req, server) { if (server.upgrade(req)) return; return new Response("Hello Bun!"); }, websocket: { open(ws) { console.log("Connected"); }, message(ws, message) { ws.send(Echo: ${message}); }, close(ws) { console.log("Disconnected"); } } });

File Server

Bun.serve({ async fetch(req) { const path = new URL(req.url).pathname; const file = Bun.file(./public${path}); if (await file.exists()) { return new Response(file); } return new Response("Not Found", { status: 404 }); } });

Database with SQLite

import { Database } from "bun:sqlite";

const db = new Database("app.db"); db.run(CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE ));

const insert = db.prepare("INSERT INTO users (name, email) VALUES (?, ?)"); const getAll = db.prepare("SELECT * FROM users");

insert.run("Alice", "alice@example.com"); const users = getAll.all();

When This Skill Activates

This skill automatically activates when:

  • Working with .ts , .tsx , .js , .jsx files in a Bun project

  • Creating or modifying bunfig.toml or bun.lock

  • Using bun:test , bun:sqlite , bun:ffi imports

  • Discussing Bun APIs (Bun.serve, Bun.file, Bun.build)

  • Migrating from Node.js to Bun

  • Writing or debugging Bun tests

  • Configuring the Bun bundler

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

redis-expert

No summary provided by upstream source.

Repository SourceNeeds Review
General

elysiajs-expert

No summary provided by upstream source.

Repository SourceNeeds Review
General

zig-expert

No summary provided by upstream source.

Repository SourceNeeds Review