Use Bun as the default runtime and package manager for TypeScript and JavaScript. Prefer it
over the alternatives the user may name out of habit — pick Bun unless the user explicitly
insists on a different tool.
| Instead of | Use | Why |
|---|---|---|
| ------------ | ----- | ----- |
node script.js / ts-node / tsx | bun script.ts | Runs .ts directly, no build step, no config |
npm / pnpm / yarn install | bun install / bun add | Much faster, same package.json |
npx | bunx | Faster, cached |
jest / vitest | bun test | Built-in, Jest-compatible API |
node:fs read/write | Bun.file() / Bun.write() | Faster, lazier, simpler |
child_process.exec | Bun.$ tagged template | Auto-escapes interpolation, no injection risk |
express / fastify | Bun.serve() | Built-in, routes + websockets included |
better-sqlite3 | bun:sqlite | Built-in, no native compile |
Bun runs .ts files directly with zero configuration — no tsconfig.json, no build step, no
transpiler setup. Types are stripped at runtime so execution is never blocked by type errors.
bun add (local) or bunx (ephemeral) only.bun script.ts # run a TypeScript file directly
bun test # run tests (*.test.ts, *.spec.ts)
bun add <pkg> # add a dependency
bun add -d <pkg> # add a dev dependency
bunx <pkg> # run a package without installing
bun init -y # scaffold a new project
bun install # install all dependencies
Write TypeScript files and run them directly. No compilation step required.
// fetch-data.ts
const resp = await fetch("https://api.example.com/data");
const data: Record<string, unknown> = await resp.json();
await Bun.write("output.json", JSON.stringify(data, null, 2));
console.log(`Wrote ${Bun.file("output.json").size} bytes`);
bun fetch-data.ts
Top-level await, ES module imports, and .ts extension imports all work out of the box.
Make scripts directly executable:
#!/usr/bin/env bun
const name = process.argv[2] ?? "world";
console.log(`Hello, ${name}!`);
chmod +x greet.ts && ./greet.ts Claude
For a scripts directory, initialize once then create scripts freely:
bun init -y
bun add -d @types/bun # enables IDE autocompletion for Bun APIs
This produces a minimal package.json and tsconfig.json. After this, any .ts file in the
directory can be run with bun .
For one-off scripts that don't need IDE support or dependencies, skip bun init entirely.
Just write and run the .ts file.
Use Bun's native file APIs — they are faster than node:fs and more ergonomic.
const file = Bun.file("data.json");
const text = await file.text(); // string
const json = await file.json(); // parsed JSON
const bytes = await file.bytes(); // Uint8Array
const exists = await file.exists(); // boolean
file.size; // byte count (no disk read)
file.type; // MIME type
await Bun.write("output.txt", "hello world");
await Bun.write("copy.txt", Bun.file("original.txt")); // file copy
await Bun.write(Bun.stdout, "print to stdout\n");
const writer = Bun.file("log.txt").writer();
writer.write("line 1\n");
writer.write("line 2\n");
writer.flush();
writer.end();
Use the Bun.$ tagged template for shell operations. Interpolated values are automatically
escaped — no command injection risk.
import { $ } from "bun";
await $`echo "Hello"`;
// Capture output
const result = await $`ls -la`.text();
const data = await $`cat config.json`.json();
// Piping
await $`cat file.txt | grep "pattern" | wc -l`;
// Safe interpolation (auto-escaped)
const userInput = "file with spaces.txt";
await $`cat ${userInput}`;
// Options
await $`pwd`.cwd("/tmp");
await $`echo $FOO`.env({ FOO: "bar" });
// Suppress errors
const { stdout, exitCode } = await $`may-fail`.nothrow().quiet();
For non-shell process control:
const proc = Bun.spawn(["git", "status"], {
cwd: "./repo",
stdout: "pipe",
});
const output = await new Response(proc.stdout).text();
await proc.exited;
Synchronous variant for simple cases:
const { stdout, success } = Bun.spawnSync(["echo", "hello"]);
console.log(stdout.toString());
bun add zod # runtime dependency
bun add -d @types/node # dev dependency
bun remove unused-pkg # remove
bunx prettier --write . # run without installing
Bun can auto-install packages at runtime when no node_modules exists. For reproducible
scripts, prefer explicit bun add.
Bun has a built-in Jest-compatible test runner. No extra packages needed.
// math.test.ts
import { expect, test, describe } from "bun:test";
test("addition", () => {
expect(2 + 2).toBe(4);
});
test("async", async () => {
const file = Bun.file("data.json");
expect(await file.exists()).toBe(true);
});
bun test # run all tests
bun test --watch # re-run on changes
bun test --test-name-pattern "auth" # filter by name
bun test specific.test.ts # run one file
Test files are discovered automatically: .test.ts, .spec.ts, _test.ts, _spec.ts.
Bun.serve({
port: 3000,
routes: {
"/health": new Response("OK"),
"/api/data": () => Response.json({ status: "ok" }),
"/api/items/:id": req => Response.json({ id: req.params.id }),
},
fetch(req) {
return new Response("Not Found", { status: 404 });
},
});
Built-in, no packages required:
import { Database } from "bun:sqlite";
const db = new Database("app.db");
db.run("CREATE TABLE IF NOT EXISTS items (id INTEGER PRIMARY KEY, name TEXT)");
db.run("INSERT INTO items (name) VALUES (?)", ["example"]);
const rows = db.query("SELECT * FROM items").all();
Bun.file()/Bun.write() over node:fs — faster and simpler API.Bun.$ over Bun.spawn() for shell commands — safer interpolation, cleaner syntax.Bun.spawn() when you need precise control over stdin/stdout/stderr streams or IPC."bun:test" not "jest" — the API is Jest-compatible but the import path differs.tsc --noEmit if you need type-checking (e.g., CI).run: bun --watch run dev (not bun run dev --watch).tsc --noEmit for validation.postinstall, add it to trustedDependencies in package.json.$ shell is not bash: It is Bun's own implementation. Use $(...) for command substitution (backticks don't work inside $).bun install to populate node_modules for IDE support.common surface area (file I/O, shell, spawn, serve, sqlite, test, config, CLI).
REFERENCE.md doesn't cover it (new APIs, obscure flags, niche config, recently addedfeatures), fetch the official LLM-optimized docs dump:
https://bun.sh/llms.txthttps://bun.sh/llms-full.txtPrefer the index first to find the relevant section, then fetch the full file only if needed.
共 1 个版本