Bun introduced something most JavaScript developers never expected — a built-in shell scripting language that runs cross-platform.
What is Bun Shell?
Bun Shell (Bun.$) is a cross-platform shell built into the Bun runtime. It lets you run shell commands using tagged template literals with full JavaScript interop.
Quick Start
import { $ } from "bun";
// Run any shell command
await $`echo Hello from Bun Shell!`;
// Capture output
const result = await $`ls -la`.text();
console.log(result);
// Use JavaScript variables seamlessly
const dir = "./src";
await $`find ${dir} -name "*.ts" | wc -l`;
Why Bun Shell Matters
1. Cross-Platform by Default
// This works on macOS, Linux, AND Windows
await $`echo $HOME`; // Uses Bun's built-in shell, not system shell
await $`cat file.txt | grep pattern`;
2. JavaScript Interop
const files = ["a.txt", "b.txt", "c.txt"];
for (const file of files) {
await $`cat ${file} >> combined.txt`;
}
// Pipe to JavaScript
const output = await $`curl -s https://api.example.com/data`.json();
console.log(output.results);
3. Error Handling
try {
await $`exit 1`;
} catch (err) {
console.log(err.exitCode); // 1
console.log(err.stderr.toString());
}
// Or use .nothrow() to suppress errors
const result = await $`maybe-missing-command`.nothrow();
if (result.exitCode !== 0) {
console.log("Command failed, but we handled it");
}
4. Piping and Redirects
// Pipe between commands
await $`cat data.json | jq .items[] | sort | uniq`;
// Redirect to file
await $`echo "Hello" > output.txt`;
await $`echo "World" >> output.txt`;
// Pipe to Response (for HTTP servers)
const server = Bun.serve({
fetch(req) {
return new Response($`cat large-file.txt`.stdout);
},
});
Real-World Use Cases
Build Scripts
// build.ts
import { $ } from "bun";
await $`rm -rf dist`;
await $`bun build ./src/index.ts --outdir ./dist`;
await $`cp -r public/* dist/`;
console.log("Build complete!");
Database Backup Script
import { $ } from "bun";
const date = new Date().toISOString().split("T")[0];
const dbUrl = process.env.DATABASE_URL;
await $`pg_dump ${dbUrl} | gzip > backups/db-${date}.sql.gz`;
await $`echo Backup created: backups/db-${date}.sql.gz`;
Dev Environment Setup
import { $ } from "bun";
// Check dependencies
await $`docker compose up -d`;
await $`bun install`;
await $`bun run db:migrate`;
await $`echo Dev environment ready!`;
Bun Shell vs Alternatives
| Feature | Bun Shell | zx (Google) | execa | child_process |
|---|---|---|---|---|
| Cross-platform | Yes | Partial | Yes | No |
| Template literals | Yes | Yes | No | No |
| Built-in (no install) | Yes | No | No | Yes |
| JavaScript interop | Native | Good | Good | Manual |
| Performance | Fast | Moderate | Good | Varies |
Performance
Bun Shell is significantly faster than spawning system shells because it uses Bun's built-in shell implementation. No fork/exec overhead for basic operations.
Building automation scripts for web scraping? Check out my ready-to-use scraping actors on Apify Store — get clean data in minutes without writing code. For custom solutions, email spinov001@gmail.com.
Top comments (0)