Spawn a process (Bun.spawn())
Provide a command as an array of strings. The result of Bun.spawn() is a Bun.Subprocess object.
Bun.spawn is a parameters object that configures the subprocess.
Input stream
By default, the input stream of the subprocess is undefined; configure it with thestdin parameter.
| Value | Description |
|---|---|
null | Default. Provide no input to the subprocess |
"pipe" | Return a FileSink for fast incremental writing |
"inherit" | Inherit the stdin of the parent process |
Bun.file() | Read from the specified file |
TypedArray | DataView | Use a binary buffer as input |
Response | Use the response body as input |
Request | Use the request body as input |
ReadableStream | Use a readable stream as input |
Blob | Use a blob as input |
number | Read from the file with a given file descriptor |
"pipe", the parent process can incrementally write to the subprocess’s input stream.
ReadableStream to stdin pipes its data directly to the subprocess’s input:
Output streams
Read the subprocess’s output from thestdout and stderr properties. By default these are instances of ReadableStream.
stdout/stderr:
| Value | Description |
|---|---|
"pipe" | Default for stdout. Pipe the output to a ReadableStream on the returned Subprocess object |
"inherit" | Default for stderr. Inherit from the parent process |
"ignore" | Discard the output |
Bun.file() | Write to the specified file |
number | Write to the file with the given file descriptor |
Exit handling
Use theonExit callback to listen for the process exiting or being killed.
exited property is a Promise that resolves when the process exits.
bun process does not terminate until all child processes have exited. Use proc.unref() to detach the child process from the parent.
Resource usage
After the process exits,resourceUsage() reports its resource usage:
Using AbortSignal
You can abort a subprocess using anAbortSignal:
Using timeout and killSignal
Settimeout to terminate a subprocess after a duration in milliseconds:
SIGTERM. Specify a different signal with the killSignal option:
killSignal option also controls which signal is sent when an AbortSignal is aborted.
Using maxBuffer
ForBun.spawnSync, maxBuffer limits how many bytes of output the process can emit before Bun kills it:
Inter-process communication (IPC)
Bun supports a direct inter-process communication channel between twobun processes. To receive messages from a spawned Bun subprocess, specify an ipc handler.
.send() method on the returned Subprocess instance. The ipc handler also receives the sending subprocess as its second argument.
process.send() and receives them with process.on("message"). This is the same API used for child_process.fork() in Node.js.
child.ts
child.ts
serialization option controls the underlying communication format between the two processes:
advanced: (default) Messages are serialized using the JSCserializeAPI, which supports cloning everythingstructuredClonesupports. This does not support transferring ownership of objects.json: Messages are serialized usingJSON.stringifyandJSON.parse, which does not support as many object types asadvanceddoes.
IPC between Bun & Node.js
To use IPC between abun process and a Node.js process, set serialization: "json" in Bun.spawn. This is because Node.js and Bun use different JavaScript engines with different object serialization formats.
bun-node-ipc.js
Terminal (PTY) support
For interactive terminal applications, use theterminal option to spawn a subprocess with a pseudo-terminal (PTY) attached. The subprocess sees a real terminal, which enables colored output, cursor movement, and interactive prompts.
terminal option is provided:
- The subprocess sees
process.stdout.isTTYastrue stdin,stdout, andstderrare all connected to the terminalproc.stdin,proc.stdout, andproc.stderrreturnnull— use the terminal instead- Access the terminal via
proc.terminal
Terminal options
| Option | Description | Default |
|---|---|---|
cols | Number of columns | 80 |
rows | Number of rows | 24 |
name | Terminal type for PTY configuration (set the TERM env var separately with the env option) | "xterm-256color" |
data | Callback when data is received (terminal, data) => void | — |
exit | Callback when PTY stream closes (EOF or error). exitCode is PTY lifecycle status (0=EOF, 1=error), not subprocess exit code. Use proc.exited for process exit. | — |
drain | Callback when ready for more data (terminal) => void | — |
Terminal methods
TheTerminal object returned by proc.terminal has the following methods:
Reusable Terminal
To run multiple commands in sequence through the same terminal session, create a terminal independently and reuse it across subprocesses:Terminal object:
- The terminal can be reused across multiple spawns
- You control when to close the terminal
- The
exitcallback fires when you callterminal.close(), not when each subprocess exits - Use
proc.exitedto detect individual subprocess exits
Platform differences
Bun.Terminal uses openpty() on Linux and macOS, and ConPTY (CreatePseudoConsole) on Windows. The core behavior — child sees a TTY, write() reaches the child’s stdin, child output reaches the data callback, resize() updates the child’s view — is the same on every platform. A few details differ:
- No termios on Windows.
inputFlags,outputFlags,localFlags, andcontrolFlagsalways read as0and setting them is a no-op.setRawMode()records the flag but has no effect on the child; the child controls its own console mode. - No echo without a child process on Windows. On POSIX, the kernel line discipline echoes
write()input back to thedatacallback even with no process attached. ConPTY has no line discipline; input is buffered for the next reader. If you need echo, spawn a process that echoes. - ConPTY re-encodes output. ConPTY renders the child’s output to a virtual screen and emits whatever VT sequences describe the result, so the
datacallback receives semantically equivalent — but not byte-identical — escape sequences. Colors and text are preserved; cursor-positioning and reset sequences may be reordered or coalesced. ConPTY also emits a short VT init sequence (\x1b[?9001h\x1b[?1004h…) before any child output. - Input
\ris not translated to\non Windows. POSIXICRNLmaps carriage return to newline on input; ConPTY passes\rthrough unchanged. process.on('SIGWINCH')in the child does not fire under ConPTY unless the child is reading stdin in raw mode.process.stdout.columns/rowsdo update afterresize(). This is a libuv limitation that affects any libuv-based child (Node.js included).- On Windows before 11 24H2 (build 26100),
terminal.close()may not terminate a still-running child promptly becauseClosePseudoConsoleblocks until conhost has flushed its output through the pipe on those versions. Kill the attached process first if you need to tear down with a running child.
Blocking API (Bun.spawnSync())
Bun.spawnSync is the blocking equivalent of Bun.spawn. It supports the same inputs and parameters and returns a SyncSubprocess object, which differs from Subprocess in a few ways.
- It contains a
successproperty that indicates whether the process exited with a zero exit code. - The
stdoutandstderrproperties are instances ofBufferinstead ofReadableStream. - There is no
stdinproperty. UseBun.spawnto incrementally write to the subprocess’s input stream.
Bun.spawn API is better for HTTP servers and apps, and Bun.spawnSync is better for building command-line tools.
Benchmarks
⚡️
Bun.spawn and Bun.spawnSync use posix_spawn(3).spawnSync spawns processes 60% faster than the Node.js child_process module.
terminal
terminal
Reference
The following is a reference of the Spawn API and types. The real types have complex generics to strongly type theSubprocess streams with the options passed to Bun.spawn and Bun.spawnSync. For full details, see bun.d.ts.
See Typescript Definitions