Traces
TeamsDiscoverBlogDocsHelp
Sign in
All posts

Our Bun 1.4 Upgrade Made Traces 18% Faster

Traces Team
·Sep 23, 2026·4 min read

We recently chose to take advantage of Bun's infamous "Rust Rewrite" and migrate the Traces CLI from Bun v1.3.13 to v1.4.2. The result was an 18% faster CLI startup and 20% smaller memory footprint. The Traces CLI runs every time you start an agent session or publish a trace so you should feel this improvement the next time you run traces.

Where the speed and memory came from

The binary shrank because the Rust runtime is smaller on Linux. The memory gain comes from two changes in Bun 1.4. First, Bun moves JavaScriptCore allocation onto mimalloc. Second, Bun added a scavenger thread that returns memory to the operating system while JavaScript is idle.

Bun 1.3.13Bun 1.4.2Change
Binary Size137.6 MB117.1 MB-15%
traces --version startup118.6 ms97.8 ms-18%
traces --help startup132.8 ms109.5 ms-18%
traces --version peak memory69 MB55 MB-20%
traces --help peak memory86 MB66 MB-23%

Every invocation of the Traces CLI is now about 20 ms faster, uses a fifth less memory, and downloads 20 MB less on install.

Other changes in Bun 1.4.2

There were also three significant behaviours that changed between Bun 1.3.13 and Bun 1.4.2

File watching on macOS

Every Traces adapter uses fs.watch to follow an agent's transcript file, and our live view depends on those events arriving.

Previous Bun implementations ran two watchers per subscription on macOS, a kqueue watcher and FSEvents thread. Bun 1.3.14+ rewrote fs.watch on POSIX systems using FSEvents only, but FSEvents have known-silent failure modes.

In this setup, a watcher that silently stops delivering events looks exactly like an agent that stopped writing, and there is no way to ask whether it is still working. If we'd shipped the upgrade without checking, a fraction of our Mac users would have opened Traces during a live session and seen nothing, and had no error to explain why.

We ruled out trusting the watcher, because it can fail without telling us why. We ruled out polling everywhere, because that punishes Linux users for a macOS problem. We ruled out adding chokidar because we didn't want the native dependency.

Instead, we paired the FSEvents watcher with a poll. Four of our adapters already did this. The others now share one module, which stats the file every 500 ms and fires the same callback the watcher would fire if the modification time or size changed. We tested it by stubbing fs.watch to install cleanly and never fire a single event, and all adapter and core tests passed.

Grok

Grok's trust file stopped parsing. Grok lists trusted folders in trusted_folders.toml, and each entry has a decided_at field written as a signed 64-bit Unix timestamp. A JavaScript number cannot hold every 64-bit interger exactly, and Bun 1.4's Bun.TOML.parse now rejects the whole document instead of rounding, so one timestamp could block hook installation for every folder in the file.

Nothing in Traces reads decided_at, so we validate it as text and drop it before the parse. The scan checks that each value is a TOML integer within the signed 64-bit range and removes the line. A value that fails the check, or one our scan cannot reach such as an inline table, is an error, because it would reach the parser unvalidated.

Color codes

traces setup wrote color codes into piped output. Bun 1.3.13's node:util.styleText ignored NO_COLOR and the TTY check. We'd written a terminal-style module that asks Bun.enableANSIColors instead, and every plain command was supposed to use it.

Bun 1.4 fixed styleText, and the fix exposed the gap. The setup command still imported styleText directly for its intro, outro, and prompt help text, so its output followed a different rule than the rest of the CLI. We routed setup through the shared bold and dim helpers and gave its prompt formatter an explicit color flag so tests cover both styled and plain output.

The details matter

A runtime rewrite gives you performance without code changes, but the compatibility work isn't free. We'll take 18% faster and 20% lighter any day. But this upgrade also sharpened our awareness of what can go unseen in a runtime change. When you upgrade foundational tools, the gains can be real, but keep your eyes on the details along the way.

Contents

  • Where the speed and memory came from
  • Other changes in Bun 1.4.2
  • The details matter