bun-dev

Bun runtime → native APIs → zero-dependency patterns.

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-dev" with this command: npx skills add outfitter-dev/agents/outfitter-dev-agents-bun-dev

Bun Development

Bun runtime → native APIs → zero-dependency patterns.

<when_to_use>

  • Bun runtime development

  • SQLite database with bun:sqlite

  • HTTP server with Bun.serve

  • Testing with bun:test

  • File operations with Bun.file/Bun.write

  • Shell operations with $ template

  • Password hashing with Bun.password

  • Environment variable handling

  • Building and bundling

NOT for: Node.js-only patterns, cross-runtime libraries, non-Bun projects

</when_to_use>

<runtime_basics>

Package management:

bun install # Install deps bun add zod # Add package bun remove zod # Remove package bun update # Update all

Script execution:

bun run dev # Run package.json script bun run src/index.ts # Execute TypeScript directly bun --watch index.ts # Watch mode

Testing:

bun test # All tests bun test src/ # Directory bun test --watch # Watch mode bun test --coverage # With coverage

Building:

bun build ./index.ts --outfile dist/bundle.js bun build ./index.ts --compile --outfile myapp # Standalone executable

</runtime_basics>

File Operations

<file_operations>

// Read file (lazy, efficient) const file = Bun.file('./data.json'); if (!(await file.exists())) throw new Error('File not found');

// Read formats const text = await file.text(); const json = await file.json(); const buffer = await file.arrayBuffer(); const stream = file.stream(); // Large files

// Metadata console.log(file.size, file.type);

// Write await Bun.write('./output.txt', 'content'); await Bun.write('./data.json', JSON.stringify(data)); await Bun.write('./blob.txt', new Blob(['data']));

</file_operations>

SQLite (bun:sqlite)

import { Database } from 'bun:sqlite';

const db = new Database('app.db', { create: true, readwrite: true, strict: true });

// Create tables db.run( CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, email TEXT UNIQUE NOT NULL, name TEXT NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP ));

// Prepared statements (always use these) const getUser = db.prepare('SELECT * FROM users WHERE id = ?'); const createUser = db.prepare('INSERT INTO users (id, email, name) VALUES (?, ?, ?) RETURNING *');

// Execution const user = getUser.get('user-123'); // Single row const all = db.prepare('SELECT * FROM users').all(); // All rows db.prepare('DELETE FROM users WHERE id = ?').run('id'); // No return

// Named parameters const stmt = db.prepare('SELECT * FROM users WHERE email = $email'); stmt.get({ $email: 'alice@example.com' });

// Transactions (atomic, auto-rollback on error) const transfer = db.transaction((fromId: string, toId: string, amount: number) => { db.run('UPDATE accounts SET balance = balance - ? WHERE id = ?', [amount, fromId]); db.run('UPDATE accounts SET balance = balance + ? WHERE id = ?', [amount, toId]); }); transfer('alice', 'bob', 100);

db.close(); // When done

See sqlite-patterns.md for migrations, pooling, repository pattern.

Password Hashing

// Hash (argon2id recommended) const hash = await Bun.password.hash('password123', { algorithm: 'argon2id', memoryCost: 65536, // 64 MB timeCost: 3 });

// Or bcrypt const bcryptHash = await Bun.password.hash('password123', { algorithm: 'bcrypt', cost: 12 });

// Verify const isValid = await Bun.password.verify('password123', hash); if (!isValid) throw new Error('Invalid password');

Auth flow example:

app.post('/auth/register', zValidator('json', RegisterSchema), async (c) => { const { email, password } = c.req.valid('json'); const db = c.get('db');

if (db.prepare('SELECT id FROM users WHERE email = ?').get(email)) { throw new HTTPException(409, { message: 'Email already registered' }); }

const hashedPassword = await Bun.password.hash(password, { algorithm: 'argon2id' }); const user = db.prepare( INSERT INTO users (id, email, password) VALUES (?, ?, ?) RETURNING id, email ).get(crypto.randomUUID(), email, hashedPassword);

return c.json({ user }, 201); });

HTTP Server

<http_server>

Bun.serve({ port: 3000, fetch(req) { const url = new URL(req.url); if (url.pathname === '/') return new Response('Hello'); if (url.pathname === '/json') return Response.json({ ok: true }); return new Response('Not found', { status: 404 }); }, error(err) { return new Response(Error: ${err.message}, { status: 500 }); } });

With Hono (recommended for APIs):

import { Hono } from 'hono';

const app = new Hono() .get('/', (c) => c.text('Hello')) .get('/json', (c) => c.json({ ok: true }));

Bun.serve({ port: 3000, fetch: app.fetch });

See server-patterns.md for routing, middleware, file serving, streaming.

</http_server>

WebSocket

import type { ServerWebSocket } from 'bun';

