Claude-skill-registry bun-runtime
Bun runtime patterns and best practices. Package management, bundling, testing, scripts. Use when working with Bun as the JavaScript runtime.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/bun-runtime" ~/.claude/skills/majiayu000-claude-skill-registry-bun-runtime && rm -rf "$T"
manifest:
skills/data/bun-runtime/SKILL.mdsource content
Bun Runtime - Fast JavaScript Runtime
Purpose
Expert guidance for Bun:
- Package Management - Fast installation
- Bundling - Built-in bundler
- Testing - Vitest-compatible runner
- Scripts - Task runner
- APIs - Bun-specific features
Package Management
Install Dependencies
# Install all dependencies bun install # Add dependency bun add zod mongoose # Add dev dependency bun add -D typescript @types/node # Add exact version bun add react@18.2.0 # Add from GitHub bun add github:user/repo # Remove dependency bun remove lodash # Update dependencies bun update # Update specific package bun update react
bunfig.toml
# bunfig.toml [install] # Disable postinstall scripts for security ignorescripts = true # Registry configuration registry = "https://registry.npmjs.org" # Install settings frozen-lockfile = true [run] # Shell for scripts shell = "bash"
Script Commands
package.json Scripts
{ "scripts": { "dev": "bun run --hot src/index.ts", "start": "bun run src/index.ts", "build": "bun build src/index.ts --outdir dist", "typecheck": "bunx tsc --noEmit", "lint": "bunx eslint . --ext .ts,.tsx", "lint:fix": "bunx eslint . --ext .ts,.tsx --fix", "test": "bun test", "test:watch": "bun test --watch", "test:coverage": "bun test --coverage" } }
Running Scripts
# Run script bun run dev bun run build # Shorthand (without "run") bun dev bun build # Run TypeScript directly bun run src/index.ts # Hot reload bun run --hot src/index.ts # Watch mode bun run --watch src/index.ts
Bundling
Basic Bundle
# Bundle for browser bun build ./src/index.ts --outdir ./dist # Minify bun build ./src/index.ts --outdir ./dist --minify # Source maps bun build ./src/index.ts --outdir ./dist --sourcemap # Target bun build ./src/index.ts --outdir ./dist --target=browser bun build ./src/index.ts --outdir ./dist --target=node bun build ./src/index.ts --outdir ./dist --target=bun
Build API
// build.ts const result = await Bun.build({ entrypoints: ['./src/index.ts'], outdir: './dist', target: 'browser', minify: true, sourcemap: 'external', splitting: true, format: 'esm', define: { 'process.env.NODE_ENV': '"production"', }, external: ['react', 'react-dom'], }); if (!result.success) { console.error('Build failed:'); for (const log of result.logs) { console.error(log); } process.exit(1); }
Testing (Vitest-compatible)
Test Configuration
// bunfig.toml [test]; preload = ['./tests/setup.ts']; coverage = true;
Test File
// tests/example.test.ts import { describe, test, expect, beforeEach, afterEach } from 'bun:test'; describe('Feature', () => { beforeEach(() => { // Setup }); afterEach(() => { // Cleanup }); test('should work correctly', () => { const result = 1 + 1; expect(result).toBe(2); }); test('async operations', async () => { const data = await fetchData(); expect(data).toBeDefined(); }); });
Mocking
import { mock, spyOn } from 'bun:test'; // Mock function const mockFn = mock((x: number) => x * 2); mockFn(5); expect(mockFn).toHaveBeenCalledWith(5); expect(mockFn).toHaveReturnedWith(10); // Spy on existing function const spy = spyOn(console, 'log'); console.log('test'); expect(spy).toHaveBeenCalledWith('test');
Bun APIs
File System
// Read file const text = await Bun.file('path/to/file.txt').text(); const json = await Bun.file('path/to/file.json').json(); const buffer = await Bun.file('path/to/file.bin').arrayBuffer(); // Write file await Bun.write('output.txt', 'Hello, World!'); await Bun.write('output.json', JSON.stringify({ hello: 'world' })); // File info const file = Bun.file('file.txt'); console.log(file.size); console.log(file.type);
HTTP Server
// Simple server Bun.serve({ port: 3000, fetch(request) { const url = new URL(request.url); if (url.pathname === '/api/hello') { return Response.json({ message: 'Hello!' }); } return new Response('Not Found', { status: 404 }); }, }); // With WebSocket Bun.serve({ port: 3000, fetch(request, server) { if (server.upgrade(request)) { return; } return new Response('Upgrade failed', { status: 500 }); }, websocket: { open(ws) { console.log('Client connected'); }, message(ws, message) { ws.send(`Echo: ${message}`); }, close(ws) { console.log('Client disconnected'); }, }, });
Subprocess
// Run command const result = Bun.spawn(['echo', 'Hello']); await result.exited; // Capture output const proc = Bun.spawn(['git', 'status'], { stdout: 'pipe', }); const output = await new Response(proc.stdout).text(); // With stdin const proc = Bun.spawn(['cat'], { stdin: 'pipe', stdout: 'pipe', }); proc.stdin.write('Hello from stdin!'); proc.stdin.end();
Password Hashing
// Hash password const hash = await Bun.password.hash('my-password', { algorithm: 'bcrypt', cost: 10, }); // Verify password const isValid = await Bun.password.verify('my-password', hash);
Environment Variables
// Access env vars const apiKey = Bun.env['API_KEY']; const nodeEnv = Bun.env['NODE_ENV'] ?? 'development'; // Set env vars Bun.env['CUSTOM_VAR'] = 'value';
Performance Tips
Use Native APIs
// Prefer Bun APIs over Node.js equivalents // File reading // Node.js way (slower) import { readFile } from 'fs/promises'; const content = await readFile('file.txt', 'utf-8'); // Bun way (faster) const content = await Bun.file('file.txt').text();
Import Optimization
// Use namespace imports for tree-shaking import * as z from 'zod'; // Avoid dynamic imports in hot paths // Bad: async function validate(data: unknown) { const { z } = await import('zod'); return z.object({}).parse(data); } // Good: import { z } from 'zod'; function validate(data: unknown) { return z.object({}).parse(data); }
Bundle for Production
# Compile to single executable bun build --compile ./src/index.ts --outfile myapp # Run compiled binary ./myapp
Docker Integration
# Use Bun official image FROM oven/bun:1-alpine AS base # Install dependencies FROM base AS deps WORKDIR /app COPY package.json bun.lockb ./ RUN bun install --frozen-lockfile # Build FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . RUN bun run build # Runtime FROM base AS runner WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/package.json ./ EXPOSE 3000 CMD ["bun", "run", "dist/index.js"]
Agent Integration
This skill is used by:
- bun-runtime-expert agent
- quality-checker for running tests
- build-error-fixer for build issues
- dockerfile-optimizer for Docker builds
FORBIDDEN
commands - Usenpm
insteadbun- Node.js fs when Bun.file works - Use native APIs
- Ignoring lockfile - Always use
in CI--frozen-lockfile - Skipping typecheck - Run
bunx tsc --noEmit
Version
- v1.0.0 - Initial implementation based on Bun 1.x patterns