Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8306480
bun run --filter: use original-case basename for workspace dirs (#29941)
Jarred-Sumner Oct 19, 2026
16ece2e
dotenv: keep $ literal before a digit (#36030)
Jarred-Sumner Oct 19, 2026
6b0a259
Suggest bounded fd limits in the fd-exhaustion error hints (#37339)
Jarred-Sumner Oct 19, 2026
960fe30
cli: read the script from stdin for `node -` in node emulation (#38566)
Jarred-Sumner Oct 19, 2026
cce7f7c
test: un-todo the process.env string coercion test on POSIX (#38864)
Jarred-Sumner Oct 19, 2026
868553d
crash handler: report failed Rust allocations as out of memory (#39635)
Jarred-Sumner Oct 19, 2026
2feba7e
output: keep a bare `>` in pretty templates instead of dropping it (#…
Jarred-Sumner Oct 19, 2026
9301e3a
bun run: print the package.json parse error instead of "Script not fo…
Jarred-Sumner Oct 19, 2026
f7f75a6
Do not forward the inherited IPC channel to spawned scripts and tools…
Jarred-Sumner Oct 19, 2026
82e6cec
cli: fix the `--no-module-preload` help text and two bunfig error mes…
Jarred-Sumner Oct 19, 2026
96ffb67
bun run: do not look for a system shell when --shell=bun runs the scr…
Jarred-Sumner Oct 19, 2026
0e0b3a8
run: run a package once when two "workspaces" entries match it (#43357)
Jarred-Sumner Oct 19, 2026
bfb8d14
docs: describe where bun build --compile --asset mounts a file or dir…
Jarred-Sumner Oct 19, 2026
5df28e4
cli: read `--conditions` for every command, so node emulation applies…
Jarred-Sumner Oct 19, 2026
d373fc5
bun patch --help: add --commit to the custom patches directory exampl…
Jarred-Sumner Oct 19, 2026
b941e92
Wake the event loop from the bun test --parallel and REPL signal hand…
Jarred-Sumner Oct 19, 2026
28a2f1a
macros: give each parse-worker macro VM its own env loader (#45960)
Jarred-Sumner Oct 19, 2026
10e0656
cli: port the rest of the chosen pull requests
Jarred-Sumner Oct 19, 2026
026a7e0
cli: keep released behavior where the ported changes went past it
Jarred-Sumner Oct 19, 2026
987af04
Merge remote-tracking branch 'origin/main' into claude/cli-consolidated
Jarred-Sumner Oct 19, 2026
aab462c
bunfig: compare owners on Windows too before reading a bunfig.toml ab…
Jarred-Sumner Oct 19, 2026
a775e73
Remove helpers that bun init's dead code was the last user of; pass C…
Jarred-Sumner Oct 19, 2026
f8a9f16
Review fixes: forward --jsx-side-effects to --parallel workers, compl…
Jarred-Sumner Oct 19, 2026
be203b5
isolated-install.test.ts: bun can wait for a lifecycle script when SI…
Jarred-Sumner Oct 19, 2026
04b8877
bunfig: the directory of a bunfig.toml above the cwd must have the cw…
Jarred-Sumner Oct 19, 2026
3e5cb94
Merge remote-tracking branch 'origin/main' into claude/cli-consolidated
Jarred-Sumner Oct 23, 2026
4f587bf
Merge remote-tracking branch 'origin/main' into claude/cli-consolidated
Jarred-Sumner Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion completions/bun-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -3885,7 +3885,7 @@
"examples": [
"bun patch jquery",
"bun patch --commit 'node_modules/jquery'",
"bun patch --patches-dir 'my-patches' 'node_modules/jquery'"
"bun patch --commit --patches-dir 'my-patches' 'node_modules/jquery'"
],
"usage": "Usage: bun patch [flags or options] <package>@<version>",
"documentationUrl": "https://bun.com/docs/install/patch.",
Expand Down
115 changes: 52 additions & 63 deletions completions/bun.bash
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
#/usr/bin/env bash

# adds the directories, and the files that match the pattern
_file_arguments() {
local extensions="${1}"
local reset=$(shopt -p globstar)
shopt -s globstar

if [[ -z "${cur_word}" ]]; then
COMPREPLY=( $(compgen -fG -X "${extensions}" -- "${cur_word}") );
else
COMPREPLY=( $(compgen -f -X "${extensions}" -- "${cur_word}") );
fi

$reset
local pattern="${1}";
local file;

while IFS= read -r file; do
if [[ -d "${file}" ]]; then
# a subcommand goes before a directory of the same name: `bun te<TAB>` gives `bun test `
[[ " ${COMPREPLY[*]} " == *" ${file} "* ]] || COMPREPLY+=( "${file}/" );
elif [[ "${file}" == ${pattern} ]]; then
COMPREPLY+=( "${file}" );
Comment thread
Jarred-Sumner marked this conversation as resolved.
fi
done < <(compgen -f -- "${cur_word}")

# no space after a directory, so that the next <TAB> lists what is in it
[[ "${#COMPREPLY[@]}" -eq 1 && "${COMPREPLY[0]}" == */ ]] && compopt -o nospace 2>/dev/null;
}

_long_short_completion() {
Expand Down Expand Up @@ -45,7 +47,7 @@ _read_scripts_in_package_json() {
local package_json_compreply;
local matched="${BASH_REMATCH[@]:1}";
local scripts="${matched%%\}*}";
scripts="${scripts//@(\"|\')/}";
scripts="${scripts//[\"\']/}";
readarray -td, scripts <<<"${scripts}";
for completion in "${scripts[@]}"; do
[[ "${completion}" =~ ^[[:space:]]*([[:alnum:]@/:._-]+)[[:space:]]*: ]] && package_json_compreply+=( "${BASH_REMATCH[1]}" );
Expand All @@ -56,8 +58,7 @@ _read_scripts_in_package_json() {
# when a script is passed as an option, do not show other scripts as part of the completion anymore
local re_prev_script="(^| )${prev}($| )";
[[
( "${COMPREPLY[*]}" =~ ${re_prev_script} && -n "${COMP_WORDS[2]}" ) || \
( "${COMPREPLY[*]}" =~ ${re_comp_word_script} )
( "${COMPREPLY[*]}" =~ ${re_prev_script} && -n "${COMP_WORDS[2]}" )
]] && {
local filtered_reply=();
local reply_word script_name keep;
Expand All @@ -69,17 +70,6 @@ _read_scripts_in_package_json() {
[[ -n "${keep}" ]] && filtered_reply+=( "${reply_word}" );
done
COMPREPLY=( "${filtered_reply[@]}" );
replaced_script="${prev}";
}
}


_subcommand_comp_reply() {
local cur_word="${1}"
local sub_commands="${2}"
local regexp_subcommand="^[dbcriauh]";
[[ "${prev}" =~ ${regexp_subcommand} ]] && {
COMPREPLY+=( $(compgen -W "${sub_commands}" -- "${cur_word}") );
}
}

Expand All @@ -90,9 +80,10 @@ _bun_completions() {
declare -A PM_OPTIONS;

local SUBCOMMANDS="dev bun create run install add remove upgrade completions discord help init pm x test repl update audit dedupe prune outdated publish link unlink build check lint fmt";
local RUNNABLE_FILES="*.@(js|mjs|cjs|ts|mts|cts|jsx|tsx|wasm|html)";

GLOBAL_OPTIONS[LONG_OPTIONS]="--use --cwd --bunfile --server-bunfile --config --disable-react-fast-refresh --disable-hmr --env-file --extension-order --jsx-factory --jsx-fragment --extension-order --jsx-factory --jsx-fragment --jsx-import-source --jsx-production --jsx-runtime --main-fields --no-summary --version --platform --public-dir --tsconfig-override --define --external --help --inject --loader --origin --port";
GLOBAL_OPTIONS[SHORT_OPTIONS]="-c -v -d -e -h -i -l -u -p";
GLOBAL_OPTIONS[LONG_OPTIONS]="--use --cwd --bunfile --server-bunfile --config --disable-react-fast-refresh --disable-hmr --env-file --extension-order --jsx-factory --jsx-fragment --extension-order --jsx-factory --jsx-fragment --jsx-import-source --jsx-production --jsx-runtime --main-fields --no-summary --version --platform --public-dir --tsconfig-override --define --external --help --inject --loader --origin --port --hot --watch --no-clear-screen --smol --bun --silent --preload --require --import --inspect --inspect-brk --inspect-wait";
GLOBAL_OPTIONS[SHORT_OPTIONS]="-c -v -d -e -h -i -l -u -p -b -r";

PACKAGE_OPTIONS[ADD_OPTIONS_LONG]="--development --optional --peer --save-prod --catalog --filter";
PACKAGE_OPTIONS[ADD_OPTIONS_SHORT]="-d -F";
Expand All @@ -116,13 +107,26 @@ _bun_completions() {
local cur_word="${COMP_WORDS[${COMP_CWORD}]}";
local prev="${COMP_WORDS[$(( COMP_CWORD - 1 ))]}";

# the subcommand or file: the first word that is not a flag or the value of one (`bun --hot run`, `bun --cwd dir run`)
local first_word="" i;
for (( i=1; i < COMP_CWORD; i++ )); do
case "${COMP_WORDS[i]}" in
# readline splits `--flag=value` and `K:V` at the `=` and the `:`
=|:) (( i++ ));;
--cwd|--env-file|--preload|--require|--import|--filter|--define|--loader|--port|--conditions|--tsconfig-override|-r|-F|-d|-l)
(( i++ )); [[ "${COMP_WORDS[i]}" == "=" ]] && (( i++ ));;
-*) ;;
*) first_word="${COMP_WORDS[i]}"; break;;
esac
done

case "${prev}" in
help|--help|-h|-v|--version) return;;
-c|--config) _file_arguments "!*.toml" && return;;
--bunfile) _file_arguments "!*.bun" && return;;
--server-bunfile) _file_arguments "!*.server.bun" && return;;
-c|--config) _file_arguments "*.toml"; return;;
--bunfile) _file_arguments "*.bun"; return;;
--server-bunfile) _file_arguments "*.server.bun"; return;;
--backend)
case "${COMP_WORDS[1]}" in
case "${first_word}" in
a|add|remove|rm|install|i|dedupe|update|up)
COMPREPLY=( $(compgen -W "clonefile copyfile hardlink clonefile_each_dir symlink" -- "${cur_word}") );
;;
Expand All @@ -132,7 +136,7 @@ _bun_completions() {
COMPREPLY=( $(compgen -W "dev optional peer" -- "${cur_word}") );
return;;
-F|--filter)
case "${COMP_WORDS[1]}" in
case "${first_word}" in
a|add|remove|rm|i|install|prune|update|up) return;;
esac
;;
Expand All @@ -159,8 +163,8 @@ _bun_completions() {
return;;
esac

case "${COMP_WORDS[1]}" in
help|completions|--help|-h|-v|--version) return;;
case "${first_word}" in
help|completions) return;;
add|a)
_long_short_completion \
"${PACKAGE_OPTIONS[ADD_OPTIONS_LONG]} ${PACKAGE_OPTIONS[ADD_OPTIONS_SHORT]} ${PACKAGE_OPTIONS[SHARED_OPTIONS_LONG]} ${PACKAGE_OPTIONS[SHARED_OPTIONS_SHORT]}" \
Expand Down Expand Up @@ -219,45 +223,30 @@ _bun_completions() {
COMPREPLY=( $(compgen -W "--help -h --eval -e --print -p --preload -r --smol --config -c --cwd --env-file --no-env-file" -- "${cur_word}") );
return;;
run)
_file_arguments "!(*.@(js|ts|jsx|tsx|mjs|cjs)?($|))";
COMPREPLY+=( $(compgen -W "--version --cwd --help --silent -v -h" -- "${cur_word}" ) );
_read_scripts_in_package_json;
COMPREPLY+=( $(compgen -W "--version --cwd --help --silent -v -h" -- "${cur_word}" ) );
_file_arguments "${RUNNABLE_FILES}";
return;;
pm)
_long_short_completion \
"${PM_OPTIONS[LONG_OPTIONS]} ${PM_OPTIONS[SHORT_OPTIONS]}";
COMPREPLY+=( $(compgen -W "bin ls licenses cache hash hash-print hash-string" -- "${cur_word}") );
return;;
*)
local replaced_script;
"")
_long_short_completion \
"${GLOBAL_OPTIONS[*]}" \
"${GLOBAL_OPTIONS[SHORT_OPTIONS]}"