type WsData = { userId: string };

Bun.serve<WsData>({ port: 3000, fetch(req, server) { const url = new URL(req.url); if (url.pathname === '/ws') { const userId = url.searchParams.get('userId') || 'anon'; return server.upgrade(req, { data: { userId } }) ? undefined : new Response('Upgrade failed', { status: 400 }); } return new Response('Hello'); }, websocket: { open(ws: ServerWebSocket<WsData>) { ws.subscribe('chat'); ws.send(JSON.stringify({ type: 'connected' })); }, message(ws: ServerWebSocket<WsData>, msg: string | Buffer) { ws.publish('chat', msg); }, close(ws: ServerWebSocket<WsData>) { ws.unsubscribe('chat'); } } });

See server-patterns.md for client tracking, rooms, reconnection.

Shell Operations

import { $ } from 'bun';

// Run commands const result = await $ls -la; console.log(result.text());

// Variables (auto-escaped) const dir = './src'; await $find ${dir} -name "*.ts";

// Check exit code const { exitCode } = await $npm test.nothrow(); if (exitCode !== 0) console.error('Tests failed');

// Spawn process const proc = Bun.spawn(['ls', '-la']); await proc.exited;

// Capture output const proc2 = Bun.spawn(['echo', 'Hello'], { stdout: 'pipe' }); const output = await new Response(proc2.stdout).text();

Testing (bun:test)

import { describe, test, expect, beforeEach, afterEach } from 'bun:test';

describe('feature', () => { let db: Database;

beforeEach(() => { db = new Database(':memory:'); }); afterEach(() => { db.close(); });

test('behavior', () => { expect(result).toBe(expected); expect(arr).toContain(item); expect(fn).toThrow(); expect(obj).toEqual({ foo: 'bar' }); });

test('async', async () => { const result = await asyncFn(); expect(result).toBeDefined(); });

test.todo('pending feature'); test.skip('temporarily disabled'); });

bun test # All tests bun test src/api.test.ts # Specific file bun test --watch # Watch mode bun test --coverage # With coverage

See testing.md for assertions, mocking, snapshots, best practices.

Environment Variables

// Access console.log(Bun.env.NODE_ENV); console.log(Bun.env.DATABASE_URL);

// Zod validation import { z } from 'zod';

const EnvSchema = z.object({ NODE_ENV: z.enum(['development', 'production', 'test']).default('development'), DATABASE_URL: z.string(), PORT: z.coerce.number().int().positive().default(3000), API_KEY: z.string().min(32) });

export const env = EnvSchema.parse(Bun.env);

Bun auto-loads .env , .env.local , .env.production .

Performance Utilities

// High-resolution timing const start = Bun.nanoseconds(); await doWork(); console.log(Took ${(Bun.nanoseconds() - start) / 1_000_000}ms);

// Hashing const hash = Bun.hash(data); const crc32 = Bun.hash.crc32(data); const sha256 = Bun.CryptoHasher.hash('sha256', data);

// Sleep await Bun.sleep(1000);

// Memory const { rss, heapUsed } = process.memoryUsage(); console.log('RSS:', rss / 1024 / 1024, 'MB');

Building & Bundling

Production bundle

bun build ./index.ts --outfile dist/bundle.js --minify --sourcemap

External deps

bun build ./index.ts --outfile dist/bundle.js --external hono --external zod

Standalone executable

bun build ./index.ts --compile --outfile myapp

Cross-compile

bun build ./index.ts --compile --target=bun-linux-x64 --outfile myapp-linux bun build ./index.ts --compile --target=bun-darwin-arm64 --outfile myapp-macos bun build ./index.ts --compile --target=bun-windows-x64 --outfile myapp.exe

ALWAYS:

  • Use Bun APIs when available (faster, native)

  • Prepared statements for database queries

  • Transactions for multi-statement operations

  • argon2id for password hashing

  • Validate environment variables at startup

  • Close database connections when done

NEVER:

  • String interpolation in SQL (use parameters)

  • Plaintext passwords

  • Ignore async disposal cleanup

  • Deprecated Node.js APIs when Bun native exists

PREFER:

  • Bun.file over fs.readFile

  • Bun.write over fs.writeFile

  • bun:sqlite over external SQLite libraries

  • Bun.password over bcrypt/argon2 packages

  • $ shell template over child_process

  • sqlite-patterns.md — migrations, pooling, repository, FTS

  • server-patterns.md — HTTP, WebSocket, streaming, compression

  • testing.md — assertions, mocking, snapshots, best practices

Examples:

  • database-crud.md — SQLite CRUD patterns

  • file-uploads.md — streaming file handling

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.

Coding

codebase-recon

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

graphite-stacks

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

hono-dev

No summary provided by upstream source.

Repository SourceNeeds Review