June 11, 2025·4 min read·engineeringtypescriptbunworkspacesruntime

Bun 1.2.16 makes workspace dependency sources explicit

Bun 1.2.16 adds control over local workspace linking and extends outdated checks to catalog dependencies. Its runtime fixes show why Node compatibility includes object behavior and lifecycle details.

A workspace dependency can mean the package currently checked out beside an application or the version published in a registry. Those inputs can have different build requirements even when the package name is identical. Bun 1.2.16 gives that choice an explicit package-manager setting.

The June 11 release adds install.linkWorkspacePackages in bunfig.toml. Disabling it makes Bun install workspace dependencies from the registry instead of linking local copies. The default remains enabled, and explicit workspace:* references still request workspace behavior.

This is useful context for the release's broader combination of dependency tooling and runtime compatibility. Bun participates in both selecting an application's inputs and executing the resulting program. Small differences at either stage can affect an existing TypeScript project.

Local source and published packages are distinct inputs

The new configuration is short enough to show the policy directly. It changes ordinary workspace linking without overriding an explicit workspace protocol.

[install]
linkWorkspacePackages = false

The release notes identify CI as one motivation. Downloading a prebuilt package from a registry can avoid building its local source. That can be a useful arrangement when a job is intended to consume published outputs instead of validating all workspace source.

The choice also changes what the job establishes. A test using a published dependency does not validate uncommitted or unreleased changes in the local workspace package. Conversely, linking a local package can exercise source that ordinary downstream consumers have not received.

The explicit workspace:* exception prevents the broad setting from silently replacing a dependency whose declaration requires a local workspace package. That gives package-level intent precedence over the general linking preference.

I value TypeScript's framework ecosystem, but it makes dependency conventions an architectural concern. The quality of a web application depends partly on knowing which package implementation its tools selected. An explicit distinction between local and published inputs helps make that relationship reviewable.

Catalog checks follow shared version declarations

The release also extends bun outdated to catalog dependencies. This is support for an existing command's interaction with catalogs, not the introduction of the command itself.

A catalog centralizes version declarations in the workspace configuration. Member packages can refer to entries through catalog: instead of repeating a version range. An outdated report needs to follow that reference before it can compare the dependency with registry versions.

That is a package-manager concern with visible application consequences. A member package's dependency declaration may not contain the version range locally, but it still participates in an update policy. Tooling that stops at the member manifest misses the shared declaration.

The release demonstrates filtering the report to one workspace package. That makes the centralized policy inspectable from the context of a particular consumer. Centralizing versions should not require losing the ability to understand an individual package's dependencies.

Runtime compatibility includes accepted objects

One runtime fix provides a particularly clear example of behavioral compatibility. Bun's promise-based timer implementation previously rejected an AbortController passed as the options object because the object was not a plain object.

The relevant Node timer interface accepts an options object containing a signal for cancellation. An AbortController has a signal property, so the release notes explain that it can supply that property directly.

The following pattern now works in Bun. The promise rejects after cancellation, and the handler consumes that rejection.

import { setTimeout } from "node:timers/promises"

const controller = new AbortController()
const pending = setTimeout(100, undefined, controller)
controller.abort()

pending.catch(error => console.error(error))

The repair concerns structural behavior at runtime. Requiring one particular object shape or prototype beyond the intended contract can reject code that another implementation accepts. The release notes connect this correction to compatibility with certain Cloudflare Wrangler subcommands.

That is a useful reminder that matching exported names is only part of runtime compatibility. The implementation also has to accept the intended inputs and produce the expected lifecycle behavior. A type declaration cannot establish that the runtime validator behaves correctly.

Networking and cleanup receive separate repairs

Bun 1.2.16 includes a rework of node:net, adding passing Node tests and correcting connection callbacks, TLS upgrades, and custom methods on Socket subclasses. These changes concern how established abstractions behave under particular operations.

It also adds vm.SyntheticModule support and an HTTP parser binding using llhttp. Those capabilities affect tools that use module construction or Node HTTP internals. They extend compatibility in different areas, so the release's total passing-test count should not be read as a guarantee about every application path.

Memory fixes address N-API handle scopes and unread piped stdio from Bun.spawn. Both concern resources that can remain allocated after their useful work has ended. Their relevance depends on which native or subprocess paths a program exercises.

My interest in Bun is strongest when its convenience comes with clear semantics. This release makes one package-selection policy explicit and corrects several execution contracts. A workspace can choose registry inputs deliberately, while runtime users receive more faithful behavior for cancellation, networking, and resource cleanup.