_read_scripts_in_package_json;
_subcommand_comp_reply "${cur_word}" "${SUBCOMMANDS}";

# determine if completion should be continued
# when the current word is an empty string
# the previous word is not part of the allowed completion
# the previous word is not an argument to the last two option
[[ -z "${cur_word}" ]] && {
local prev_in_reply="";
local reply_word;
for reply_word in "${COMPREPLY[@]}"; do
[[ "${reply_word}" == "${prev}" ]] && { prev_in_reply=1; break; };
done
[[ -z "${prev_in_reply}" ]] && {
local re_prev_prev="(^| )${COMP_WORDS[(( COMP_CWORD - 2 ))]}($| )";
local global_option_with_extra_args="--bunfile --server-bunfile --config --port --cwd --public-dir --jsx-runtime --platform --loader";
[[
( -n "${replaced_script}" && "${replaced_script}" == "${prev}" ) || \
( "${global_option_with_extra_args}" =~ ${re_prev_prev} )
]] && return;
unset COMPREPLY;
}
[[ "${cur_word}" != -* ]] && {
COMPREPLY+=( $(compgen -W "${SUBCOMMANDS}" -- "${cur_word}") );
_file_arguments "${RUNNABLE_FILES}";
}
return;;
*)
_long_short_completion \
"${GLOBAL_OPTIONS[*]}" \
"${GLOBAL_OPTIONS[SHORT_OPTIONS]}"
[[ "${cur_word}" != -* ]] && _file_arguments "*";
return;;
esac

}
Expand Down
28 changes: 27 additions & 1 deletion completions/bun.fish
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ set -l bun_install_boolean_flags_descriptions "Write a yarn.lock file (yarn v1)"
set -l bun_builtin_cmds_without_run dev create help bun upgrade discord install remove add update audit dedupe prune publish init pm x repl check lint fmt
# The package manager commands and `bun x` reject a flag they do not have.
set -l bun_builtin_cmds_accepting_flags create help bun upgrade discord run init
set -l bun_cmds_without_files create c help upgrade discord install i ci add a remove rm update up audit dedupe prune pm x repl link unlink outdated why info exec completions

