# Install Bun
curl -fsSL https://bun.sh/install | bash
# Upgrade Bun
bun upgrade
# Check version
bun --version# Create new project
bun init
# Create new Next.js project
bunx create-next-app@latest my-app
# Install dependencies
bun install
# Add a package
bun add express
# Add dev dependency
bun add -d typescript
# Remove a package
bun remove express
# Run a script
bun run dev
bun run build
bun run start# Run a file directly
bun index.ts
bun index.js
# Run with watch mode (auto restart)
bun --watch index.ts
# Run with hot reload
bun --hot index.ts
# Execute a one-liner
bun -e "console.log('hello')"| Command | Description |
|---|---|
bun install |
Install all dependencies |
bun add <pkg> |
Add a package |
bun add -d <pkg> |
Add a dev dependency |
bun add -g <pkg> |
Add a global package |
bun remove <pkg> |
Remove a package |
bun update |
Update all packages |
bun update <pkg> |
Update specific package |
bun pm ls |
List installed packages |
bun pm cache rm |
Clear package cache |
bun installis up to 25x faster than npm — uses a binary lockfilebun.lockb
{
"scripts": {
"dev": "bun --watch index.ts",
"build": "bun build ./index.ts --outdir ./dist",
"start": "bun index.ts",
"test": "bun test"
}
}bun run dev
bun run build# Bundle for browser
bun build ./index.ts --outdir ./dist
# Bundle as single file
bun build ./index.ts --outfile bundle.js
# Minify output
bun build ./index.ts --outdir ./dist --minify
# Target specific environment
bun build ./index.ts --outdir ./dist --target browser
bun build ./index.ts --outdir ./dist --target node
bun build ./index.ts --outdir ./dist --target bun
# Watch mode
bun build ./index.ts --outdir ./dist --watch// No express needed — Bun has a built-in fast HTTP server
Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url)
if (url.pathname === '/') {
return new Response('Hello World')
}
if (url.pathname === '/json') {
return Response.json({ message: 'Hello' })
}
return new Response('Not Found', { status: 404 })
},
})
console.log('Server running at http://localhost:3000')// Read file
const file = Bun.file('data.txt')
const text = await file.text()
const json = await file.json()
const buffer = await file.arrayBuffer()
// Write file
await Bun.write('output.txt', 'Hello World')
await Bun.write('data.json', JSON.stringify({ key: 'value' }))
// Check if file exists
const exists = await Bun.file('data.txt').exists()
// File size
const size = Bun.file('data.txt').size// Bun auto-loads .env, .env.local, .env.production
console.log(Bun.env.DATABASE_URL)
console.log(process.env.DATABASE_URL) // also works# .env
DATABASE_URL=postgres://localhost/mydb
API_KEY=secret123No need for
dotenvpackage — Bun loads.envautomatically
// math.test.ts
import { test, expect, describe, beforeEach } from 'bun:test'
describe('math', () => {
test('adds two numbers', () => {
expect(1 + 1).toBe(2)
})
test('async test', async () => {
const result = await Promise.resolve(42)
expect(result).toBe(42)
})
})# Run all tests
bun test
# Run specific file
bun test math.test.ts
# Watch mode
bun test --watch
# Coverage
bun test --coverage// No external package needed
import { Database } from 'bun:sqlite'
const db = new Database('mydb.sqlite')
// Create table
db.run('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)')
// Insert
db.run('INSERT INTO users (name) VALUES (?)', ['Alice'])
// Query
const users = db.query('SELECT * FROM users').all()
console.log(users)
// Prepared statement
const getUser = db.query('SELECT * FROM users WHERE id = ?')
const user = getUser.get(1)Bun.serve({
port: 3000,
fetch(req, server) {
if (server.upgrade(req)) return // upgrade to WebSocket
return new Response('Not a WebSocket', { status: 400 })
},
websocket: {
open(ws) { console.log('connected') },
message(ws, msg) { ws.send(`echo: ${msg}`) },
close(ws) { console.log('disconnected') },
},
})# Run a package without installing
bunx cowsay "Hello"
bunx create-next-app@latest
bunx prettier --write .
bunx eslint .| Node + npm | Bun | |
|---|---|---|
| Runtime | V8 | JavaScriptCore |
| Install speed | baseline | up to 25x faster |
| TypeScript | needs ts-node/tsx | ✅ native, zero config |
.env loading |
needs dotenv | ✅ built-in |
| Test runner | needs Jest/Vitest | ✅ built-in |
| Bundler | needs webpack/esbuild | ✅ built-in |
| SQLite | needs better-sqlite3 | ✅ built-in |
| HTTP server | needs express/fastify | ✅ built-in |
| npm compatible | ✅ | ✅ fully compatible |
- Use
bun --watchduring development instead ofnodemon - No need for
ts-node,dotenv,jest— Bun replaces all of them bun.lockbis binary — commit it to git, don't edit manually- Use
bunxinstead ofnpxfor faster one-off package execution - Bun is a drop-in replacement — existing
package.jsonscripts work as-is - For packages with known Bun issues (e.g. Qwen Code), fall back to
npm install -g