We’re hiring C/C++ and Zig engineers to build the future of JavaScript!
Happy Holidays! We’re excited to release Bun v0.4.0 with support for more Node.js APIs, increased stability, lots of bug fixes, and a new command: bunx
.
Introducing bunx
This version introduces bunx
, Bun’s equivalent of npx
with 100x faster startup times. It runs executables from local or remote npm packages.
As with npx
, it will check for a locally installed package first, then fall back to auto-installing from npm into a shared global cache. With Bun’s fast startup times, it’s roughly 100x faster than npx
for locally installed packages.
Introducing bunx
auto-install & run an executable from npm
100x faster than npx
left: “bunx esbuild –version” (1k runs)
right: “npx esbuild –version” (1k runs) pic.twitter.com/pbgzfXyhnP— Jarred Sumner (@jarredsumner) December 23, 2022
The --bun
flag
By default, Bun respects the #!/usr/bin/env node
shebang at the top of scripts or executables that are run with bun run
or bunx
.
// foo.js
#! /usr/bin/env node
console.log(process.argv[0]);
$ bun run foo.js
/path/to/node/19.2.0/bin/node
To override this behavior, pass the --bun
flag. This temporarily aliases node
to bun
for the duration of the execution.
$ bun --bun run foo.js
/path/to/.bun/bin/bun
In the future, we might make this behaviour the default once Bun’s Node.js compatibility is more complete.

Node.js compatibility
Support for Node.js APIs continues to be a top priority for Bun. As of Bun v0.4.0, you can now use the following APIs:
crypto.timingSafeEqual()
crypto.scryptSync()
process.abort()
process.argv0
andprocess.execPath
node:util/types
Setup and teardown in bun:test
Bun has a built-in test runner that you can run using the command: bun wiptest
. You can now define Jest-style lifecycle hooks for the setup and teardown of tests.
import { beforeAll, test } from "bun:test";
let tests;
beforeAll(async () => {
const response = await fetch("https://example.com/path/to/resource");
tests = await response.json();
});
test("that integration tests are defined", () => {
expect(tests).toHaveLength(100);
});
Bun.deepEquals()
strict
You can now pass a strict
argument to Bun.deepEquals()
, which will have the same behaviour as expect().toStrictEqual()
.
const a = { entries: [1, 2] };
const b = { entries: [1, 2], extra: undefined };
Bun.deepEquals(a, b); // => true
Bun.deepEquals(a, b, true); // => false
bun pm
In case you missed it, Bun has a command that allows you see information about your packages and lockfile in a project: bun pm
.
bun pm ls
In Bun v0.4.0 there is new sub-command, bun pm ls
, which will list all the packages and versions in your project, similar to npm ls
.
Notable Fixes
- Fixed various issues when installing dependencies –
#1643
,#1647
,#1649
- Fixed various bugs with
node:stream
–#1606
,#1613
- Fixed
process.stdin
not working in atty
–#1611
,#1626
- Fixed
Bun.write()
on older Linux kernels that don’t supportio_uring
–e7a14f8
- Fixed an issue when importing a binary file –
5bbaa7
- Fixed a transpiler bug where
const {resolve} = require
would not work –3c2029
- Implemented support for passing arguments to
setTimeout()
,setInterval()
, andsetImmediate()
–a98e0ad
- Removed a work-around for RegExp backtracking support, since WebKit implemented it –
#1625
- Fixed a transpiler bug (in Bun) breaking
@babel/parser
when loading in Bun’s runtime
PR log
- fix
__require
collision from linking by @dylan-conway in#1585
- chore: add eslintcache by @Simon-He95 in
#1586
- Add filename completions on
bun
command to Zsh by @colinhacks in#1593
- Exclude additional TSdeclaration file extensions from completions by @colinhacks in
#1596
- fix path string by @YUxiangLuo in
#1597
- override
process.stdin.on()
correctly by @alexlamsl in#1603
- fix(stream): Fix Readable.pipe() by @ThatOneBro in
#1606
- make
process.stdin
work under TTY by @alexlamsl in#1611
- add
bun pm ls
for printing lockfiles by @dylan-con