function __bun_complete_bins_scripts --inherit-variable bun_builtin_cmds_without_run -d "Emit bun completions for bins and scripts"
# Do nothing if we already have a builtin subcommand,
Expand Down Expand Up @@ -79,6 +80,9 @@ complete -e -c bun
# Dynamically emit scripts and binaries
complete -c bun -f -a "(__bun_complete_bins_scripts)"

# Complete files for `bun <file>`, `bun run <file>`, `bun test <file>` and the arguments of a script.
complete -c bun -n "not __fish_seen_subcommand_from $bun_cmds_without_files" -F

# Complete flags if we have no subcommand or a flag-friendly one.
set -l flag_applies "__fish_use_subcommand; or __fish_seen_subcommand_from $bun_builtin_cmds_accepting_flags"
complete -c bun \
Expand All @@ -92,7 +96,29 @@ complete -c bun \
complete -c bun \
-n $flag_applies --no-files -l 'use' -r -d 'Use a framework (ex: next)'
complete -c bun \
-n $flag_applies --no-files -l 'hot' -r -d 'Enable hot reloading in Bun\'s JavaScript runtime'
-n $flag_applies --no-files -l 'hot' -d 'Enable hot reloading in Bun\'s JavaScript runtime'
complete -c bun \
-n $flag_applies --no-files -l 'watch' -d 'Automatically restart the process on file change'
complete -c bun \
-n $flag_applies --no-files -l 'no-clear-screen' -d 'Disable clearing the terminal screen on reload when --hot or --watch is enabled'
complete -c bun \
-n $flag_applies --no-files -l 'smol' -d 'Use less memory, but run garbage collection more often'
complete -c bun \
-n $flag_applies --no-files -s 'b' -l 'bun' -d 'Force a script or package to use Bun\'s runtime instead of Node.js'
complete -c bun \
-n $flag_applies --no-files -l 'silent' -d 'Don\'t print the script command'
complete -c bun \
-n $flag_applies --no-files -l 'inspect' -d 'Activate Bun\'s debugger'
complete -c bun \
-n $flag_applies --no-files -l 'inspect-brk' -d 'Activate Bun\'s debugger, set breakpoint on first line of code and wait'
complete -c bun \
-n $flag_applies --no-files -l 'inspect-wait' -d 'Activate Bun\'s debugger, wait for a connection before executing'
complete -c bun \
-n $flag_applies -s 'r' -l 'preload' -r -d 'Import a module before other modules are loaded'
complete -c bun \
-n $flag_applies -l 'cwd' -r -d 'Absolute path to resolve files & entry points from'
complete -c bun \
-n $flag_applies -l 'env-file' -r -d 'Load environment variables from the specified file(s)'

