agentsclimarketplace

Bun runtime expert

Skill roedyrustam/claudevibeskills/src/bun-runtime-expert

Koleksi 20 Claude Skills siap pakai untuk pengembangan SaaS, web modern, dan praktik rekayasa perangkat lunak tingkat lanjut.

Install
npx -y skills add roedyrustam/claudevibeskills --skill bun-runtime-expert

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Expert skill for the Bun JavaScript/TypeScript runtime. Use whenever the user is building, running, or debugging code with Bun — covering Bun.serve (HTTP server), Bun.sql (PostgreSQL), Bun.s3 (object storage), bun:test (testing), the Bun bundler, and package manager. Trigger on any mention of Bun, bun install, bun run, Bun.serve, Bun.file, Bun.sql, bun:test, or when the user wants a fast Node.js alternative. Also trigger for Bun shell scripting or Bun-specific APIs.

SKILL.md

9.2 KB, as published. Nobody here has run it

Bun Runtime Expert

Fast, all-in-one JavaScript/TypeScript runtime — server, bundler, package manager, test runner.


Why Bun

FeatureBunNode.js
Startup time~5ms~50ms
bun install~100msnpm: ~3s
Built-in SQLite
Built-in test runner❌ (need Jest)
Built-in bundler❌ (need webpack)
TypeScript natively❌ (need ts-node)
Web APIs (fetch, Request)✅ nativePartial

HTTP Server — Bun.serve

Basic Server

const server = Bun.serve({
  port: 3000,
  hostname: "0.0.0.0",

  async fetch(req: Request): Promise<Response> {
    const url = new URL(req.url)

    if (url.pathname === "/health") {
      return Response.json({ status: "ok" })
    }

    if (url.pathname === "/api/users" && req.method === "GET") {
      const users = await getUsers()
      return Response.json(users)
    }

    if (url.pathname === "/api/users" && req.method === "POST") {
      const body = await req.json()
      const user = await createUser(body)
      return Response.json(user, { status: 201 })
    }

    return new Response("Not Found", { status: 404 })
  },

  error(err: Error): Response {
    console.error(err)
    return Response.json({ error: "Internal Server Error" }, { status: 500 })
  },
})

console.log(`Server running at http://localhost:${server.port}`)

Router Pattern

type Handler = (req: Request, params: Record<string, string>) => Promise<Response>

class Router {
  private routes = new Map<string, Handler>()

  add(method: string, path: string, handler: Handler) {
    this.routes.set(`${method}:${path}`, handler)
    return this
  }

  get(path: string, handler: Handler) { return this.add("GET", path, handler) }
  post(path: string, handler: Handler) { return this.add("POST", path, handler) }
  put(path: string, handler: Handler) { return this.add("PUT", path, handler) }
  delete(path: string, handler: Handler) { return this.add("DELETE", path, handler) }

  async handle(req: Request): Promise<Response> {
    const url = new URL(req.url)
    const key = `${req.method}:${url.pathname}`
    const handler = this.routes.get(key)

    if (!handler) return new Response("Not Found", { status: 404 })
    return handler(req, {})
  }
}

const router = new Router()
  .get("/api/posts", listPosts)
  .post("/api/posts", createPost)
  .get("/api/posts/:id", getPost)

Bun.serve({ fetch: req => router.handle(req) })

WebSocket Support

Bun.serve({
  fetch(req, server) {
    if (server.upgrade(req)) return // Upgraded to WS
    return new Response("HTTP response")
  },
  websocket: {
    open(ws) {
      ws.subscribe("chat")
      ws.send(JSON.stringify({ type: "connected" }))
    },
    message(ws, message) {
      // Broadcast to all subscribers
      ws.publish("chat", message)
    },
    close(ws) {
      ws.unsubscribe("chat")
    },
  },
})

Database — Bun.sql

PostgreSQL (Built-in, no driver needed)

import { sql } from "bun"

// Bun.sql uses tagged template literals — SQL injection safe
const users = await sql`SELECT * FROM users WHERE active = ${true}`

// With types
type User = { id: string; email: string; name: string }
const user = await sql<User[]>`
  SELECT id, email, name
  FROM users
  WHERE email = ${email}
  LIMIT 1
`

// Transactions
await sql.begin(async (tx) => {
  const [newUser] = await tx<User[]>`
    INSERT INTO users (email, name) VALUES (${email}, ${name})
    RETURNING *
  `
  await tx`
    INSERT INTO audit_log (user_id, action) VALUES (${newUser.id}, 'signup')
  `
  return newUser
})

// Configure connection
const db = new Bun.SQL({
  url: process.env.DATABASE_URL,
  max: 20,           // pool size
  idleTimeout: 30,   // seconds
})

SQLite (Zero-config, built-in)

