This release fixes 69 issues (addressing 204 👍).
To install Bun
curl -fsSL https://bun.sh/install | bash
npm install -g bun
powershell -c "irm bun.sh/install.ps1|iex"
scoop install bun
brew tap oven-sh/bun
brew install bun
docker pull oven/bun
docker run --rm --init --ulimit memlock=-1:-1 oven/bun
To upgrade Bun
bun upgrade
Bun.SQL
- unified SQL client
You can now use Bun.SQL
to connect to MySQL/MariaDB, SQLite, and PostgreSQL. The same database library just works for the three most popular SQL databases, with zero dependencies.
MySQL & MariaDB in Bun.SQL
Bun's MySQL/MariaDB driver is written in Zig.

To get started, you can pass either an options object or a URL string to the SQL
constructor.
import { SQL } from "bun";
// Connect to a MySQL or MariaDB database
const sql = new SQL({
adapter: "mysql",
hostname: "127.0.0.1",
username: "user",
password: "password",
database: "buns_burgers",
});
// Run a query
const users = await sql`SELECT * FROM users;`.all();
console.log(users);
// or via url
const mysql = new SQL("mysql://user:password@127.0.0.1:3306/buns_burgers");
// Run a query
const users = await mysql`SELECT * FROM users;`;
console.log(users);
Thanks to @cirospaciari for the contribution
SQLite in Bun.SQL
Bun.SQL
now also has built-in SQLite support. This brings the same simple and performant tagged template literal API that was previously only available for PostgreSQL to SQLite users.
You can create an in-memory database by passing ":memory:"
or a file-based database by providing a path like sqlite://path/to/db.sqlite
.
import { SQL } from "bun";
// Create an in-memory SQLite database
const db = new SQL(":memory:");
// Create a table
await db`CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)`;
// Insert multiple users
const names = ["Alice", "Bob"];
await db`INSERT INTO users (name) VALUES ${SQL.values(
names.map((name) => [name]),
)}`;
// Query the users
const users = await db`SELECT * FROM users ORDER BY name ASC`;
console.log(users);
// => [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]
Thanks to @alii for the contribution!
Native YAML support
Bun now has a built-in YAML parser. You can import .yaml
and .yml
files directly, or parse YAML strings at runtime using Bun.YAML.parse
. This works just like Bun's built-in support for JSON and TOML.
In the next version of Bun
— Bun (@bunjavascript) August 23, 2025
Native YAML support comes to JavaScript
Import, bundle, require and parse YAML in JS as easily as JSON pic.twitter.com/5TYRLDoZgM
To import a YAML file, you can import
it as you would a JavaScript module. Bun will parse the file and export its contents as the default export.
name: my-package
version: 1.1.1
import pkg from "./package.yaml";
console.log(pkg.name); // "my-package"
console.log(pkg.version); // "1.1.1"
To parse a YAML string, use the Bun.YAML.parse
function.
import { YAML } from "bun";
const text = `
- item1
- item2
`;
const items = YAML.parse(text);
console.log(items); // [ "item1", "item2" ]
Thanks to @dylan-conway for the contribution!
500x faster postMessage(string)
Sending strings between workers using postMessage
and cloning strings with structuredClone
is now significantly faster.
Bun.secrets
- native secrets manager for CLI tools
Bun.secrets
securely stores and retrieves credentials using the operating system's native credential storage. This helps avoid storing sensitive data in plaintext files which is especially useful for CLI tools and local development.
It uses Keychain Services on macOS, libsecret
(GNOME Keyring, KWallet) on Linux, and the Windows Credential Manager. All operations (get
, set
, and delete
) are asynchronous and run in Bun's thread pool.
import { secrets } from "bun";
// Store a GitHub token securely
await secrets.set({
service: "my-cli-tool",
name: "github-token",
value: "ghp_xxxxxxxxxxxxxxxxxxxx",
});
// Retrieve it when needed
const token = await secrets.get({
service: "my-cli-tool",
name: "github-token",
});
// Or delete it later
await secrets.delete({
service: "my-cli-tool",
name: "github-token",
});
Security Scanner API for bun install
Bun's package manager can now scan packages for security vulnerabilities before installation, helping protect your applications from supply chain attacks and known vulnerabilities.
To enable this feature, install a security scanner package from npm and configure it in your bunfig.toml
. When a scanner is configured, bun install
will invoke it, and the installation will be cancelled if vulnerabilities with fatal
severity are found.
# bunfig.toml
[install.security]
# First, run `bun add -d @my-company/bun-security-scanner`
scanner = "@my-company/bun-security-scanner"
You can learn more about this API in our docs. For a quickstart on building a security scanner, see our template repository.
Thanks to @alii for the contribution!
bun audit
gets new filtering options
The bun audit
command now supports new flags for filtering vulnerabilities, giving you more control over your security audits.
--audit-level=<level>
: Only report vulnerabilities with a severity of<level>
or higher. The supported levels arelow
,moderate
,high
, andcritical
.--prod
: Restricts the audit to only production dependencies, ignoringdevDependencies
.--ignore=<CVE>
: Allows you to ignore specific vulnerabilities by their CVE ID. This flag can be used multiple times.
These flags make it easier to integrate bun audit
into CI/CD pipelines by allowing you to focus on the most critical security issues relevant to your application.
# Only report high and critical vulnerabilities
bun audit --audit-level=high
# Audit only production dependencies
bun audit --prod
# Ignore a specific vulnerability
bun audit --ignore CVE-2023-12345
# Ignore multiple vulnerabilities
bun audit --ignore CVE-2023-12345 --ignore CVE-2023-67890
Thanks to @RiskyMH for the contribution
bun install --lockfile-only
is much faster
The bun install --lockfile-only
command has been optimized to avoid downloading package tarballs from the npm registry. It now only fetches package manifests, which contain all the necessary information to generate or update bun.lock
.
This change significantly reduces network bandwidth usage and improves performance, especially in CI environments or for projects with many dependencies. For non-npm dependencies, such as direct tarball URLs or Git repositories, the tarballs are still downloaded to ensure the lockfile's accuracy.
bun update --interactive
supports scrolling
The interactive mode for bun update
(bun update -i
or bun update --interactive
) now supports scrolling. When the list of updatable dependencies exceeds the height of your terminal, you can use the up and down arrow keys to navigate the full list.
Additionally, the table display is now responsive to your terminal's width. Long package names will be truncated to ensure the layout remains clean and readable on smaller screens.
Thanks to @RiskyMH for the contribution
Reduced idle CPU usage
Previously, Bun.serve
would wake up every second to update a cached Date
header for HTTP responses. This caused Bun's process to use a small amount of CPU and trigger context switches, even when the server was completely idle or not even used at all.