# Complete dev and create as first subcommand.
complete -c bun \
Expand Down
8 changes: 6 additions & 2 deletions completions/bun.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ _bun() {
'help\:"Show all supported flags and commands" '
)
main_commands=($main_commands)
_alternative "$scripts" "args:command:(($main_commands))" "files:files:compadd -a files_list"
_alternative "$scripts" "args:command:(($main_commands))" "files:files:compadd -a files_list" "globbed-files:file:_files -g '*.(js|mjs|cjs|ts|mts|cts|jsx|tsx|wasm|html)'"

;;
args)
Expand Down Expand Up @@ -1375,6 +1375,10 @@ _bun() {
;;
esac

;;
*)
_files

;;
esac

Expand All @@ -1394,7 +1398,7 @@ _bun_run_param_script_completion() {

_alternative "scripts:scripts:compadd -a scripts_list"
_alternative "bin:bin:compadd -a bins"
_alternative "files:file:_files -g '*.(js|ts|jsx|tsx|wasm)'"
_alternative "files:file:_files -g '*.(js|mjs|cjs|ts|mts|cts|jsx|tsx|wasm|html)'"
}

_bun_link_param_package_completion() {
Expand Down
2 changes: 1 addition & 1 deletion docs/bundler/esbuild.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ In Bun's CLI, boolean flags like `--minify` take no argument. Flags that take on
| `--minify-syntax` | `--minify-syntax` | |
| `--out-extension` | n/a | Not supported |
| `--outbase` | `--root` | |
| `--preserve-symlinks` | n/a | Not supported |
| `--preserve-symlinks` | `--preserve-symlinks` | Applies to imports. An entry point that is a symlink is still resolved to its target |
| `--public-path` | `--public-path` | |
| `--pure` | n/a | Not supported |
| `--reserve-props` | n/a | Not supported |
Expand Down
6 changes: 3 additions & 3 deletions docs/bundler/executables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ BUN_OPTIONS="--smol --cpu-prof-md" ./myapp

## Automatic config loading

Standalone executables can automatically load configuration files from the directory where they are run. By default:
Standalone executables can automatically load configuration files from the directory where they are run. They do not search parent directories. By default:

- **`tsconfig.json`** and **`package.json`** loading is **disabled** — these are typically only needed at development time, and the bundler already uses them when compiling
- **`.env`** and **`bunfig.toml`** loading is **enabled** — these often contain runtime configuration that may vary per deployment
Expand Down Expand Up @@ -897,7 +897,7 @@ If you're using `@mapbox/node-pre-gyp` or similar tools, require the `.node` fil

### Embed directories

Use `--asset` (or `compile.assets` in the JavaScript API) to embed a file or directory tree into the executable under its original relative path. The embedded files live under `import.meta.dir` at runtime and are reachable via `node:fs` (`existsSync`, `statSync`, `readdirSync`, `readFileSync`) and `Bun.file()`.
Use `--asset` (or `compile.assets` in the JavaScript API) to embed a file or directory tree into the executable. Bun mounts each asset under its basename, next to the entry point: `--asset ./build/client` lands at `path.join(import.meta.dir, "client")`, and `--asset ./config/app.json` at `path.join(import.meta.dir, "app.json")`. The leading directories of the path you pass are dropped, and a directory keeps its internal tree. The embedded files are reachable via `node:fs` (`existsSync`, `statSync`, `readdirSync`, `readFileSync`) and `Bun.file()`.

<Tabs>
<Tab title="CLI">
Expand Down Expand Up @@ -931,7 +931,7 @@ for (const entry of fs.readdirSync(publicDir, { withFileTypes: true })) {
const html = await Bun.file(path.join(publicDir, "index.html")).text();
```

Pass `--asset` multiple times to embed several directories (for example `--asset ./client --asset ./prerendered` for a SvelteKit build). Bun embeds only regular files; it skips symlinks and empty subdirectories inside the tree.
Pass `--asset` multiple times to embed several directories (for example `--asset ./client --asset ./prerendered` for a SvelteKit build). Two assets with the same basename are merged into one directory (`--asset a/b --asset x/b` both land under `b/`). Two files that resolve to the same embedded path are an error. Bun embeds only regular files; it skips symlinks and empty subdirectories inside the tree.

You can also embed individual files via the `with { type: "file" }` import attribute or, for files that use the `file` loader (images, fonts, and so on) as well as `.wasm` and `.node` files, by adding them as extra entry points. Bun renames imported assets according to `--asset-naming` (default `[name]-[hash].[ext]`):

Expand Down
2 changes: 1 addition & 1 deletion docs/bundler/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,7 @@ A map of global identifiers to be replaced at build time. Keys of this object ar

### loader

A map of file extensions to built-in loader names. Use this to customize how certain files are loaded.
A map of file extensions to built-in loader names. Use this to customize how certain files are loaded. The empty extension (`""`, or `--loader :tsx` on the command line) is for files that have none.

<Tabs>
<Tab title="JavaScript">
Expand Down
Loading
Loading