bun-expert
npx skills add https://github.com/lammesen/skills --skill bun-expert
Agent 安装分布
Skill 文档
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 APIBun.connect()/Bun.listen()– TCP/UDP socket APIsBun.dns– DNS resolution utilities
File System Operations:
Bun.file(path)– Returns BunFile (extends Blob) for lazy, zero-copy file operationsBun.write(path, data)– Optimized file writesBun.stdin/Bun.stdout/Bun.stderr– Standard I/O streams
Process & Shell:
Bun.spawn(cmd)/Bun.spawnSync(cmd)– Child process spawningBun.$\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, SQLiteBun.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 hashingBun.hash(data)– Fast hashing (xxhash, murmur)Bun.Glob– Native glob pattern matchingBun.semver– Semver comparison utilitiesBun.sleep(ms)/Bun.sleepSync(ms)– Sleep functionsBun.deepEquals(a, b)– Deep comparisonBun.escapeHTML()– HTML sanitizationBun.YAML.parse()/Bun.YAML.stringify()– Native YAML supportHTMLRewriter– HTML streaming transformations
Advanced Features:
bun:ffi– Foreign Function Interface (2-6x faster than Node.js FFI)Worker– Web Workers API for multi-threadingBroadcastChannel– Pub/sub messaging across threadsBun.Transpiler– JavaScript/TypeScript transpilation APIBun.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 testtest.only()– Run only this test (with--onlyflag)test.todo()– Mark as todotest.if(condition)/test.skipIf(condition)– Conditional executiontest.failing()– Expected to failtest.concurrent– Run concurrentlytest.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
- Install Bun:
curl -fsSL https://bun.sh/install | bash - Replace package manager:
# 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:urlnode:fs(92%),node:http,node:https,node:stream,node:zlibnode:crypto,node:net,node:dns,node:os
Partially Compatible:
node:child_process– Missingproc.gid,proc.uid; IPC limited to JSONnode:cluster– Linux-only SO_REUSEPORT for load balancingnode:http2– 95% compatible; missingpushStreamnode:worker_threads– Missingstdin,stdout,stderroptionsnode: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 (
bcryptjsinstead ofbcrypt)
- Solution: Use pure JS alternatives (
- Lifecycle Scripts: Bun blocks postinstall by default (security)
- Solution:
bun pm trust <package>or add totrustedDependencies
- Solution:
- Module System: Some packages relying on Node.js internals may fail
Module._nodeModulePathsdoesn’t exist in Bun
- File System Differences: Heavy concurrent file reads can cause memory issues
- Solution: Use
graceful-fswrapper
- Solution: Use
- 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
trustedDependenciesminimal - Environment Variables: Use
.env.localfor secrets (not committed) - Input Validation: Sanitize all user inputs
- Dependencies: Run
bun auditregularly - Production: Use
--productionflag 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,.jsxfiles in a Bun project - Creating or modifying
bunfig.tomlorbun.lock - Using
bun:test,bun:sqlite,bun:ffiimports - Discussing Bun APIs (Bun.serve, Bun.file, Bun.build)
- Migrating from Node.js to Bun
- Writing or debugging Bun tests
- Configuring the Bun bundler