| name | bun-api |
| description | Bun runtime API reference for TypeScript scripts. Covers Bun.file(), Bun.write(), Bun.$() shell, Bun.spawn(), Bun.Glob, Bun.env, bun:sqlite, Bun.sql() for PostgreSQL/MySQL via DATABASE_URL, Bun.s3 for S3-compatible storage, Bun.redis for Redis/Valkey, Bun.Archive for tarballs, Bun.Image image processing, Bun.WebView headless browser automation, Bun.cron in-process scheduler, JSONC/JSON5/JSONL/markdown (named imports), Bun.hash, Bun.password, compression, and scripting utilities. Use when writing scripts, automating tasks, querying databases, working with S3 storage, Redis caching, processing images, automating a headless browser, parsing markdown/JSON variants, or doing file processing in a Bun project. Signals: bun.lock, bunfig.toml, DATABASE_URL, REDIS_URL, AWS_ACCESS_KEY_ID, Bun.$ usage Not for bun CLI commands (bun-cli skill), non-Bun runtimes, or ORM CLI tooling |
Bun Runtime API
Bun runs TypeScript natively — no tsc compilation, no ts-node, no build step. Run any .ts file directly with bun file.ts. Use Bun's native APIs instead of Node.js equivalents — they're faster, more ergonomic, and require no additional dependencies.
Critical: In a Bun project (has bun.lock, bun.lockb, bunfig.toml, or @types/bun in devDependencies), always use Bun to run scripts (bun file.ts, not node file.ts) and prefer Bun-native APIs over Node.js equivalents. Mixing runtimes causes subtle bugs and unnecessary retries.
Verified against Bun v1.3.14 (2026-05-28).
When to Use
- Scripts for generating files, parsing data, running migrations
- File processing and transformation pipelines
- Shell scripting and automation
- Database operations with SQLite (
bun:sqlite)
- Database queries via connection URL -- project has
DATABASE_URL in .env or environment (PostgreSQL, MySQL, SQLite via Bun.sql())
- S3 storage operations -- project has
AWS_ACCESS_KEY_ID or uses S3-compatible storage (Bun.s3)
- Redis/Valkey caching and pub/sub -- project has
REDIS_URL or VALKEY_URL (Bun.redis)
- Any scripting task in a Bun project
HTTP Server (Bun.serve)
Built-in HTTP server — replaces Express, Fastify, or http.createServer.
const server = Bun.serve({
port: 3000,
fetch(req: Request): Response | Promise<Response> {
const url = new URL(req.url)
if (url.pathname === '/api/health') {
return Response.json({ status: 'ok' })
}
if (url.pathname === '/api/data' && req.method === 'POST') {
const body = await req.json()
return Response.json({ received: body })
}
return new Response('Not Found', { status: 404 })
},
error(error: Error): Response {
return new Response(`Error: ${error.message}`, { status: 500 })
},
})
console.log(`Listening on ${server.url}`)
Key methods: server.stop(), server.reload() (hot-swap handler), server.requestIP(req), server.upgrade(req) (WebSocket).
Reference: See references/http-server.md for TLS, WebSocket upgrade, streaming responses, static file serving, and full server API.
TCP / UDP Sockets
Raw sockets for non-HTTP protocols -- Bun.listen() / Bun.connect() for TCP, Bun.udpSocket() for UDP, plus the built-in WebSocket client and fetch().
const server = Bun.listen({
hostname: '127.0.0.1',
port: 8080,
socket: {
open(socket) { socket.write('welcome\n') },
data(socket, data) { },
},
})
Reference: See references/networking.md for TCP/UDP handlers, Unix sockets, the WebSocket client (ws+unix://), and fetch() transport options (HTTP/2, HTTP/3, proxies, system CA).
File I/O
Reading Files
const file = Bun.file('path/to/file.txt')
const text = await file.text()
const json = await file.json()
const bytes = await file.arrayBuffer()
const stream = file.stream()
const blob = await file.blob()
file.size
file.type
file.name
await file.exists()
const remote = Bun.file('https://example.com/data.json')
Writing Files
await Bun.write('output.txt', 'content')
await Bun.write('copy.txt', Bun.file('original.txt'))
await Bun.write('data.json', JSON.stringify(data, null, 2))
await Bun.write('binary.dat', new Uint8Array([1, 2, 3]))
await Bun.write('page.html', await fetch('https://example.com'))
await Bun.write(Bun.stdout, 'Hello\n')
Stdio
Bun.stdin
Bun.stdout
Bun.stderr
const input = await Bun.stdin.text()
for await (const chunk of Bun.stdin.stream()) {
}
Common Patterns
const data = await Bun.file('input.json').json()
data.version = '2.0.0'
await Bun.write('output.json', JSON.stringify(data, null, 2))
const template = await Bun.file('template.html').text()
const output = template.replace('{{title}}', 'My Page')
await Bun.write('index.html', output)
const file = Bun.file('config.json')
if (await file.exists()) {
const config = await file.json()
}
Reference: See references/file-io.md for BunFile interface, write overloads, streaming, MIME detection, and file watching.
Shell and Process Execution
Bun.$ (Tagged Template Shell)
The primary way to run shell commands. Returns a promise with output.
import { $ } from 'bun'
const result = await $`ls -la`
console.log(result.text())
const dir = 'my folder'
await $`ls ${dir}`
const output = await $`echo hello`
output.text()
output.json()
output.lines()
output.bytes()
output.blob()
output.exitCode
output.stderr
await $`cat file.txt | grep pattern | wc -l`
await $`npm install`.quiet()
const result = await $`command-that-might-fail`.nothrow()
if (result.exitCode !== 0) {
console.error('Failed:', result.stderr.toString())
}
await $`risky-command`.quiet().nothrow()
await $`echo $HOME`.env({ HOME: '/custom' })
await $`ls`.cwd('/tmp')
await $`echo hello > output.txt`
await $`cat < input.txt`
const input = Buffer.from('hello')
await $`cat`.stdin(input)
Bun.spawn (Lower-Level)
For more control over process execution.
const proc = Bun.spawn(['command', 'arg1', 'arg2'], {
cwd: '/path',
env: { ...process.env, CUSTOM: 'value' },
stdin: 'pipe',
stdout: 'pipe',
stderr: 'pipe',
onExit(proc, exitCode, signalCode, error) {
},
})
proc.stdin.write('input data')
proc.stdin.end()
const output = await new Response(proc.stdout).text()
await proc.exited
proc.kill()
proc.kill('SIGKILL')
Bun.spawnSync (Synchronous)
const result = Bun.spawnSync(['command', 'arg1'], {
cwd: '/path',
env: { ...process.env },
})
result.exitCode
result.stdout
result.stderr
result.success
Reference: See references/shell-and-process.md for complete $ API, spawn options, IPC, and signal handling.
Glob Pattern Matching
const glob = new Bun.Glob('**/*.ts')
for await (const path of glob.scan({ cwd: './src', onlyFiles: true })) {
console.log(path)
}
for (const path of glob.scanSync('./src')) {
console.log(path)
}
glob.match('src/index.ts')
glob.match('README.md')
glob.scan({
cwd: './src',
dot: false,
onlyFiles: true,
absolute: false,
followSymlinks: false,
})
Environment and Arguments
Bun.env.NODE_ENV
Bun.env.DATABASE_URL
Bun.argv
Bun.main
import.meta.dir
import.meta.file
import.meta.path
import.meta.dirname
import.meta.filename
SQL Client (Bun.sql) -- PostgreSQL, MySQL, SQLite
Built-in SQL client for querying databases via connection URL. Zero dependencies, tagged template literals, automatic prepared statements, connection pooling. Use when the project has DATABASE_URL in .env or environment.
import { sql, SQL } from "bun"
const users = await sql`SELECT * FROM users WHERE active = ${true} LIMIT ${10}`
const db = new SQL("postgres://user:pass@localhost:5432/mydb")
const results = await db`SELECT * FROM users`
const mysql = new SQL("mysql://user:pass@localhost:3306/mydb")
Insert / Update with Object Helpers
const user = { name: "Alice", email: "alice@example.com" }
const [newUser] = await sql`INSERT INTO users ${sql(user)} RETURNING *`
await sql`INSERT INTO users ${sql([user1, user2, user3])}`
await sql`UPDATE users SET ${sql(updates)} WHERE id = ${userId}`
Transactions
await sql.begin(async (tx) => {
const [user] = await tx`INSERT INTO users (name) VALUES (${"Alice"}) RETURNING *`
await tx`INSERT INTO audit_log (action, user_id) VALUES ('created', ${user.id})`
})
Reference: See references/sql-client.md for connection options, pool management, savepoints, MySQL specifics, and prepared statement configuration.
S3 Client (Bun.s3)
Built-in S3 client with Web standard Blob API. Zero dependencies, works with any S3-compatible service (AWS S3, Cloudflare R2, MinIO, etc.). Use when the project has AWS_ACCESS_KEY_ID or S3-compatible credentials in environment.
import { s3, write } from "bun"
const file = s3.file("data.json")
const data = await file.json()
const text = await file.text()
const stream = file.stream()
await write(s3.file("output.json"), JSON.stringify(data))
const url = s3.presign("report.pdf", {
expiresIn: 3600,
method: "PUT",
acl: "public-read",
})
await file.delete()
Reference: See references/s3-client.md for custom S3Client, presign options, multipart upload, and serving from Bun.serve.
Redis Client (Bun.redis)
Built-in Redis/Valkey client with zero dependencies. Use when the project has REDIS_URL or VALKEY_URL in environment.
import { redis, RedisClient } from "bun"
await redis.set("key", "value")
const value = await redis.get("key")
await redis.set("session", "data", "EX", 3600)
await redis.incr("counter")
await redis.incrby("counter", 5)
await redis.hset("user:1", "name", "Alice", "email", "alice@example.com")
await redis.hget("user:1", "name")
const client = new RedisClient("redis://user:pass@host:6379")
Reference: See references/redis-client.md for all commands (strings, hashes, lists, sets, sorted sets), pub/sub, pipelines, and common patterns.
Archive (Bun.Archive)
Create and extract tarballs with optional gzip compression.
const archive = new Bun.Archive({
"hello.txt": "Hello, World!",
"config.json": JSON.stringify({ key: "value" }),
})
await Bun.write("archive.tar", archive)
const compressed = new Bun.Archive(
{ "hello.txt": "Hello, World!" },
{ compress: "gzip", level: 9 }
)
await Bun.write("archive.tar.gz", compressed)
const tarball = await Bun.file("archive.tar.gz").bytes()
const extracted = new Bun.Archive(tarball)
JSONC (JSON with Comments)
Parse JSON with comments and trailing commas -- replaces jsonc-parser or json5 packages.
import { JSONC } from "bun"
const config = JSONC.parse(`{
// Database config
"host": "localhost",
"port": 5432, // default port
}`)
Bun automatically uses JSONC parsing for tsconfig.json, jsconfig.json, package.json, and bun.lock. .jsonc files can be imported directly: import config from "./config.jsonc".
Additional Parsing and Utilities (v1.3+)
import { JSON5, JSONL, markdown, cron } from "bun"
const config = JSON5.parse(`{ unquoted: 'value', /* comment */ }`)
const records = JSONL.parse('{"a":1}\n{"a":2}\n')
const html = markdown.html("# Title\n\n**Bold** text.")
const ansi = markdown.ansi("# Title")
const job = cron("0 9 * * 1-5", runReport)
const next = cron.parse("0 9 * * 1-5")
const coloredText = "\x1b[31mHello, World!\x1b[0m"
Bun.wrapAnsi(coloredText, 80)
Bun.sliceAnsi(coloredText, 0, 5)
Reference: See references/utilities.md for full details on all parsing and utility APIs.
SQLite (bun:sqlite)
Built-in SQLite3 with zero dependencies. For embedded/local databases -- file-based or in-memory.
import { Database } from 'bun:sqlite'
const db = new Database('mydb.sqlite')
const db = new Database(':memory:')
db.exec('PRAGMA journal_mode = WAL')
db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)')
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)')
insert.run('Alice', 'alice@example.com')
const select = db.prepare('SELECT * FROM users WHERE name = ?')
const user = select.get('Alice')
const users = select.all('Alice')
const stmt = db.prepare('SELECT * FROM users WHERE name = $name')
stmt.get({ $name: 'Alice' })
const insertMany = db.transaction((users) => {
for (const user of users) {
insert.run(user.name, user.email)
}
})
insertMany([
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Carol', email: 'carol@example.com' },
])
db.close()
Reference: See references/sqlite-and-data.md for Database constructor, Statement API, transactions, and column types.
Hashing and Passwords
Bun.hash('input')
Bun.hash.crc32('input')
new Bun.CryptoHasher('sha256').update('data').digest('hex')
const hash = await Bun.password.hash('password')
const hash = await Bun.password.hash('password', { algorithm: 'argon2id' })
const valid = await Bun.password.verify('password', hash)
Reference: See references/hashing.md for all hash algorithms, CryptoHasher streaming API, and password hashing options (bcrypt vs argon2id, cost parameters).
Compression
const compressed = Bun.gzipSync(data)
const decompressed = Bun.gunzipSync(compressed)
const compressed = Bun.deflateSync(data)
const decompressed = Bun.inflateSync(compressed)
const compressed = Bun.zstdCompressSync(data)
const decompressed = Bun.zstdDecompressSync(compressed)
Bun.gzipSync(data, { level: 9, memLevel: 9 })
Bun.deflateSync(data, { level: 6 })
Bun.zstdCompressSync(data, { level: 3 })
All compression functions accept Uint8Array | string | ArrayBuffer and return Uint8Array.
Utilities
Bun.which('node')
Bun.which('bun', { PATH: '/custom/bin' })
Bun.inspect(obj)
Bun.inspect(obj, { depth: 4, colors: true })
Bun.resolveSync('./module', '/from/dir')
Bun.deepEquals(a, b)
Bun.deepEquals(a, b, true)
await Bun.sleep(1000)
await Bun.sleep(Bun.nanoseconds() + 1e9)
Bun.nanoseconds()
Bun.randomUUIDv7()
Bun.stringWidth('hello')
Bun.stringWidth('你好')
const value = Bun.peek(promise)
Bun.color('red', 'css')
Bun.color('#ff0000', 'ansi')
Bun.color('hsl(0, 100%, 50%)', 'number')
Reference: See references/utilities.md for complete utility function signatures and examples.
Semver (Bun.semver)
Built-in semver operations — replaces the semver npm package.
Bun.semver.satisfies('1.2.3', '^1.0.0')
Bun.semver.satisfies('2.0.0', '>=1.0 <2.0')
Bun.semver.satisfies('1.0.0-beta', '*')
Bun.semver.order('1.0.0', '2.0.0')
Bun.semver.order('2.0.0', '1.0.0')
Bun.semver.order('1.0.0', '1.0.0')
const versions = ['3.0.0', '1.2.0', '2.1.0']
versions.sort(Bun.semver.order)
Serialization (bun:jsc)
Binary structured clone for efficient serialization.
import { serialize, deserialize } from 'bun:jsc'
const data = { key: 'value', nested: [1, 2, 3] }
const bytes = serialize(data)
const restored = deserialize(bytes)
Faster than JSON.stringify/JSON.parse for complex objects. Supports types JSON doesn't: Date, RegExp, Map, Set, ArrayBuffer, etc.
Image Processing (Bun.Image)
Built-in image decode/transform/encode (v1.3.14+) — replaces sharp and jimp. Supports JPEG, PNG, WebP, GIF, BMP, HEIC, AVIF, TIFF.
const thumb = await Bun.file('upload.jpg')
.image()
.resize(400, 400, { fit: 'cover' })
.webp({ quality: 82 })
.bytes()
const { width, height, format } = await new Bun.Image(buffer).metadata()
const blur = await Bun.file('hero.jpg').image().placeholder()
Reference: See references/image.md for transforms, output formats, and metadata.
Browser Automation (Bun.WebView)
Headless browser automation (v1.3.12+) — navigate, click, type, run JS, and screenshot without Playwright or Puppeteer (WebKit on macOS, Chrome backend elsewhere).
await using view = new Bun.WebView({ width: 1280, height: 720 })
await view.navigate('https://bun.sh')
const title = await view.evaluate('document.title')
await Bun.write('page.png', await view.screenshot())
Reference: See references/webview.md for the full method list and CDP access.
Script Patterns
CLI Script Template
#!/usr/bin/env bun
const args = Bun.argv.slice(2)
const command = args[0]
switch (command) {
case 'generate':
await generate(args.slice(1))
break
case 'process':
await process(args.slice(1))
break
default:
console.log('Usage: script <generate|process> [args]')
process.exit(1)
}
File Generator
const glob = new Bun.Glob('**/*.schema.json')
for await (const path of glob.scan('./schemas')) {
const schema = await Bun.file(`./schemas/${path}`).json()
const code = generateTypeScript(schema)
const outPath = path.replace('.schema.json', '.ts')
await Bun.write(`./generated/${outPath}`, code)
}
Data Pipeline
import { $ } from 'bun'
import { Database } from 'bun:sqlite'
const data = await $`curl -s https://api.example.com/data`.json()
const db = new Database('output.sqlite')
db.exec('CREATE TABLE IF NOT EXISTS items (id TEXT PRIMARY KEY, value TEXT)')
const insert = db.prepare('INSERT OR REPLACE INTO items (id, value) VALUES (?, ?)')
const batch = db.transaction((items) => {
for (const item of items) {
insert.run(item.id, JSON.stringify(item))
}
})
batch(data.items)
db.close()
Best Practices
- Prefer
Bun.file() + Bun.write() over fs.readFile/fs.writeFile
- Use
Bun.$ for shell commands instead of child_process
- Use
Bun.sql() for PostgreSQL/MySQL when DATABASE_URL is available -- zero-dependency, connection pooling, tagged templates
- Use
bun:sqlite for embedded/local SQLite databases instead of external packages
- Use
Bun.Glob instead of glob npm package
- Use
Bun.CryptoHasher instead of crypto.createHash
- Use
Bun.password instead of bcrypt/argon2 npm packages
- Use
Bun.gzipSync/Bun.zstdCompressSync instead of zlib
- Use
Bun.env for environment variables (same as process.env but typed)
- Use
import.meta.dir instead of __dirname (or import.meta.dirname for Node compat)
- Use
Bun.which() instead of which npm package
- Use
Bun.s3 instead of @aws-sdk/client-s3 for S3 operations
- Use
Bun.redis instead of ioredis or redis npm packages
- Use
Bun.Archive instead of tar or archiver npm packages for tarballs
- Use
JSONC.parse() instead of jsonc-parser package
- Use
JSON5.parse() instead of json5 package
- Use
JSONL.parse() instead of manual newline splitting for JSON Lines
- Use
markdown.html()/markdown.ansi() instead of marked, remark, or markdown-it packages
- Use
Bun.wrapAnsi() instead of wrap-ansi npm package
- Use
Bun.sliceAnsi() instead of slice-ansi npm package
- Use
Bun.Image instead of sharp or jimp for image processing