| name | bun-shell |
| description | Bun shell scripting with Bun.$, Bun.spawn, subprocess management. Use for shell commands, template literals, or command execution. |
| license | MIT |
Bun Shell
Bun provides powerful shell scripting capabilities with template literals and spawn APIs.
Bun.$ (Shell Template)
Basic Usage
import { $ } from "bun";
await $`echo "Hello World"`;
const result = await $`ls -la`.text();
console.log(result);
const pkg = await $`cat package.json`.json();
console.log(pkg.name);
Variable Interpolation
import { $ } from "bun";
const name = "world";
const dir = "./src";
await $`echo "Hello ${name}"`;
await $`ls ${dir}`;
const files = ["a.txt", "b.txt", "c.txt"];
await $`touch ${files}`;
Piping
import { $ } from "bun";
const result = await $`cat file.txt | grep "pattern" | wc -l`.text();
const files = await $`ls -la`.text();
const lines = files.split("\n").filter(line => line.includes(".ts"));
Error Handling
import { $ } from "bun";
try {
await $`exit 1`;
} catch (err) {
console.log(err.exitCode);
console.log(err.stderr);
}
const result = await $`exit 1`.quiet();
console.log(result.exitCode);
const { exitCode } = await $`grep pattern file.txt`.quiet();
if (exitCode !== 0) {
console.log("Pattern not found");
}
Output Types
import { $ } from "bun";
const text = await $`echo hello`.text();
const json = await $`cat data.json`.json();
const lines = await $`ls`.lines();
const blob = await $`cat image.png`.blob();
const buffer = await $`cat binary.dat`.arrayBuffer();
Environment Variables
import { $ } from "bun";
await $`echo $MY_VAR`.env({ MY_VAR: "value" });
$.env.MY_VAR = "value";
await $`echo $MY_VAR`;
await $`env`.env({});
Working Directory
import { $ } from "bun";
await $`pwd`.cwd("/tmp");
$.cwd("/tmp");
await $`pwd`;
Bun.spawn
Basic Spawn
const proc = Bun.spawn(["echo", "Hello World"]);
const output = await new Response(proc.stdout).text();
console.log(output);
With Options
const proc = Bun.spawn(["node", "script.js"], {
cwd: "./project",
env: {
NODE_ENV: "production",
...process.env,
},
stdin: "pipe",
stdout: "pipe",
stderr: "pipe",
});
proc.stdin.write("input data\n");
proc.stdin.end();
const output = await new Response(proc.stdout).text();
const errors = await new Response(proc.stderr).text();
const exitCode = await proc.exited;
Stdio Options
Bun.spawn(["ls"], { stdio: ["inherit", "inherit", "inherit"] });
Bun.spawn(["ls"], { stdin: "pipe", stdout: "pipe", stderr: "pipe" });
Bun.spawn(["ls"], { stdout: null, stderr: null });
Bun.spawn(["ls"], {
stdout: Bun.file("output.txt"),
stderr: Bun.file("errors.txt"),
});
Streaming Output
const proc = Bun.spawn(["tail", "-f", "log.txt"], {
stdout: "pipe",
});
const reader = proc.stdout.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(new TextDecoder().decode(value));
}
Bun.spawnSync
const result = Bun.spawnSync(["ls", "-la"]);
console.log(result.exitCode);
console.log(result.stdout.toString());
console.log(result.stderr.toString());
console.log(result.success);
Shell Scripts
Shebang Scripts
#!/usr/bin/env bun
import { $ } from "bun";
const branch = await $`git branch --show-current`.text();
console.log(`Current branch: ${branch.trim()}`);
await $`npm test`;
await $`npm run build`;
chmod +x script.ts
./script.ts
Complex Script
#!/usr/bin/env bun
import { $ } from "bun";
async function deploy() {
console.log("🚀 Starting deployment...");
const status = await $`git status --porcelain`.text();
if (status.trim()) {
console.error("❌ Uncommitted changes found!");
process.exit(1);
}
console.log("🧪 Running tests...");
await $`bun test`;
console.log("🏗️ Building...");
await $`bun run build`;
console.log("📦 Deploying...");
await $`rsync -avz ./dist/ server:/app/`;
console.log("✅ Deployment complete!");
}
deploy().catch((err) => {
console.error(, err);
process.();
});
Parallel Commands
import { $ } from "bun";
await Promise.all([
$`npm run lint`,
$`npm run typecheck`,
$`npm run test`,
]);
const procs = [
Bun.spawn(["npm", "run", "lint"]),
Bun.spawn(["npm", "run", "typecheck"]),
Bun.spawn(["npm", "run", "test"]),
];
await Promise.all(procs.map(p => p.exited));
Interactive Commands
import { $ } from "bun";
const proc = Bun.spawn(["node"], {
stdin: "inherit",
stdout: "inherit",
stderr: "inherit",
});
await proc.exited;
Process Management
const proc = Bun.spawn(["long-running-process"]);
proc.kill();
proc.kill("SIGKILL");
console.log(proc.killed);
console.log(proc.pid);
const timeout = setTimeout(() => proc.kill(), 5000);
await proc.exited;
clearTimeout(timeout);
Common Patterns
Run npm/bun scripts
import { $ } from "bun";
await $`bun run build`;
await $`bun test`;
await $`bunx tsc --noEmit`;
Git Operations
import { $ } from "bun";
const branch = await $`git branch --show-current`.text();
const commit = await $`git rev-parse HEAD`.text();
const status = await $`git status --short`.text();
if (status) {
await $`git add -A`;
await $`git commit -m "Auto commit"`;
}
File Operations
import { $ } from "bun";
const files = await $`find . -name "*.ts"`.lines();
const matches = await $`grep -r "TODO" src/`.text();
await $`tar -czf backup.tar.gz ./data`;
Common Errors
| Error | Cause | Fix |
|---|
Command not found | Not in PATH | Use absolute path |
Permission denied | Not executable | chmod +x |
Exit code 1 | Command failed | Check stderr |
EPIPE | Broken pipe | Handle process exit |
When to Load References
Load references/advanced-scripting.md when:
- Complex pipelines
- Process groups
- Signal handling
Load references/cross-platform.md when:
- Windows compatibility
- Path handling
- Shell differences