Features
- Cross-platform: works on Windows, Linux & macOS. Instead of
rimraf
orcross-env
’, you can use Bun Shell without installing extra dependencies. Common shell commands likels
,cd
,rm
are implemented natively. - Familiar: Bun Shell is a bash-like shell, supporting redirection, pipes, environment variables and more.
- Globs: Glob patterns are supported natively, including
**
,*
,{expansion}
, and more. - Template literals: Template literals are used to execute shell commands. This allows for easy interpolation of variables and expressions.
- Safety: Bun Shell escapes all strings by default, preventing shell injection attacks.
- JavaScript interop: Use
Response
,ArrayBuffer
,Blob
,Bun.file(path)
and other JavaScript objects as stdin, stdout, and stderr. - Shell scripting: Bun Shell can be used to run shell scripts (
.bun.sh
files). - Custom interpreter: Bun Shell is written in Zig, along with its lexer, parser, and interpreter. Bun Shell is a small programming language.
Getting started
The simplest shell command isecho
. To run it, use the $
template literal tag:
.quiet()
:
.text()
:
await
ing will return stdout and stderr as Buffer
s.
Error handling
By default, non-zero exit codes will throw an error. ThisShellError
contains information about the command run.
.nothrow()
. The result’s exitCode
will need to be checked manually.
.nothrow()
or .throws(boolean)
on the $
function itself.
Redirection
A command’s input or output may be redirected using the typical Bash operators:<
redirect stdin>
or1>
redirect stdout2>
redirect stderr&>
redirect both stdout and stderr>>
or1>>
redirect stdout, appending to the destination, instead of overwriting2>>
redirect stderr, appending to the destination, instead of overwriting&>>
redirect both stdout and stderr, appending to the destination, instead of overwriting1>&2
redirect stdout to stderr (all writes to stdout will instead be in stderr)2>&1
redirect stderr to stdout (all writes to stderr will instead be in stdout)
Example: Redirect output to JavaScript objects (>
)
To redirect stdout to a JavaScript object, use the >
operator:
Buffer
,Uint8Array
,Uint16Array
,Uint32Array
,Int8Array
,Int16Array
,Int32Array
,Float32Array
,Float64Array
,ArrayBuffer
,SharedArrayBuffer
(writes to the underlying buffer)Bun.file(path)
,Bun.file(fd)
(writes to the file)
Example: Redirect input from JavaScript objects (<
)
To redirect the output from JavaScript objects to stdin, use the <
operator:
Buffer
,Uint8Array
,Uint16Array
,Uint32Array
,Int8Array
,Int16Array
,Int32Array
,Float32Array
,Float64Array
,ArrayBuffer
,SharedArrayBuffer
(reads from the underlying buffer)Bun.file(path)
,Bun.file(fd)
(reads from the file)Response
(reads from the body)
Example: Redirect stdin -> file
Example: Redirect stdout -> file
Example: Redirect stderr -> file
Example: Redirect stderr -> stdout
Example: Redirect stdout -> stderr
Piping (|
)
Like in bash, you can pipe the output of one command to another:
Command substitution ($(...)
)
Command substitution allows you to substitute the output of another script into the current script:
Because Bun internally uses the special Instead of printing:The above will print out:We instead recommend sticking to the
raw
property on the input template literal, using the backtick syntax for command substitution won’t work:$(...)
syntax.Environment variables
Environment variables can be set like in bash:Changing the environment variables
By default,process.env
is used as the environment variables for all commands.
You can change the environment variables for a single command by calling .env()
:
$.env
:
$.env()
with no arguments:
Changing the working directory
You can change the working directory of a command by passing a string to.cwd()
:
$.cwd
:
Reading output
To read the output of a command as a string, use.text()
:
Reading output as JSON
To read the output of a command as JSON, use.json()
:
Reading output line-by-line
To read the output of a command line-by-line, use.lines()
:
.lines()
on a completed command:
Reading output as a Blob
To read the output of a command as a Blob, use.blob()
:
Builtin Commands
For cross-platform compatibility, Bun Shell implements a set of builtin commands, in addition to reading commands from the PATH environment variable.cd
: change the working directoryls
: list files in a directoryrm
: remove files and directoriesecho
: print textpwd
: print the working directorybun
: run bun in buncat
touch
mkdir
which
mv
exit
true
false
yes
seq
dirname
basename
mv
: move files and directories (missing cross-device support)
- See Issue #9716 for the full list.
Utilities
Bun Shell also implements a set of utilities for working with shells.$.braces
(brace expansion)
This function implements simple brace expansion for shell commands:
$.escape
(escape strings)
Exposes Bun Shell’s escaping logic as a function:
{ raw: 'str' }
object:
.sh
file loader
For simple shell scripts, instead of /bin/sh
, you can use Bun Shell to run shell scripts.
To do so, just run the script with bun
on a file with the .sh
extension.
script.sh
terminal
powershell
Implementation notes
Bun Shell is a small programming language in Bun that is implemented in Zig. It includes a handwritten lexer, parser, and interpreter. Unlike bash, zsh, and other shells, Bun Shell runs operations concurrently.Security in the Bun shell
By design, the Bun shell does not invoke a system shell (like/bin/sh
) and
is instead a re-implementation of bash that runs in the same Bun process,
designed with security in mind.
When parsing command arguments, it treats all interpolated variables as single, literal strings.
This protects the Bun shell against command injection:
userInput
is treated as a single string. This causes
the ls
command to try to read the contents of a single directory named
“my-file; rm -rf /”.
Security considerations
While command injection is prevented by default, developers are still responsible for security in certain scenarios. Similar to theBun.spawn
or node:child_process.exec()
APIs, you can intentionally
execute a command which spawns a new shell (e.g. bash -c
) with arguments.
When you do this, you hand off control, and Bun’s built-in protections no
longer apply to the string interpreted by that new shell.
Argument injection
The Bun shell cannot know how an external command interprets its own command-line arguments. An attacker can supply input that the target program recognizes as one of its own options or flags, leading to unintended behavior.Recommendation — As is best practice in every language, always sanitize user-provided input
before passing it as an argument to an external command. The responsibility for validating
arguments rests with your application code.