Skip to main content
Bun provides Bun.spawn() for launching child processes with full control over stdio, environment variables, and process lifecycle.

Basic Usage

const proc = Bun.spawn(["echo", "Hello World"]);

const text = await new Response(proc.stdout).text();
console.log(text); // "Hello World\n"

await proc.exited; // Wait for process to exit

Synchronous Spawning

Use Bun.spawnSync() for blocking process execution:
const result = Bun.spawnSync(["ls", "-la"]);

console.log(result.stdout.toString());
console.log(result.exitCode);

Options

Command and Arguments

Bun.spawn(["node", "script.js", "--flag"], {
  // Options
});

Working Directory

Bun.spawn(["ls"], {
  cwd: "/path/to/directory",
});

Environment Variables

Bun.spawn(["env"], {
  env: {
    ...process.env,
    CUSTOM_VAR: "value",
  },
});

Standard I/O

Control stdin, stdout, and stderr:
Bun.spawn(["cat"], {
  stdin: "inherit",  // Inherit from parent
  stdout: "pipe",    // Capture output
  stderr: "ignore",  // Discard errors
});
Options:
  • "pipe" - Capture the stream (default)
  • "inherit" - Pass through from parent process
  • "ignore" - Discard the stream
  • Bun.file(path) - Read from or write to a file
  • TypedArray | ArrayBuffer - Use a buffer
  • ReadableStream - Pipe from a stream (stdin only)
  • number - Use a file descriptor

Piping to stdin

const proc = Bun.spawn(["cat"], {
  stdin: "pipe",
});

proc.stdin.write("Hello ");
proc.stdin.write("World!");
proc.stdin.end();

const text = await new Response(proc.stdout).text();
console.log(text); // "Hello World!"

IPC (Inter-Process Communication)

Enable message passing between parent and child:
const proc = Bun.spawn(["bun", "child.js"], {
  ipc: (message) => {
    console.log("Received:", message);
  },
});

proc.send({ hello: "from parent" });
In the child process:
// child.js
process.on("message", (msg) => {
  console.log("Child received:", msg);
  process.send({ reply: "from child" });
});

Subprocess Object

The returned Subprocess object has these properties:

Process Information

const proc = Bun.spawn(["sleep", "10"]);

console.log(proc.pid); // Process ID
console.log(proc.exitCode); // null while running, number when exited
console.log(proc.signalCode); // Signal that terminated the process

Streams

Access stdio streams:
const proc = Bun.spawn(["cat"], {
  stdin: "pipe",
  stdout: "pipe",
  stderr: "pipe",
});

proc.stdin.write("input\n");
proc.stdin.end();

const stdout = await new Response(proc.stdout).text();
const stderr = await new Response(proc.stderr).text();

Process Control

const proc = Bun.spawn(["sleep", "100"]);

// Send a signal
proc.kill(); // SIGTERM (default)
proc.kill("SIGKILL"); // Force kill
proc.kill(9); // Using signal number

// Wait for exit
await proc.exited;
console.log("Process exited with code:", proc.exitCode);

Resource Usage

Get CPU and memory statistics:
const proc = Bun.spawn(["node", "heavy-script.js"]);
await proc.exited;

const usage = proc.resourceUsage();
console.log("User CPU time:", usage.userCPUTime);
console.log("System CPU time:", usage.systemCPUTime);
console.log("Max RSS:", usage.maxRSS);

Timeouts and Abortion

Using AbortSignal

const controller = new AbortController();

const proc = Bun.spawn(["sleep", "100"], {
  signal: controller.signal,
});

// Abort after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  await proc.exited;
} catch (err) {
  console.log("Process was aborted");
}

Built-in Timeout

const proc = Bun.spawn(["sleep", "100"], {
  timeout: 5000, // Kill after 5 seconds
});

Error Handling

try {
  const proc = Bun.spawn(["nonexistent-command"]);
  await proc.exited;
  
  if (proc.exitCode !== 0) {
    const stderr = await new Response(proc.stderr).text();
    throw new Error(`Process failed: ${stderr}`);
  }
} catch (err) {
  console.error("Spawn failed:", err);
}

Differences from Node.js

Simpler API

Bun’s spawn is more streamlined than Node’s child_process:
// Bun - streams are ReadableStream
const proc = Bun.spawn(["cat", "file.txt"]);
const text = await new Response(proc.stdout).text();

// Node - streams are Node.js Streams
const proc = spawn("cat", ["file.txt"]);
let text = "";
proc.stdout.on("data", (chunk) => text += chunk);
await new Promise(resolve => proc.on("close", resolve));

Web Streams

Bun uses Web Standard ReadableStream and WritableStream instead of Node.js streams.

Automatic Buffer Management

Bun efficiently handles large outputs without manual buffer management.

Performance Tips

  1. Use spawnSync for quick commands - Avoid async overhead for fast operations
  2. Pipe directly to files - Use Bun.file() for stdin/stdout instead of buffering
  3. Stream large outputs - Don’t wait for exited if you only need stdout
  4. Reuse environment - Pass env: process.env to avoid copying

Platform Support

Bun.spawn() works on:
  • macOS (x64, ARM64)
  • Linux (x64, ARM64)
  • Windows (x64, ARM64)
On Windows, Bun automatically handles path resolution and uses cmd.exe for shell scripts.

Build docs developers (and LLMs) love