import { Database } from "bun:sqlite"

const db = new Database("mydb.sqlite")

// Prepare statements (reuse for performance)
const getUser = db.prepare<{ id: number; name: string }, [string]>(
  "SELECT id, name FROM users WHERE email = ?"
)

const user = getUser.get("[email protected]")

// Transactions
const insertUser = db.prepare("INSERT INTO users (email, name) VALUES (?, ?)")
const insertLog = db.prepare("INSERT INTO logs (user_id) VALUES (?)")

const signup = db.transaction((email: string, name: string) => {
  const info = insertUser.run(email, name)
  insertLog.run(info.lastInsertRowid)
  return info.lastInsertRowid
})

const id = signup("[email protected]", "Bob")

Object Storage — Bun.s3

// Configure (auto-reads AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
const s3 = new Bun.S3Client({
  bucket: "my-bucket",
  region: "us-east-1",
  // Or use custom endpoint for R2/MinIO:
  endpoint: "https://xxx.r2.cloudflarestorage.com",
})

// Upload
await s3.write("uploads/avatar.png", imageBuffer, {
  type: "image/png",
  acl: "public-read",
})

// Download
const file = s3.file("uploads/avatar.png")
const buffer = await file.arrayBuffer()

// Presigned URL
const url = await s3.presign("uploads/avatar.png", {
  expiresIn: 3600, // 1 hour
  method: "GET",
})

// Delete
await s3.delete("uploads/old-avatar.png")

// List
const objects = await s3.list({ prefix: "uploads/" })

Testing — bun:test

// math.test.ts
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test"

describe("Calculator", () => {
  it("adds two numbers", () => {
    expect(1 + 2).toBe(3)
  })

  it("handles async operations", async () => {
    const result = await fetchData("https://api.example.com")
    expect(result).toMatchObject({ status: "ok" })
  })

  it("mocks functions", () => {
    const mockFetch = mock(() => Promise.resolve({ ok: true }))
    globalThis.fetch = mockFetch as any

    // test code that calls fetch...
    expect(mockFetch).toHaveBeenCalledTimes(1)
  })
})

// Snapshot testing
it("renders correctly", () => {
  const output = renderComponent()
  expect(output).toMatchSnapshot()
})
# Run tests
bun test

# Watch mode
bun test --watch

# Coverage
bun test --coverage

# Filter by name
bun test --test-name-pattern "Calculator"

# Specific file
bun test math.test.ts

Bundler

// build.ts
await Bun.build({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  target: "browser",    // or "node" or "bun"
  format: "esm",        // or "cjs" or "iife"
  splitting: true,      // code splitting
  minify: true,
  sourcemap: "external",
  define: {
    "process.env.NODE_ENV": JSON.stringify("production"),
  },
  plugins: [
    // Custom plugins (compatible with esbuild API)
  ],
})
# Build from CLI
bun build ./src/index.ts --outdir ./dist --minify

# Bundle to single file
bun build ./src/index.ts --outfile ./dist/bundle.js

Package Manager

# Install (fastest package manager)
bun install                    # install from package.json
bun add express                # add dependency
bun add -d @types/bun          # add devDependency
bun remove express             # remove
bun update                     # update all

# Run scripts
bun run dev
bun run build

# Execute files
bun index.ts                   # run TypeScript directly
bun --watch index.ts           # hot reload

# Workspaces
bun install                    # installs all workspace packages

bunfig.toml Configuration

[install]
registry = "https://registry.npmjs.org"
frozen = true  # like --frozen-lockfile

[run]
bun = true  # prefer bun over node for scripts

Bun Shell ($)

import { $ } from "bun"

// Run shell commands
const result = await $`ls -la`.text()

// Pipe
const count = await $`cat package.json | grep name`.text()

// Template with variables (auto-escaped)
const filename = "my file.txt"
await $`rm ${filename}`         // safe: rm "my file.txt"

// Capture output
const { stdout, stderr, exitCode } = await $`git status`.quiet()

// Write file
await $`echo "hello" > output.txt`

// Script mode
await $`
  mkdir -p dist
  bun build ./src/index.ts --outdir dist
  echo "Build complete"
`

Key Rules

  1. Use tagged template literals for SQL — never string concatenation (injection safe)
  2. bun:test not Jest — same API, 10x faster
  3. Bun.file() for file reads — lazy, streaming, faster than fs.readFile
  4. Response.json() not new Response(JSON.stringify()) — cleaner API
  5. Bun.serve error handler — always define error() for uncaught handler errors
  6. Pool connections — set max on Bun.SQL for production
  7. bun --watch for development — built-in hot reload
  8. TypeScript natively — no build step needed in development
  9. bun build for production — minify + tree-shake before deploying
  10. bunx instead of npx — runs package CLIs faster

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.