new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Bun · Runtime · all subjects

bun apis/shell

44 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Shell command execution with $ API

Bun provides a $ API for shell command execution located at /runtime/shell.

bunfig.toml run.bun auto-alias setting

In the [run] section, bun is a boolean that when true, prepends $PATH with a node symlink pointing to the bun binary for all scripts invoked by bun run or bun. Scripts that run node run bun instead, working recursively and applying to shebangs. By default, this is enabled if node is not already in $PATH. Set to false to disable.

bunfig.toml run.shell setting values

In the [run] section, shell specifies which shell to use for package.json scripts with bun run or bun. Defaults to "bun" on Windows and "system" on other platforms. Valid values: "system" (use system shell) or "bun" (use Bun's shell).

bunfig.toml run.elide-lines setting

In the [run] section, elide-lines is the number of lines of script output shown per script when using --filter. Default is 10. Set to 0 to show all lines. Equivalent to the --elide-lines flag.

bunfig.toml run.noOrphans setting

In the [run] section, noOrphans is a boolean that when true, watches the process that spawned Bun and exits as soon as that parent goes away, even if force-killed. On exit, Bun terminates every descendant process so nothing it spawned outlives it. On Linux uses prctl(PR_SET_PDEATHSIG) and /proc walk; on macOS uses EVFILT_PROC/NOTE_EXIT on kqueue; on Windows uses thread-pool wait on parent handle and kill-on-close Job Object. Equivalent to --no-orphans flag or BUN_FEATURE_FLAG_NO_ORPHANS=1 environment variable.

bunfig.toml run.silent setting

In the [run] section, silent is a boolean that when true, suppresses bun run and bun from printing the command being run. Equivalent to prefixing bun run commands with --silent.

sh loader for Bun Shell scripts

The `sh` loader parses Bun Shell scripts, default for .sh files. It is only supported when starting Bun itself, so it is not available in the bundler or in the runtime. Usage: `bun run ./script.sh`.

Bun.$ global error handling with $.throws()

Call $.throws(boolean) on the $ function itself to set the default error handling for all shell commands. $.throws(false) is equivalent to $.nothrow(). $.throws(true) restores default behavior where non-zero exit codes throw.

Bun shell redirection operators

Bun Shell supports these redirection operators: < (stdin), > or 1> (stdout), 2> (stderr), &> (both stdout and stderr), >> or 1>> (append stdout), 2>> (append stderr), &>> (append both), 1>&2 (redirect stdout to stderr), 2>&1 (redirect stderr to stdout).

Bun shell redirect input from JavaScript objects

Redirect stdin from JavaScript objects using the < operator: Buffer, Uint8Array, Uint16Array, Uint32Array, Int8Array, Int16Array, Int32Array, Float32Array, Float64Array, ArrayBuffer, SharedArrayBuffer, Bun.file(path), Bun.file(fd), or Response. For example: `const response = new Response("hello"); const result = await $`cat < ${response}`.text();`

Bun shell piping with | operator

Pipe the output of one command to another using the | operator, like in bash. For example: `const result = await $`echo "Hello World!" | wc -w`.text();` returns '2\n'.

Bun shell command substitution with $(…)

Use the $(...) syntax for command substitution to insert the output of another command. For example: `await $`echo Hash of current commit: $(git rev-parse HEAD)`;` inserts the commit hash. Note: backtick syntax for command substitution does not work in Bun Shell.

Bun shell environment variables with template interpolation

Set environment variables using bash syntax. For example: `await $`FOO=foo bun -e 'console.log(process.env.FOO)'`;` or `const foo = "bar123"; await $`FOO=${foo + "456"} bun -e 'console.log(process.env.FOO)'`;` String interpolation is escaped by default, preventing shell injection attacks.

Bun shell .env() method sets environment variables

Call .env() on a command to set environment variables for that command only. For example: `await $`echo $FOO`.env({ ...process.env, FOO: "bar" });` Call $.env() globally to set default environment variables for all commands. Call $.env() with no arguments to reset to defaults.

Bun shell .cwd() method changes working directory

Call .cwd() with a string path to change the working directory for a single command. For example: `await $`pwd`.cwd("/tmp");` returns '/tmp'. Call $.cwd() globally to set the default working directory for all commands.

Bun shell .json() method parses output as JSON

Call .json() on a command to parse its output as JSON. For example: `const result = await $`echo '{"foo": "bar"}'`.json();` returns { foo: "bar" }.

Bun shell .lines() method reads output line by line

Call .lines() to read command output line by line. Returns an async iterable. For example: `for await (let line of $`echo "Hello World!"`.lines()) { console.log(line); }` You can also call .lines() on a completed command result.

Bun shell .blob() method returns output as Blob

Call .blob() on a command to get the output as a Blob object. For example: `const result = await $`echo "Hello World!"`.blob();` returns Blob(13) { size: 13, type: "text/plain" }.

Bun Shell builtin commands

Bun Shell implements these builtin commands for cross-platform compatibility: cd, ls (with -l flag support), rm, echo, pwd, bun, cat, touch, mkdir, which, mv, exit, true, false, yes, seq, dirname, basename. The mv command has partial implementation missing cross-device support.

Bun.$.braces() implements brace expansion

Call $.braces() to expand brace patterns. For example: `await $.braces(`echo {1,2,3}`);` returns ["echo 1", "echo 2", "echo 3"].

Bun.$.escape() escapes shell strings

Call $.escape() to escape a string for shell use. For example: `$.escape('$(foo) `bar` "baz"')` returns "\$(foo) \`bar\` \"baz\"". To skip escaping, wrap the string in { raw: 'str' } object.

Bun Shell implementation details

Bun Shell is a small programming language implemented in Rust with a handwritten lexer, parser, and interpreter. Unlike bash, zsh, and other shells, Bun Shell runs operations concurrently and does not invoke a system shell like /bin/sh.

Bun Shell command injection prevention

Bun Shell prevents command injection by treating all interpolated variables as single, literal strings. For example: `const userInput = "my-file.txt; rm -rf /"; await $`ls ${userInput}`;` treats userInput as a single string, so ls tries to read a directory named 'my-file.txt; rm -rf /'.

Bun Shell security with bash -c

When you explicitly invoke a system shell like bash -c, Bun's built-in injection protections no longer apply to strings interpreted by that new shell. For example: `const userInput = "world; touch /tmp/pwned"; await $`bash -c "echo ${userInput}"`;` is unsafe because bash -c will execute the touch command. User input passed this way must be rigorously sanitized.

Bun Shell argument injection vulnerability

Bun Shell cannot know how an external command interprets its own command-line arguments. An attacker can supply input formatted as command-line flags. For example: `const branch = "--upload-pack=echo pwned"; await $`git ls-remote origin ${branch}`;` is unsafe because git sees and acts upon the malicious flag. Always sanitize user-provided input before passing it as an argument to an external command.

Bun Shell features list

Bun Shell features: cross-platform (Windows, Linux, macOS) with native implementations of common commands; bash-like syntax with redirection, pipes, and environment variables; native glob patterns including **, *, and {expansion}; template literals that execute shell commands and interpolate variables; string escaping by default to prevent injection; JavaScript interop with Response, ArrayBuffer, Blob, Bun.file() as stdin/stdout/stderr; ability to run .bun.sh files; small programming language with its own lexer, parser, and interpreter written in Rust.

Bun Shell .sh file loader

Pass a .sh file to bun to run it as a shell script: `bun ./script.sh` or `bun .\script.sh` on Windows. Bun Shell scripts are cross-platform and work on Windows, Linux, and macOS.

Bun.$ shell template literal basic usage

Import the $ function from 'bun' and use it as a template literal tag to execute shell commands. For example: `import { $ } from "bun"; await $`echo "Hello World!"`;` executes the echo command.

Bun.$ .quiet() method silences output

Call .quiet() on a shell command to suppress output. For example: `await $`echo "Hello World!"`.quiet();` runs the command without printing to stdout.

Bun.$ .text() method returns output as string

Call .text() on a shell command to get the output as a string. The .text() method automatically calls .quiet() internally. For example: `const welcome = await $`echo "Hello World!"`.text();` returns 'Hello World!\n'.

Bun.$ default await returns stdout and stderr as Buffers

By default, awaiting a shell command without calling .text() or other output methods returns an object with stdout and stderr properties containing Buffers. For example: `const { stdout, stderr } = await $`echo "Hello!"`.quiet();` gives Buffer objects.

Bun.$ ShellError thrown on non-zero exit code

By default, a non-zero exit code throws a ShellError. The ShellError object contains exitCode, stdout, and stderr properties. For example: `try { await $`something-that-may-fail`.text(); } catch (err) { console.log(err.exitCode); }`

Bun.$ .nothrow() disables throwing on error

Call .nothrow() to prevent throwing on non-zero exit codes. Check the exitCode property of the result manually. For example: `const { exitCode } = await $`cmd`.nothrow().quiet();`

--watch mode restarts process on file changes

The --watch mode keeps track of all imported files and watches them for changes. When a file changes, Bun restarts the process with the same CLI arguments and environment variables as the initial run. If Bun crashes, --watch attempts to restart the process.

--watch mode works with bun test and code files

Watch mode works with bun test and when running TypeScript, JSX, and JavaScript files. Use 'bun --watch index.tsx' to run a file in watch mode, or 'bun --watch test' to run tests in watch mode.

--no-clear-screen flag in watch mode

The --no-clear-screen flag keeps Bun from clearing the terminal in watch mode, similar to TypeScript's --preserveWatchOutput. Use it when running multiple 'bun build --watch' commands at the same time with a tool like concurrently, where one instance clearing the screen could hide another's errors.

--watch-kill-signal option

Before each restart, bun run --watch runs the handlers your script registered for the kill signal (default SIGTERM, matching the signal Node.js sends its watched process). Use --watch-kill-signal to pick a different signal, e.g. 'bun --watch --watch-kill-signal SIGINT index.ts'.

--hot mode soft reloads without restarting process

The --hot mode enables hot reloading when executing code with Bun. Unlike --watch mode, Bun doesn't hard-restart the entire process. It detects code changes and updates its internal module cache with the new code.

--hot mode builds registry of imported source files

Starting from the entrypoint, Bun builds a registry of all imported source files (excluding those in node_modules) and watches them for changes. When a file changes, Bun performs a 'soft reload'. All files are re-evaluated, but global state (notably, the globalThis object) persists.

--hot mode with HTTP servers

You can update your HTTP request handler without shutting down the server: when you save the file, Bun reloads the server with the updated code without restarting the process, resulting in fast refresh speeds.

--hot mode implementation details

On hot reload, Bun resets the internal require cache and ES module registry (Loader.registry), runs the garbage collector synchronously (to minimize memory leaks), re-transpiles all code from scratch including sourcemaps, and re-evaluates the code with JavaScriptCore. This implementation re-transpiles files that haven't changed and makes no attempt at incremental compilation.

Bun uses native filesystem watchers for --watch mode

Bun uses the operating system's native filesystem watcher APIs, like kqueue or inotify, to detect file changes instead of relying on polling. Bun also applies optimizations to scale to larger projects, such as setting a high rlimit for file descriptors, statically allocating file path buffers, and reusing file descriptors when possible.

Example --hot mode with globalThis state

Example showing --hot mode with globalThis: declare global { var count: number; } globalThis.count ??= 0; console.log(`Reloaded ${globalThis.count} times`); globalThis.count++; setInterval(function () {}, 1000000);

Example --hot mode with HTTP server

Example showing --hot mode with HTTP server: globalThis.count ??= 0; globalThis.count++; Bun.serve({ fetch(req: Request) { return new Response(`Reloaded ${globalThis.count} times`); }, port: 3000, });

Give your agent this brain