Now, this timer is only active when there are in-flight requests. When a server is idle, Bun's process will now truly sleep, consuming virtually no CPU resources.
Bun.build()
now supports compiling executables
You can now create standalone executables with the Bun.build()
JavaScript API. This functionality, previously only available via the bun build --compile
CLI flag, is now accessible programmatically. Bundler plugins are also now fully supported when compiling an executable.
The new compile
option in Bun.build
accepts true
to build for the current platform, a target string like 'bun-linux-x64'
, or a configuration object for more advanced options.
// Cross-compile an executable for Linux x64 with musl
await Bun.build({
entrypoints: ["./cli.ts"],
// target can be a shorthand string where it uses entrypoint name as executable name
compile: "bun-linux-x64-musl",
});
// Or use an object for more configuration, like setting a custom filename and Windows icon
await Bun.build({
entrypoints: ["./cli.ts"],
compile: {
target: "bun-windows-x64",
outfile: "./my-app-windows",
windows: {
// set the icon for the .exe
icon: "./icon.ico",
},
},
});
Thanks to @RiskyMH for the contribution
Embed runtime flags into standalone executables with --compile-exec-argv
The bun build --compile
command now supports a new --compile-exec-argv
flag that lets you embed runtime arguments directly into a standalone executable.
When the compiled binary is executed, these arguments are processed by the Bun runtime as if they were passed on the command line. This allows you to create specialized builds with different runtime characteristics, such as enabling the inspector, setting a default user-agent, or optimizing for memory usage. The embedded arguments are also available for inspection via process.execArgv
.
// index.ts
console.log(`Bun was launched with: ${process.execArgv.join(" ")}`);
// This --user-agent flag is actually processed by Bun's runtime.
// All fetch requests will use this user-agent.
const res = await fetch("https://api.bunjstest.com/agent");
console.log(`User-Agent header sent: ${await res.text()}`);
You can build this file with embedded arguments.
bun build ./index.ts --compile --outfile=my-app \
--compile-exec-argv="--smol --user-agent=MyApp/1.0"
./my-app
Bun was launched with: --smol --user-agent=MyApp/1.0
User-Agent header sent: MyApp/1.0
Set metadata for Windows executables
You can now embed metadata into standalone executables for Windows using bun build --compile
. This allows you to set the application's title, publisher, version, description, and copyright, which will be visible in the file properties in Windows Explorer.
This is supported via a new set of CLI flags:
--windows-title
--windows-publisher
--windows-version
--windows-description
--windows-copyright
These options are also available in the Bun.build()
API via the compile.windows
object.
await Bun.build({
entrypoints: ["./app.js"],
outfile: "./app.exe",
compile: {
windows: {
title: "My Cool App",
publisher: "My Company",
version: "1.2.3.4",
description: "This is a really cool application.",
copyright: "© 2024 My Company",
},
},
});
Thanks to @RiskyMH for the contribution
Bun.stripANSI()
- SIMD-accelerated ANSI escape removal
Bun.stripANSI()
lets you strip ANSI escape codes from a string. It serves as a high-performance, built-in alternative to the strip-ansi
package from npm, running between 6x and 57x faster.
const coloredText = "\u001b[31mHello\u001b[0m \u001b[32mWorld\u001b[0m";
const plainText = Bun.stripANSI(coloredText);
console.log(plainText); // => "Hello World"
// Works with various ANSI codes
const formatted = "\u001b[1m\u001b[4mBold and underlined\u001b[0m";
console.log(Bun.stripANSI(formatted)); // => "Bold and underlined"
Thanks to @taylordotfish for the contribution!
Codesigned bun.exe
for Windows
bun.exe
for Windows is now code-signed, which resolves a security warning that could appear when running it for the first time.
Thanks to @connerlphillippi for the contribution!
bunx
now supports --package
You can now use the --package
(or -p
) flag with bunx
to run a binary from a package where the binary's name differs from the package's name. This is useful for packages that ship multiple binaries or for scoped packages. This brings bunx
's functionality in line with npx
and yarn dlx
.
For example, the renovate
package provides a renovate-config-validator
binary. You can now run it directly:
# Run the `renovate-config-validator` binary from the `renovate` package
bunx --package renovate renovate-config-validator
Similarly, to use the ng
binary from the @angular/cli
package:
# Run the `ng` binary from the `@angular/cli` package
bunx -p @angular/cli ng new my-app
Thanks to @RiskyMH for the contribution
package.json
sideEffects
now supports glob patterns
Bun's bundler now supports using glob patterns in the sideEffects
field of package.json
. This allows for more precise tree-shaking and can lead to smaller bundle sizes, especially when using component libraries that rely on this feature.
Previously, using a glob pattern would cause Bun to de-optimize the entire package. Now, Bun correctly identifies which files have side effects based on the provided patterns.
Supported patterns include *
, ?
, **
, []
, and {}
.
// package.json
{
"name": "my-package",
"sideEffects": ["**/*.css", "./src/setup.js", "./src/components/*.js"]
}
In the example above, Bun will correctly preserve all CSS files, src/setup.js
, and any JavaScript files directly inside src/components/
, while tree-shaking other modules if they are not used.
Thanks to @RiskyMH for the contribution
Customize User-Agent
with the --user-agent
flag
A new --user-agent
flag has been added to the Bun CLI. This allows you to override the default User-Agent
header for all HTTP requests made using fetch()
within your application. This is useful for identifying your application to external services or for APIs that require a specific User-Agent
.
const response = await fetch("https://httpbin.org/user-agent");
const data = await response.json();
console.log(data["user-agent"]);
# Run with a custom user agent
bun --user-agent "MyCustomApp/1.0" agent.js
MyCustomApp/1.0
# Without the flag, it uses the default
bun agent.js
Bun/1.2.18
Node.js compatibility improvements
- Fixed:
TypeError
when usingws
that could occur when a WebSocket upgrade is aborted or fails (server-side) - Fixed:
process.exit()
in a Worker now correctly notifies N-API callers that the VM is terminating, improving Node.js compatibility. - Fixed: assertion failure during process exit when using NAPI addons, such as
node-sqlite3
, that trigger garbage collection within their finalizers. - Fixed: assertion failure that could occur in native addons when
napi_is_exception_pending
is called from an object finalizer. - Fixed: assertion failure when reading a file with an odd number of bytes using
utf16le
orucs2
encoding. - Fixed: assertion failure when terminating a Worker that called
process.exit
. - Fixed: assertion failure when using N-API native addons like
lmdb
that attempt to remove a cleanup hook that has already been removed or was never added. Bun's behavior is now aligned with Node.js, which silently ignores this operation. - Fixed: bug in
child_process
that occurred when stdio streams were destroyed too quickly. Bun nowstream.Readable
andstream.Writable
instances just like Node.js. - Fixed: bug when
Error.prepareStackTrace
was called with anull
,undefined
, or other non-array value as the second argument. - Fixed: bug where exceptions thrown from N-API modules were propagated to JavaScript too quickly, which could lead to a crash.
- Fixed: bug where
readline.createInterface()
fromnode:readline/promises
did not implement[Symbol.dispose]
, preventing its use withusing
declarations. - Fixed: bugs in
structuredClone
where certain non-transferable objects were handled incorrectly. - Fixed: deadlock in
net.BlockList
that could occur when the same instance was accessed from multiple threads simultaneously. - Fixed: rare race condition in inter-process communication (IPC) that could lead to a crash when using
node:cluster
. - Fixed: regression in
node:crypto
where functions likecrypto.sign()
would fail when using lowercase algorithm names, such as'rsa-sha256'
. This improves compatibility with Node.js and fixes libraries likemailauth
.
Bundler & parser bugfixes
- Fixed: assertion failure in the JavaScript lexer when parsing an invalid template string in a JSX element, such as
<div a=\
`/>`. - Fixed: assertion failure in the CSS parser when bundling stylesheets with large floating-point values, such as those generated by TailwindCSS's
rounded-full
utility. - Fixed a bug where
String contains an invalid character
would be thrown when rendering multiple frontend errors in Bun's frontend development server.
Bun.SQL bugfixes
- Fixed: Bun.SQL error classes are all now exported, accessible under
Bun.SQL.PostgresError
,Bun.SQL.SQLiteError
andBun.SQL.MySQLError
. This allows for type-safe error handling likeerror instanceof Bun.SQL.PostgresError
. You can also use the superclass they all extend,Bun.SQL.SQLError
. - Fixed: Unix domain sockets would fail to connect when using PostgreSQL in certain configurations, often resulting in a
PostgresError: Connection closed
. sql(["a", "b", "c"])
now supports string arrays inWHERE IN
clauses. Thanks to @zenazn for the contribution.
bun install bugfixes
- Fixed: A UI flickering issue in
bun update --interactive
has been resolved, providing a smoother experience. - Fixed:
yarn.lock
migrations for packages with long version strings, such as those that include git commit SHAs - Fixed: assertion failure in Bun's logger that could occur when processing source locations.
- Fixed: assertion failure in
bun install
when parsing a malformed or oversized integrity hash in abun.lockb
file - Fixed: assertion failure that could occur when parsing a
package.json
with top-level catalog configurations. - Fixed: bug where
bun init
would listCLAUDE.md
twice in the summary of created files.
Runtime bugfixes
- Fixed: typo in the
bun upgrade
error message, which caused an extra closing parenthesis to be printed on verification failure, has been corrected. - Fixed:
Bun.hash.xxHash64
to correctly handleBigInt
seeds larger than 32-bits - Fixed:
Bun.serve()
would incorrectly reject atls
array with a single configuration object - Fixed: bug impacting Windows when using pipelines in
bun shell
($
) - Fixed: bug that could occur when calling
server.stop()
on aBun.serve
instance while requests were still being processed - Fixed: bug where
Bun.serve
would add aDate
header to an HTTP response even if one was already present, resulting in duplicateDate
headers - Fixed: crash in
HTMLRewriter
when an element handler throws an exception. This change also resolves a memory leak when parsing invalid CSS selectors and improves error messages for them. - Fixed: namespace import objects (
import * as ns from '...'
) incorrectly inherited fromObject.prototype
. Please let us know if this breaks anything - Improved internal exception handling in
bun:sqlite
expect(...).toBeCloseTo(...)
is now correctly counted in the total number of expect calls reported bybun test
.