Bun Shell
Bun provides powerful shell scripting capabilities with template literals and spawn APIs.
Bun.$ (Shell Template)
Basic Usage
import
{
$
}
from
"bun"
;
// Run command
await
$
echo "Hello World"
;
// Get output
const
result
=
await
$
ls -la
.
text
(
)
;
console
.
log
(
result
)
;
// JSON output
const
pkg
=
await
$
cat package.json
.
json
(
)
;
console
.
log
(
pkg
.
name
)
;
Variable Interpolation
import
{
$
}
from
"bun"
;
const
name
=
"world"
;
const
dir
=
"./src"
;
// Safe interpolation (escaped)
await
$
echo "Hello
${
name
}
"
;
await
$
ls
${
dir
}
;
// Array expansion
const
files
=
[
"a.txt"
,
"b.txt"
,
"c.txt"
]
;
await
$
touch
${
files
}
;
Piping
import
{
$
}
from
"bun"
;
// Pipe commands
const
result
=
await
$
cat file.txt | grep "pattern" | wc -l
.
text
(
)
;
// Chain with JavaScript
const
files
=
await
$
ls -la
.
text
(
)
;
const
lines
=
files
.
split
(
"\n"
)
.
filter
(
line
=>
line
.
includes
(
".ts"
)
)
;
Error Handling
import
{
$
}
from
"bun"
;
// Throws on non-zero exit
try
{
await
$
exit 1
;
}
catch
(
err
)
{
console
.
log
(
err
.
exitCode
)
;
// 1
console
.
log
(
err
.
stderr
)
;
}
// Quiet mode (no throw)
const
result
=
await
$
exit 1
.
quiet
(
)
;
console
.
log
(
result
.
exitCode
)
;
// 1
// Check exit code
const
{
exitCode
}
=
await
$
grep pattern file.txt
.
quiet
(
)
;
if
(
exitCode
!==
0
)
{
console
.
log
(
"Pattern not found"
)
;
}
Output Types
import
{
$
}
from
"bun"
;
// Text
const
text
=
await
$
echo hello
.
text
(
)
;
// JSON
const
json
=
await
$
cat data.json
.
json
(
)
;
// Lines
const
lines
=
await
$
ls
.
lines
(
)
;
// Blob
const
blob
=
await
$
cat image.png
.
blob
(
)
;
// ArrayBuffer
const
buffer
=
await
$
cat binary.dat
.
arrayBuffer
(
)
;
Environment Variables
import
{
$
}
from
"bun"
;
// Set env for command
await
$
echo $MY_VAR
.
env
(
{
MY_VAR
:
"value"
}
)
;
// Access current env
$
.
env
.
MY_VAR
=
"value"
;
await
$
echo $MY_VAR
;
// Clear env
await
$
env
.
env
(
{
}
)
;
Working Directory
import
{
$
}
from
"bun"
;
// Change directory for command
await
$
pwd
.
cwd
(
"/tmp"
)
;
// Or globally
$
.
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
)
;
// "Hello World\n"
With Options
const
proc
=
Bun
.
spawn
(
[
"node"
,
"script.js"
]
,
{
cwd
:
"./project"
,
env
:
{
NODE_ENV
:
"production"
,
...
process
.
env
,
}
,
stdin
:
"pipe"
,
stdout
:
"pipe"
,
stderr
:
"pipe"
,
}
)
;
// Write to stdin
proc
.
stdin
.
write
(
"input data\n"
)
;
proc
.
stdin
.
end
(
)
;
// Read stdout
const
output
=
await
new
Response
(
proc
.
stdout
)
.
text
(
)
;
const
errors
=
await
new
Response
(
proc
.
stderr
)
.
text
(
)
;
// Wait for exit
const
exitCode
=
await
proc
.
exited
;
Stdio Options
// Inherit (use parent's stdio)
Bun
.
spawn
(
[
"ls"
]
,
{
stdio
:
[
"inherit"
,
"inherit"
,
"inherit"
]
}
)
;
// Pipe (capture output)
Bun
.
spawn
(
[
"ls"
]
,
{
stdin
:
"pipe"
,
stdout
:
"pipe"
,
stderr
:
"pipe"
}
)
;
// Null (ignore)
Bun
.
spawn
(
[
"ls"
]
,
{
stdout
:
null
,
stderr
:
null
}
)
;
// File (redirect to file)
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
// Synchronous execution
const
result
=
Bun
.
spawnSync
(
[
"ls"
,
"-la"
]
)
;
console
.
log
(
result
.
exitCode
)
;
console
.
log
(
result
.
stdout
.
toString
(
)
)
;
console
.
log
(
result
.
stderr
.
toString
(
)
)
;
console
.
log
(
result
.
success
)
;
// exitCode === 0
Shell Scripts
Shebang Scripts
!/usr/bin/env bun
import
{
$
}
from
"bun"
;
// Script logic
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..."
)
;
// Check for uncommitted changes
const
status
=
await
$
git status --porcelain
.
text
(
)
;
if
(
status
.
trim
(
)
)
{
console
.
error
(
"❌ Uncommitted changes found!"
)
;
process
.
exit
(
1
)
;
}
// Run tests
console
.
log
(
"🧪 Running tests..."
)
;
await
$
bun test
;
// Build
console
.
log
(
"🏗️ Building..."
)
;
await
$
bun run build
;
// Deploy
console
.
log
(
"📦 Deploying..."
)
;
await
$
rsync -avz ./dist/ server:/app/
;
console
.
log
(
"✅ Deployment complete!"
)
;
}
deploy
(
)
.
catch
(
(
err
)
=>
{
console
.
error
(
"❌ Deployment failed:"
,
err
)
;
process
.
exit
(
1
)
;
}
)
;
Parallel Commands
import
{
$
}
from
"bun"
;
// Run in parallel
await
Promise
.
all
(
[
$
npm run lint
,
$
npm run typecheck
,
$
npm run test
,
]
)
;
// Or with spawn
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"
;
// Pass through stdin
const
proc
=
Bun
.
spawn
(
[
"node"
]
,
{
stdin
:
"inherit"
,
stdout
:
"inherit"
,
stderr
:
"inherit"
,
}
)
;
await
proc
.
exited
;
Process Management
const
proc
=
Bun
.
spawn
(
[
"long-running-process"
]
)
;
// Kill process
proc
.
kill
(
)
;
// SIGTERM
proc
.
kill
(
"SIGKILL"
)
;
// Force kill
// Check if running
console
.
log
(
proc
.
killed
)
;
// Get PID
console
.
log
(
proc
.
pid
)
;
// Wait with timeout
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"
;
// Find files
const
files
=
await
$
find . -name "*.ts"
.
lines
(
)
;
// Search content
const
matches
=
await
$
grep -r "TODO" src/
.
text
(
)
;
// Archive
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