lammesen

bun-expert

1
0
# Install this skill:
npx skills add lammesen/skills --skill "bun-expert"

Install specific skill from multi-skill repository

# Description

|

# SKILL.md


name: bun-expert
description: |
Comprehensive Bun runtime expertise covering all major features.
Use when working with Bun projects, migrating from Node.js, or leveraging Bun-specific APIs.
Activates for: Bun.serve, Bun.file, bun:test, bun:sqlite, bun install, bun build,
bunfig.toml, TypeScript in Bun, package manager operations, bundler configuration,
and Node.js compatibility questions.
allowed-tools: Read, Write, Edit, MultiEdit, Grep, Glob, Bash


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


2. 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.


3. 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

4. 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"
      };
    });
  }
};

5. 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

6. 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 }

7. 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

  1. Install Bun: curl -fsSL https://bun.sh/install | bash
  2. Replace package manager:
# Delete node_modules and lockfile
rm -rf node_modules package-lock.json yarn.lock pnpm-lock.yaml
bun install
  1. Update scripts in package.json:
{
  "scripts": {
    "dev": "bun run --watch src/index.ts",
    "test": "bun test",
    "build": "bun build src/index.ts --outdir dist"
  }
}
  1. 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

  1. Native Modules: Packages using node-gyp (bcrypt, sharp) may fail
  2. Solution: Use pure JS alternatives (bcryptjs instead of bcrypt)
  3. Lifecycle Scripts: Bun blocks postinstall by default (security)
  4. Solution: bun pm trust <package> or add to trustedDependencies
  5. Module System: Some packages relying on Node.js internals may fail
  6. Module._nodeModulePaths doesn't exist in Bun
  7. File System Differences: Heavy concurrent file reads can cause memory issues
  8. Solution: Use graceful-fs wrapper
  9. 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

  1. Lifecycle Scripts: Keep trustedDependencies minimal
  2. Environment Variables: Use .env.local for secrets (not committed)
  3. Input Validation: Sanitize all user inputs
  4. Dependencies: Run bun audit regularly
  5. 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", "[email protected]");
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

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.