In fact using the word "rewrite" itself is pretty inaccurate.
As has been mentioned the goal was a port so they "could" eventually rewrite most of it to be idiomatic rust. The main benefit of this now is the compiler and being able to use these tools to fix issues that were already being hidden when it was in zig.
If you go into this codebase expecting to see idiomatic rust and get angry when it's not there, you are going in with the entirely incorrect attitude.
It's understandable how people see it as AI slop or whatever given the division among developers at the moment. But please see it for what it is instead of just jumping to conclusions.
They may have said that, but quite clearly the value they actually get out of it is getting the headline "AI reimplements complex, broadly used software in 2 weeks, but makes it way better because it's rust now" in front of a million people's eyes, only 1% of whom will ever find out it was mostly fluff
This is entirely disingenuous. Jarred has already made it clear what value they get out of moving off of Zig. Yes they used AI heavily to attempt this goal but I don't see what the big issue is. They haven't even released it yet and Anthropic themselves have said 0 about this.
The "headlines" thus far are really just people completely uninvolved with Bun and with all to gain by perpetrating "AI BAD".
My honest take: the big issue isn't "what if it goes wrong" its the fear that a migration of this size works out of the box and being done almost entirely by AI.
I wonder what are the real legitimate use-cases for "unsafe" in the first place, it is there for a reason?
In my application I'm able to guarantee that there is no modification to the backing file by making them read-only and ensuring nobody messes with them, but that guarantee exists outside of rust. So -- unsafe with a big SAFETY comment explaining the requirements if you use it.
Much rust code will never use unsafe. Systems code is likely to use a bit but also to know what it's doing.
Things like this port of bun are unusual and presumably transitory on the way to an implementation with minimal use of unsafe.
I think they shat over the community who trusted them by trying to advertise their owner company
The code they are complaining about is not safe code, it is unsafe code that exposes a supposedly but not actually safe interface. They demonstrate this by using the interface to get undefined behavior.
You can see this rather directly by how miri points to the exact line of unsafe code that results in undefined behavior (which isn't something miri can always do, but it can in this instance).
Jarred is an exceptional 1% engineer, and its likely he can succeed at this port, to the detriment of naysayers who don't believe there's any chance it's possible.
Step 2: Purchase an entire company for a product that, if you squint, might help paper over the entirely predictable problems that arise from using the wrong tools to implement the wrong architecture, because surely the solution isn’t reevaluating your original engineering choices.
Step 3: Perform a buggy, vibe-code rewrite of the tool you just bought. A tool you only need because — for whatever internal political reasons — sunk cost means you can only keep digging.
Step 4: ???
What matters more is if it does what you want it to do, and is well maintained.
1 week turnaround I guess is what they meant.
Will definitely use that going forward
Didn't find anything on my existing vibecoded rust projects but can't hurt
- Its a throw thing at the wall and see what sticks situation
- LLMs will improve*
- Using LLMs in an agentic way will improve (git worktrees, sliced PRs, spec driven steps)
So what happened here is a mess, but you gotta break a few eggs to make a souffle.
It's a learning step and I am glad it happened, there will be so many things to debrief from this.
I don't use Bun or Rust but fair play to them having a punt.
<Shameless plug> I have been working with Claude code to spec out and bring back to life a Spring Boot starter library for Apache Solr search
https://github.com/tomaytotomato/spring-data-solr-lazarus
There were a few points I had to steer it but the result has been a good implementation.
What would have been significantly better is just rewriting Claude in a language that's actually well suited to what it's doing in the first place (which could well be Rust, Codex is written in it as prior art). It's funny how the vibe coding promoters are keen on things like this, rewriting other codebases as fast as possible with little quality checking, but they are still defensive of their own code.
I guess they can just hook up the agent to Miri checks and let it grind away, and see what happens.
Strong deja-vu about that time Cursor tried to slop together a browser and tried to bury dissent when people pointed out how hilariously terrible the whole thing was.
I don't see what the big deal is here.
architector4@AGOGUS:/tmp$ git clone --depth=1 'https://github.com/oven-sh/bun' Cloning into 'bun'... … architector4@AGOGUS:/tmp$ cd bun/ architector4@AGOGUS:/tmp/bun$ find -type f -name '*.rs' -exec grep unsafe {} \; | grep -v '//' | wc -l 13255
....Thirteen thousand two hundred and fifty five lines without comments with the word "unsafe" in them in Rust code files across this rewrite.
This is so gross.
I'm a founder of an early-stage startup. I built a precision-editing tool system (called HIC Mouse). It provides coordinate-based addressing, staged batching with atomic rollback, embedded agent guidance, and more. It works well, it's available on VS Code Marketplace, and I've worked for a year and am still grinding every day, working so hard, just to get people to think about trying it, and to get attention paid to it. I did rigorous, careful benchmark research to make sure I wasn't just fooling myself. I incorporated, built a sales pipeline, changed my life by taking a chance and launching a business, and I pound the pavement and toil in obscurity every day and night, trying so hard to get interest in my product. I check every diff painstakingly before committing. I may make tools for AI agents but I am unbelievably careful about reviewing and thoroughly testing their code, and usually rather ruthlessly editing quite a bit further beyond any initial version drafted, long before deciding it is good enough to ship. I take enormous pains to get things right and worry constantly about whether I'm doing enough to make HIC Mouse secure and performant for my users. All I want is to make my users happier and to give them a genuine way to get "surgical, precise edits" that "don't touch the other lines", like we all ask of our AI agents over and over all day if we're using AI.
Or maybe not. Here we have Bun. Who cares about 90K GitHub Stars and massive community engagement -- just go crap all over them, all at once, with this AI tripe that you obviously neither tested in any meaningful manner, nor documented, nor read, I am assuming, before merging the whole bloated mess to production. What a disgraceful way to treat your users! I would be so grateful if I had a tiny fraction of the interest in my project that the Bun team has. I could never imagine shipping this garbage in a million years.
I'm sorry to vent but this just isn't defensible. It's the very worst of AI. I'm not going to wish ill on Bun, but it just makes me sad that I spend so much effort, work so hard to do things right, and painstakingly review everything because it's not just me any more and I do have folks who depend on my code being reliable and secure. And meanwhile, Bun just gives a huge middle finger to 90k+ starred supporters not to mention the millions of users who didn't click on the star but rely on the library, by acting this disrespectfully and disgracefully towards their own users. How they didn't take one look at this and promptly revert and apologize is simply beyond me. Again, sorry to vent, but this made me irrationally mad.
In this context "UB" means something different than how you're using it. The UB being mentioned here is the "nasal demons" form, i.e., programs which contain undefined behavior have no defined meaning according to the language semantics.
What you're talking about is probably better described in this context as "unspecified behavior", which is behavior that the language standard does not mandate but does not render programs meaningless. For example, IIRC in C++ the order in which g(), h(), and i() are evaluated in f(g(), h(), and i()) is unspecified - an implementation can pick any order, and the order doesn't have to be consistent, but no matter the order the program is valid (approximately speaking).
Those "dark corners" come into the picture when you decide you want a General Purpose language.
When your program might actually intend to respond to emails by executing the x86-64 machine code squirrelled away inside this logo PNG and running the output as SQL on your customer database, it's not possible for the language to ensure that programs which weren't intended to do that can't do that, how would they know? The translator isn't a mind reader, your intent is unreadable.
I think we should use general purpose languages much less often, the industry doesn't seem to agree, the results are obvious for everyone to see.
Rust has a subset, "safe Rust" which isn't a fully general purpose language but deliberately shares its syntax with a larger unsafe Rust you can use when it turns out that you needed it. Safe Rust doesn't have UB.
And it's not like Bun when written in Zig has been a beacon of stability either. It has been segfaults all over the place.
Unsafe Rust allows you to tell the compiler “hold my beer”. It’s a concession to the reality that the normal restrictions of Rust disallow some semantically valid programs that you might otherwise want to write. The safeguards work great in most cases, but in some they’re overly restrictive.
In practice, the overwhelming majority of code is able to be written in safe Rust and the compiler can have your back. The majority of the rest is for performance reasons, interacting with external functions like C libraries over FFI, or expressing semantics that safe Rust struggles with (e.g., circular references).
But they got bought out. By the tech equivalent of private equity. Every community in the USA & in most of the world is aware what happens when the friendly neighborhood business you've supported & relied on sells.
This is an old & systemic capitalistic phenomenon more than it is anything specific to AI. Hopefully someday we can figure out a real solution.
So this "unspecified behavior" might turn into the more nasal demon type when g(), h() and i() share mutable state and assume some particular sequential order of execution. No?
But sure, if you're writing C++ and (for example) g is depended on for initialization of pointed memory that the other two consume you could end up with UB. But if you're writing Java then no, you will not end up with UB just buggy code.
I take issue with the phrasing of OP's title: "allows for UB in safe rust". AFAIK there are compiler bugs that allow UB in safe Rust, but this is not what is happening here. We have UB in an unsafe block (which is to be expected) which enables an issue outside in safe code. What is your opinion? Is calling this "UB in safe Rust" justified?
This is a bug in the library, namely in Bun's PathString implementation. The bug is a soundness issue, precisely because usage of Bun's PathString implementation allows for UB in safe rust. Now this buggy library isn't that big of a concern for the community, because Bun is the only consumer. It's not also an indication of a compiler bug, because Bun's library is implemented using unsafe rust. But the fundamental issue is that usage of Bun's PathString implementation allows for UB in safe rust, and is therefore (clearly) unsound.
The UB is† always in the Unsafe Rust, but that's not necessarily a problem, the problem was that we caused it from our safe Rust and that's definitely not OK.
† Soundness bugs are known to exist in Rust, but for the known ones you have to be really asking for it, so it's not plausible that they'd impact you by accident.
Later, the garage enters otherwise safe machinery and triggers UB. UB has now happened in safe rust as a result of my earlier contractual violation.
You can extend this example to other scenarios where UB in unsafe begets further UB in safe later on.
fn safe_function(...) -> (...) {
// do unsafe things here
}then `safe_function` can be called from safe code, and still trigger UB. This wouldn't be a soundness issue in the rust compiler, but instead a bug in safe_function.
There are many reasons you might want to do that. In particular, it's very common in rust to have a library define some data structure that uses unsafe under-the-hood, but checks whatever invariants it needs to, and provides solely safe methods to external callers. Rust's `String` type is like this: it's (roughly) a `Vec<u8>`, e.g. heap-allocated bytes. It has the additional invariant that these bytes correspond to valid UTF8 though. See for example `push_str_slice`, which (roughly) concatenates 2 strings.
https://doc.rust-lang.org/src/alloc/string.rs.html#1107
It does the following thing
1. reserve enough space for the concatenated string within the source string 2. does some pointer arithmetic and a call to Rust's equivalent to `memcpy` (unsafe) 3. re-casts this pointer to a string object without checking that it's valid utf8 (unsafe).
While these individual calls are unsafe, `push_str_slice` checks that in this particular situation they are safe, so the stdlib authors do not mark `push_str_slice` as unsafe. It has no invariants that must be maintained by external callers.
Here's some links on this topic which have some examples:
https://doc.rust-lang.org/nomicon/working-with-unsafe.html https://www.ralfj.de/blog/2016/01/09/the-scope-of-unsafe.htm...
Maybe its better to think about this in the reverse, where C and C++ has 'defined behavior', but unsafe rust intentionally does not, its just whatever the complier and platform lets you get away with. Ultimately its still just a computer which stores values in memory and jumps to subroutines.
Undefined behavior is everything else. C and C++ are relatively unique in that their standards explicitly say "combining these constructs in this way is undefined", and we call those cases explicit UB. There's also a larger universe of implicit UB that standards omit. Most (all?) languages have implicit UB, even if they lack the explicit stuff. What happens when you get ENOMEM is a common one.
Rust does something similar to C/C++ and lists a bunch of UB that's only possible with incorrect code in unsafe blocks. Correct code placed in an unsafe block remains defined, as does code without unsafe (up to compiler/language bugs).
The goal of a library is to provide the encapsulation such that the unsafety doesn't spread.
If undefined behavior occurs, the fault lies with whoever wrote `unsafe { ... }` in the body of a function. If I write "unsafe" in order to call an unsafe library function, and I don't meet the library function's pre-requisites, then it's my fault. If the library internally writes "unsafe" in order while providing a safe wrapper, and I never actually wrote `unsafe { ... }`. If neither I nor the library wrote `unsafe { ... }`, then it is the fault of the compiler.
Using "in safe Rust" means that `unsafe` doesn't occur either in the user code nor in the library. In this context, since we've heard how many uses of `unsafe { ... }` exist in the Bun rewrite, I'd read "in safe Rust" to mean "without calling any functions marked as unsafe".
This is because that's not going to emit any machine code at all, and yet it will cause LLVM to do very nasty things, for example code which either prints "Odd" or "Even" by examining the integer may now print neither because that's faster and this uninitialized integer isn't odd, yet it also isn't even so...
I was first interested in Bun because it was written in Zig. I was interested in Zig because I respected Andrew Kelley's decision-making, and his taste matched my own.
I got really excited about Bun for many reasons after that, but they essentially came down to a similar root: the decisions were ones that I respected and would probably have made myself if I had thought of them.
I was a little concerned when Bun was acquired by Anthropic, but forced myself to remain cautiously optimistic.
This behavior, though, is exactly the sort of decision-making that I don't respect. I've got nothing against Rust, but if this is how Anthropic is managing Bun, I can no longer bet on it being a reliable part of my toolkit. It isn't just the code, it's the thought behind it that I have to trust.
I was so excited by Bun for many of the use-cases I have, but this just turns me off completely. This looks like an Anthropic internal-only tool, based on the behavior.
I don't have a single reason not to pick nodejs when doing JS.
But, I warmed up to Bun over the last couple years almost against my own will — trying to maintain a pretty large body of TypeScript code in a runtime-agnostic way (including even Node, since 24.2). I don't want to make any specific TypeScript runtime a requirement for my TypeScript code, unless there are really good reasons to do so.
But Bun (like Deno) kept providing those reasons. Postgres, SQLite, S3, websockets, local secrets (Keychain/wallet), bundling, compilation, killer speed. So I (somewhat grudgingly) started using Bun more, and even made it a requirement for some of my projects (albeit, in ways I could walk back later if needed).
Today, I have a bunch of API servers and frontend app servers which are bun build --compile --bytecode single executables ,that can run and be deployed virtually anywhere.
I've been very happy with it so far. But also, I don’t think that the way I am doing it is super-common, and now that they are doing this, uh... extremely ambitious LLM port, I am perfectly positioned to regret all of my decisions around Bun if this port ends up sucking.
So I'm a little nervous, but... what if it doesn't suck? That would be cool, because a.) they will have shown something interesting about what is possible with LLMs (albeit if you are rounds-to-a-trillion-dollars valuation frontier AI lab, lol, but still). And b.) going forward, Bun will be developed in Rust. We all have our own preferences, obviously, but to me, that's a win.
And if it does suck, though — that's super interesting too! Will be annoying to me to re-architect my Bun-specific shit to Deno, but for the world at large (and me, too) that's still interesting information!
Because Bun is perfectly positioned to do a huge LLM-powered port. They are one of the premier TS/JS runtimes, it's obviously and insane marketing pillar for the AI lab that bought them, they have unfathomable resources and access to the cutting-edge models that all of us don't get to play with yet, and for all intents and purposes, they have unlimited money to do this.
So if they can't do it — which will be really obvious, I think, if true — then it really just isn't possible yet, and all the naysayers were right.
I don't know, I've followed Deno, and it appeared to me an incredibly low ambition from the get go.
Why not both? How about that: perfectly fine for Anthropic but suck for everyone else.
In this case, I would trust the output even less than the input. The input was memory-unsafe but hand-written. The output is memory-unsafe but also vibe-coded and has had no eyeballs on it. What is the point of abusing agentic AI for this use-case?
The issue isn't the existence of undefined behavior that miri would catch. The issue is exposing an API that allows undefined behavior from safe code - which miri only catches if you go write the test that proves it.
This isn't an all together unreasonable thing to happen during an initial port of code from an unsafe language. You can, and the bun team seems to be, go around later and make sure that the functions where you wrap unsafe code does so correctly. Temporarily in a porting stage incorrectly marking some unsafe functions as safe isn't a real issue. It's a bit strange to merge it into the main repo in this state, but not a wholly unreasonable thing to do if the team has decided that they're definitely doing this. The only real issue would be if they made an actual release with the code in this state.
It's also a bit unfortunate that they didn't immediately set up their tests to run in miri if only because LLMs respond so well to good tests - I know they didn't do this not because of this github issue (which doesn't demonstrate that) but because there's another test [1] that absolutely does invoke undefined behavior that miri would catch. Though the code it's testing doesn't actually appear to be used anywhere so it's not much of a real issue. That said it's obviously early in the porting process... maybe they'll get around to it (or just get rid of all this unsafe code that they don't actually need).
[1] https://github.com/oven-sh/bun/blob/4d443e54022ceeadc79adf54... - the pointers derived from the first mutable references are invalidated by creating a new mutable reference to the same object. In C terms think of "mutable reference" as "restrict reference which a trivial mutation is made through". It's easy to do this properly, derive all the pointers from the same mutable reference, it just wasn't done properly.
PS. Spamming github just makes people less likely to work in the open. Please don't. We can all judge this work just fine on third party sites.
PPS. And we might want to withhold judgement until it's in a published state. Judging intermediate working states doesn't seem terribly fair or interesting to me.
Couldn't a case be made that it's better to get Bun to the to the language with the stronger type system first and, once there, use that stronger type system as leverage for these kinds of improvements as a follow-on effort? It seems preferable to requiring perfection on the very first step.
This is what they are doing.
They are working through the issues as they come in.
What is a bit disappointing is that the Rust code apparently has APIs that aren't marked unsafe but may cause UB anyway. When doing this kind of translation, I'd always err on the side of caution and start by marking all/most things unsafe. Or prompt the slopbots to do the same I guess.
Then you can go in and verify the safety of individual bits step by step.
This is expected, because unsafe rust can leave your program in an unhealthy state, since the language doesn't doesn't hold your hand anymore.
The bar for matching tsc's behavior is really _really_ high. see:
https://github.com/type-challenges/type-challenges
I'm not against using LLMs to write a lot of code. But verification should be 100x more robust now that we can output code at this rate.
This asymmetry is well understood by marketing and PR professionals, and actively exploited.
Then I realized that the github ui was auto-collapsing a dozen messages in a row that were all completely devoid of any informational value and certainly sourced from forums and community discord channels.
This places everyone in a no-win situation. Someone who has identified critical issues that they believe the majority of a relevant community would be concerned about has good reason to signal-boost as much as they can.
It's a substantial request about very recent changes, and tone-policing it doesn't make it less true. The problem is that the additional attention literally kills the discussion. This also provides cover for people who may be making more emotive or ai-psychosis influenced decisions on the maintainer side.
Projects with a siege mentality which block and ignore criticism tend to go off the rails very quickly. On the other hand, maintainer burnout is inevitable for projects which can't shield maintainers from the anxieties and pathologies of people who seem to think that if they complain about AI enough, everyone else will stop trying to use and improve it it.
https://news.ycombinator.com/item?id=48073680 (seems like just a normal user - enthusiast at best)
https://news.ycombinator.com/item?id=48132488 (this one seems suspicious - 2 year old user with this being their only submission ever and they have zero comments - anthropic could have submarined it but it's not a big flashy announcement)
https://news.ycombinator.com/item?id=48150900 (this thread - user is anti-AI and anti-datacenter)
But definitely the one thing these things aren't are big flashy announcement. To be honest, this kind of post-truth environment where people just make up things about people they don't like are super-lame. I've generally been able to deal with it by kill-filing people who post falsehoods but the number of users who do is getting so extraordinarily large I am starting to believe that I need to auto-hide anyone who created an account in the last 10 years.
Isn't the whole point of AI companies using Rust that it's explicit, safe, and AIs are fairly good at writing it?
In particular, if you have a situation that requires any kind of conceptual understanding then AI will likely have issues. Sync blocking async is the classic example. My theory is that humans make this worse because they will often prompt in a certain direction and AI will faithfully build the footgun.
Related: If AI writes your code, why use Python? (which notes why Rust has taken off for LLMs) https://news.ycombinator.com/item?id=48100433
Also the LLM is inventing ways to get around borrow checker limitations with unsafe which is also concerning. But I didn't verify if they are UB or not (either way it's a rejection if I'm to review the code).
In a nutshell, the LLM created abstractions that allow you to write unsound code in safe rust, which is squarely against the language.
To be specific: the abstraction takes a (shared) reference and uses unsafe to wrap it in an owned object, completely erasing le lifetime. In practice, this means users of the abstraction think they own the underlying memory: they choose when to free it. However, it just wraps a pointer that’s owned by someone else (it was a shared reference, remember?), thus it will be freed when you don’t expect it.
So why does it not exist in Zig: it’s a false contract about what it is. The Zig pointer is a pointer with no added lifetime information. You can hold a Zig pointer wrong, but you will hold a lying abstraction wrong. You will misuse it because it doesn’t do what’s written on the tin. You will write bugs with it.
And, LLMs will too. If they do not have the abstraction definition in their context, they also have no way to know the contract is lying.
If you find a bug, just go straight to blog posts and CVEs to denounce this idiocy. It ranks higher on Google.
The "rewrite it in rust" commit is +1M lines of code. Humans haven't looked at that in depth. In about a week, they saw the tests passed and pushed it to main. Now people have started to look through it and are pointing out glaring issues. And the solution is just going to be "feed it to another AI and ask it to fix it".
The entire codebase is slop now. Nobody knows what it does. It manages to pass some tests, but its largely a black box just on the basis of humans haven't read it yet. The code isn't guaranteed to be anything close to 1:1 with the old codebase. Its probably vaguely shaped like the old codebase, but new bugs could be there, old bugs could be there, nobody knows anything yet.
Its going to be interesting to see how recoverable this is. They are almost certainly going to just hand every file to an AI, say "look for soundness issues and fix them" and then what? If AI is making huge, sweeping changes to the code so frequently that humans can't keep up, is that really maintainable? The only solution appears to be "even more AI" while anybody that looks closely gets scared away by the too-large-to-comprehend-and-entirely-slop codebase.
This kind of thing has been happening with many smaller projects already, but now its a larger project and happening in a much more public way, with the intent to replace human-written, mostly-understood code with slop. I suspect the same thing, with the same problems, is happening inside all the largest companies, just not quite as obviously.
There’s no way they had time to review the code. This just seems so wildly irresponsible for such an important and high profile project.
My grandpa told my dad never to show a client a work in progress - You told them when you'd get the work done, and they can see the finished result when it's ready.
It's just a story so don't wrap yourself around the axle with counter-examples. I think it's fair to say that an open-source project going through a language translation is going to have transitional periods as they shake things out, and criticizing every snapshot as some proof that they're incompetent is useless.
But I think their true strategy is to have AI produce "fixes" like these which will end up infecting the entire codebase: https://github.com/oven-sh/bun/pull/30728
It's been like a day since the merge, presumably such followups are coming.
> The Zig original is a packed struct with the same shape; it "worked" only because Zig has no reference aliasing or provenance rules to violate. The Rust port inherited the shape without rethinking the API surface.
I'd be concerned that by jumping onboard with this sort of development process I'd lose touch with how to engineer software in a detail-oriented or remotely rigorous way.
It also makes me question what sort of value the entire Bun project ever had if a drop-in replacement can just be thrown in here like it's nothing. Why do we need all these JS runtimes again?
The AI bubble is so large that we've also forgotten how useless and dumb a lot of software engineering labor was even before LLMs came along. We were already in a bubble.
All that is to say, I think it's useful to reframe some conversations about AI as, "if AI can accomplish this task, was it ever actually valuable?" I think for some specific things, the answer will be yes, but the tech industry has been huffing its own farts for so long I really don't think anyone has sight anymore of what's economically valuable in a ground truth sense. Much like LLMs themselves, this confusion pollutes the entire well of discourse about their economic utility.
"Zig, let me Ai you"
"no"
*Ai's Zig fork, suffers from memory bugs*
"Well I'm moving!"
*Ai's code into Rust, suffers from memory bugs*
Have you ever seen what comes out of c2rust? It's awful. It relies on a library of functions which emulate unsafe C pointer semantics with unsafe Rust.
A few years ago, when I was struggling with bugs in OpenJPEG (a JPEG 2000 decoder), someone tried running it through c2rust. The converted unsafe rust segfaulted at the same place the C code did. It's compatible, but not safe.
Main insight: don't do string manipulation in C or unsafe Rust. It's totally the wrong tool for the job.
which is somewhat close to what their port produced...
like their goal was from the get to go to have a mostly exactly the same as zig "just in rust" which implies mostly unsafe rust and all the soundness/memory issues zig has (plus probably some more due to AI based port instead of a tool like c2ruts)
the thing is if you don't keep things mostly 1:1 with all the problems that has there is absolutely no way to review that PR or catch the AI going rogue with hallucinations etc. With a mostly 1:1 port you can at least check if things seem mostly the same.
but it also means this is just step 1 of very many, with the other being incrementally fixing soundness, removing unsafe and (hopefully) making the code more idiomatic...
(to got to the actual question of why?, I think the answer is doing this port using AI is likely way easier/faster then first writing a tool which need in depth understanding of the languages, especially given that some features in zig do not map 1:1 in rust and fuzzily mapping is what LLMs are good at and human hand written tools tend to be very bad at).
That is indeed the point of c2rust. It gives you a baseline that is semantically identical to the original codebase, and with that passing the full test suite, bug-for-bug, you can then start gradually adopting rusty idioms to improve the memory safety of the codebase.
This is awful. They have some internal string format borrowed from a Zig library where the address of the item is in the low end of a pointer and the length is at the high end. Why are they doing that in 2026? It lets you save a few bytes at best. It doesn't enforce the Rust rule that strings must be strict UTF-8. It's totally alien to the safe way Rust handles strings.
[1] https://github.com/oven-sh/bun/blob/main/src/bun_core/string...
Isn't that exactly what you want from that kind of tool? Otherwise it means it's changing how stuff works and in this specific case that would be good but in most cases unwanted.
its not cynical, its a real question. not trying to be mean but saying that something that people have solved countless time shouldnt be done is weird statement.
Yes and that would be safer than the current slop translation, because c2rust does these ugly things exactly to avoid introducing new issues with the more strict Rust semantics.
It _already was and should_ be that awful to match the original code without introducing hundreds of new UBs like the current situation.
They did ;) a highly dynamic one...
This doesn’t work like you think it does. These things are full of errors and make the code very verbose and hard to reason about. It works with small apps, not entire rewrites.
Translating zig -> rust is more complex than writing a JPEG parser in static python and then lowering it into zig and rust differently using idiomatic construct for each language.
Towards that end, I've created a parser for a dialect of python which is suitable for this purpose. It should maintain compatibility with the vast majority of python code out there, while picking up some rust/zig features that make translation easier. JPEG parser included in the assets of the skill for a flavor.
If you are making a full rewrite and have non-working, in-progress code, you use a branch. This way you can still have the working "main", in case there is a security fix needed or something.
- Test before code, Bun had lots of test so that's good but maybe they could start by asking Mythos to write like 20k additional tests that pass on Zig Bun first.
- Deterministic anti-slop features. LLMs love to solve the problem in the wrong abstraction layer or place. There are many ways to catch this with deterministic tests. I do this in tsz a lot
- Roadmap that constantly evolving by humans.
- Taking a pause and looking how the progress is going and undoing slop
- Fuzztest(https://github.com/google/fuzztest) style "trying to break things" with the powers of LLM
This is awesome. Typescript really needs more of this. I hope this gets more publicized and perhaps get adopted by Microsoft.
I am not sure you should call it sound mode though.
> It is not a mathematical proof of soundness, and it does not make third-party .d.ts files truthful.
Here there are two completely unrelated things
First, soundness is a mathematical thing (sorry). If something is sound, it's really really sound. Soundness is the thing that says we don't need to manually check the details - we can trust the compiler to do the right thing. It will do the wrong thing if there's a bug, but the implementation can be fixed. Soundness means there's is no bug in the spec, no bug in the type system that would make things go wrong even in theory.
Second, and here's the important thing.. it's entirely okay and expected that real world languages need to have unchecked features where we trust the humans to do the right thing, rather than trusting the compiler to verify. That's like Haskell's unsafeCoerce or Java's sun.misc.unsafe. The problem really is when the type system breaks even when we don't do any of those
If type system says, x has type T, then x has type T
TypeScripts type system does not have that property. E.g. by default `stringArray[0]` has type `string` when it should be `string | undefined`.But TypeScript could be sound if you eliminate all these cases. If that's the goal of "SoundMode" then the name sounds fair to me.
Not even sure `.d.ts` files are a problem in this regard. They are like axioms/facts. Resolution (from formal logic) is a sound inference rule but you can still derive contradictions from contradicting facts.
It shouldn't be shocking, it was done using only compute, and the codebase is owned by the company who owns the compute, you literally just turn the dial up and it will be done faster. Efficacy of LLMs aside - anything they could do in 30 days they could also do in 3, if you spend more money.
If you believe that having enough tests can save an LLM codebase - I have bad news for you. You can write a test for every single interaction ever written in typescript and it'd not be even close to 10% coverage.
If I was the bun maintainers I wouldn't want to have to maintain a language fork either, when there are viable alternatives.
Now with LLM's getting stronger and stronger a rewrite like this is getting more and more viable, and it looks like they are just approaching this like the "how do you eat an elephant? One bite at a time"-method.
Not sure why people thing this is an elaborate PR campaign, we already know LLM's are increasingly powerful for coding tasks.
It is. We’re what, a week into this exercise? Absolutely everyone criticizing it, with no exceptions, is behaving like a micromanaging middle manager who couldn’t even dream of doing the work themselves.
I half want to start a list of “people to ignore”, but such people tend to expose themselves in every other comment anyway.
Did they even claim it was "memory-safe"? Every discussion of this topic has had dozens of comments noting that their vibed codebase is bursting at the seams with unaudited unsafe blocks, lightly reviewed by people who seem to not only seem to not understand Rust, but who seem incensed at the idea of needing to understand any programming language in the first place.
They did cite Rust's safety as a motivating factor for the port. That doesn't imply trying to achieve that simultaneously with the language change — which is good, because that would be insane. (Or, if you prefer, even more insane.)
You cannot faithfully port a codebase to a new language while also radically re-architecting it. You have to choose.
They want the safety benefits of Rust going forward; i.e., after it's finished, when they then write new code in Rust.
they didn't,
actually the port is trying to be mostly 1:1 and in turn is mostly unsafe rust, which means no benefits initially
but also doing the 1:1 port to mostly unsafe rust is also only the first step of a full port, you then incrementally go through it fixing issues and remove "unsafe" usage. (And long term likely also doing some refactoring to using more idiomatic rust, but that has less priority).
The problem is there was no blog port describing the whole thing to someone without contextual knowledge. Instead just linked PRs which is in this case somewhat close to a "as if nearly all people only read the HN headline" case :/
Like a more context giving version of the first HN post would have something on the line of `Show HN: Bun is porting to safe rust (PR link), starting with an AI based automatized port to mostly unsafe rust which once it behaves mostly the same as Bun in the test suite will likely be merged. But must be followed up with incremental PRs to remove unsafeness, and likely also a lot of unsoundness related to the way it's ported (some explanation about why this port will have unsoundness).`
In your quote, there is no time-dependency between the lie and the truth. Whereas here, it's an attractive lie (easily parsed, great narrative), followed up by truths (that need more than surface-level analysis).
The rewrite was a code translation meant to be a starting point.
> a big, flashy announcement (here: bun was re-written in memory-safe rust in a couple weeks), and the relatively small reach of a correction (often just a footnote on an old article, here a GH issue).
The Bun team never made a big announcement that the code is now memory safe. They've been clear that this is the starting point.
Anyone expecting it to be perfect immediately and to have solved all of the memory problems in the original Zig code is arguing with an announcement they imagined, not what the Bun team has said.
Did anyone try to map this code back to the original codebase to see if this memory problem exists in the original codebase?
FWIW what is being discussed is not memory problems, it's breaking rust invariants (the unsafe code has to follow specific rules, e.g. annotate lifetimes properly).
Thus far most of the buzz and marketing has been entirely negative from people who are against AI.
My take is that most of the buzz is also tied to recent negative opinions of Anthropic themselves due to some of their recent decisions.
To me it seems like quite a lot of it is also by people who spent years maintaining a codebase just to have the metaphorical rug be pulled out from under their feet, and feel that a migration like this might be kind of disrespectful (how many of the people that have gotten good at Zig and know the codebase will find the switch over to Rust easy)? Or in some cases, that it's just bad engineering - instead of releasing it alongside the main project and focusing on gradually getting parity over months, it just got merged into the main branch.
On a more practical note, however - if you get acquired by a company that gives you almost unlimited usage of tools that might help you migrate to a language, that 3 years down the line will lead to a better codebase than today, then I guess it also makes sense to take that chance.
And of course, you get a lot of people who are opposed to AI on principle, as you said.
It's not that they're using AI, it's the massive rug pull on bun users.
* Make a huge deal out of it how “Claude Code enabled Bun team to rewrite 1+ mil of Zig lines to Rust” and write a blogpost, VCs are salivating
* Basic checks fail
* Let Mythos rip the codebase to shreds, spend God knows how much more
* Write a separate blogpost
* Charlatans and smooth brains clap and defend against “delusional anti-AI mob”
* VCs orgasm even harder
Clap, clap, clap. That’s how you make money, folks.
And btw, we need to get rid of software engineers now.
That's the idea, to transform businesses to be wholly dependent on "AI" service to develop software. What better way than to re/write entire codebases until no human being understands it.
The Zig project know this, and its so-called "anti-AI" policy is actually pro-community and cultivating human understanding. It's not about the tool or technology, per se, it's about people, knowledge, and sustainability.
In contrast, the Bun project is demonstrating how they doesn't care about any of that, YOLO-ing its way to losing the trust of its users, contributors, and maintainers. Oh well, AI will maintain the project now, since no one else can.
It's sad to see what hacker culture has been reduced to: outright contempt for science and engineering.
I am not against AI code, it can be perfectly fine.
The principle issue in my mind is the rate of change.
Once you rewrite a code base like this (in a week no less) the only way to work on it in the future is using AI tools because no single person has any knowledge about any specific piece of code base any more.
AI generated code that is run through a classic PR process would potentially be fine, but then you sorta lose the entire point of using AI.
Bun's fork of Zig was just an unsound hack that at best would have produced a strictly inferior speedup compared to our current work with incremental compilation, which is already plenty usable:
- June 2025 core team starts using it with the zig compiler itself https://ziglang.org/devlog/2025/#2025-06-14
- April 2026 https://ziglang.org/devlog/2026/#2026-04-08
> Zig's AI stance is ridiculous & politically-motivated
It's literally an issue with our business model to mess with our contributor pipeline, can't get more concrete than this.
> An example of this is the changes to type resolution which happened in the 0.16.0 release cycle—these didn’t affect users too much, but had big implications for the compiler implementation. Before those changes, the compiler’s behavior was often highly dependent on the order in which types and declarations were semantically analyzed by the compiler. Some orders might result in successful compilation, while others give compile errors. Single-threaded semantic analysis prevented these bugs from causing user-facing non-determinism. The rewritten type resolution semantics were designed to avoid these issues, but Bun’s Zig fork does not incorporate the changes (and has not otherwise solved the design problems), which means their parallelized semantic analysis implementation will exhibit non-deterministic behavior. That’s pretty much a non-starter for most serious developers: you don’t want your compilation to randomly fail with a nonsense error 30% of the time.
There is a reason why, zig is upholding the quality and they hate it.
However, I think if it turns out that that's the case, then their port will fail in two ways (to paraphrase Hemingway): gradually, and then suddenly.
I don't think this port can be a success unless they end up — on the other side of it, not necessarily immediately — with maintainable Rust code.
but sure anthropic might not agree
When we've seen linux having a new significant exploit every other day now thanks to LLMs being better at weaponizing memory bugs this seems significant.
Judging by the name, nor should it, because OS-paths aren't always UTF-8. See for example the rust standard library type OsString https://doc.rust-lang.org/std/ffi/struct.OsString.html
The rust std library string is a reasonable default, but it's not always the right choice. Lots of projects use different things for good reasons.
Agreed. But it isn't the goal of the sound mode. It's still unsound from a type theory point of view, just with fewer holes
It's simply not possible to include all the nuance of safety of a language and all software written in it a single word. This leads to all kinds of miscommunication and strawmanning.
Rust's official line is specific memory safety guarantees, with caveats that it must not be broken by unsafe code, the OS, compiler bugs may happen, etc. Rust also has a bunch of best-effort features that steer users towards more robust code, but can't guarantee it.
This gets twisted in both directions:
- people ignore the caveats and limitations, pretending that Rust promised zero bugs ever, and use any bug in any Rust program as a proof by contradiction that Rust's claims are false.
- or focus solely on the caveats, ignoring all the advancements and incremental improvements, and take a "then why even bother?" There are classes of bugs Rust can't stop. Nothing is foolproof for a sufficiently advanced fool, and an infallible programmer could write bug-free code in any language, which creates a false equivalence between languages.
Well, presumably they want to contribute to the compiler. I know that you did not like those contributions, and that view seems entirely valid, but obviously "no AI" rules out their development model (by design, and you likely think that's good, and maybe it is!).
Not intending to defend the bun move, but obviously a project using Zig and also using AI might feel motivated to avoid Zig since they're ruled out as contributors.
https://www.reddit.com/r/rust/comments/1hxjdvp/eli5_what_is_...
In C or C++ you conventionally store a suitably large integer (uintptr_t for example) and then when you sometimes need a pointer you just cast that integer to a pointer. Under the proposed C provenance semantics PNVI-ae-udi this gets you exposed provenance.
In Rust you conventionally store a pointer, and then when you sometimes need an integer you ask for the address bits from the pointer (which on popular platforms will be the whole pointer but as an integer) or you make pointers from the integer you have with no claim to their provenance. If you're careful this gets you what Rust calls "strict" provenance, it's just straight PNVI.
This is basically the same argument made for C++ and I think it's not a very solid one. We know this worked, but that's not evidence that alternatives couldn't have succeeded. I think in a world where Queen never happened the prevailing wisdom would be that someone like Farrokh Bulsara (Freddie Mercury) can't be a rockstar because that seems ridiculous.
Actually speaking of royalty, Prince is an even more extreme case. You cannot use numeral-letter substitutions in song titles, that's something for kids and won't... oh unless you're Prince. Yeah, no, "Nothing Compares 2 U" is fine Prince, thanks.
My goal with tsz is to make it practical and useful. I know how difficult it is to convince a tsc user to try something not officially from Microsoft
I don't think this is the problem.
I mean, ok, the first part of the problem is that typescript can't or won't represent at the type level some real world Javascript constructs. But that's understandable since Javascript can get arbitrarily complicated. (you could do a survey on npm and make a type system strong enough for all existing libraries, but this would probably be too complicated to use)
So this is not by itself too bad if, for each instance of non-representable APIs, you wrote a wrapper library that called the bad library but gave you a perfectly good API to work with. Similar to how in Rust you are supposed to wrap unsafe libraries with a safer, higher level API on top. (except it' s not about memory safety, but type safety. but the same reasoning applies, it's just lower stakes since UB is not involved)
Bur the other, more fundamental problem is that for some godforsaken reason, Typescript decided it was okay to lie with types. Some operations return the wrong type rather than a more honest type. This is not caused by the fact that Typescript has to work with libraries in npm, it's entirely self inflicted. Elsewhere in the thread someone gave an example: stringArray[0] has type string when it should be string | undefined.
This (and all other instances of deliberately lying with types) is why Typescript is unsound. Here's a list of things that cause unsoundness (not sure if complete) https://effectivetypescript.com/2021/05/06/unsoundness/
If all those things are patched up, Typescript can be in general mostly sound, even though it has to work with npm libraries and even though you need to trust other people's .d.ts files. To gain full soundness on your application code, you just need to write wrappers to work around the most egregious cases (which should be a minority). Again, the same situation as Rust is supposed to be: it's in general sound but when you need to interact with bad stuff you write a wrapper. (Note: Rust has its shares of unsoundness, but contrary to Typescript, Rust has a plan to eventually patch them up, even if this causes incompatibilities down the line)
The "1:1" assumption is a massive unjustified assumption. Rust and Zig have different memory models, so it's possible to do a "1:1" translation of Zig code to Rust and end up with undefined behavior in Rust.
For example, Zig code might make assumptions about lifetimes based on implicit knowledge of which allocator was used for some memory. That could cause problems in Rust if you erase the lifetime https://github.com/oven-sh/bun/blob/main/src/bun_core/string...
It's not, that's clear from this kind of bug popping up. Functionally this bug exists because `PathString` was converted into a "safe" Rust API but still works the same internally as the original Zig code did (via using `unsafe`), that introduces UB that wasn't there in the Zig code.
If it was attempting to be a 1:1 with no behavior changes (like c2Rust attempts to do) then this would not have been turned into a "safe" Rust API like this.
c’mon.
I mean, the phrase "Zig to Rust port of Bun" makes little sense even to many professional developers. They may know Rust, might have heard of Zig, very likely don't know what Bun is.
So the fact that this gets any attention at all says something.
Any serious professional in this field knows that software development is far from a solved problem. It wasn't before LLMs, and it isn't now. Responsible development takes discipline and respect for the hard-won lessons of past and present efforts.
But no, according to many here, being responsible makes you a "luddite." "Humans make mistakes too," that's what they'll say as they'll inevitably screw over people's lives with their reckless disregard for others. "It's not my issue to solve."
Seriously, haven't techbros already caused enough damage throughout society with "move fast and break things"? A lot of people are losing patience for this nonsense.
But tbh this is trivial to write these days since the boilerplate can be written by the machines and you can just write the core functionality to make it work. I only have it public because I'm hoping others will also block users who misinform as a habit and I can subscribe to their lists and crib off their work without having to do it myself.
If you want to save yourself the first 15 min of prompting, just point Claude Code at this https://github.com/TechnologyBrotherhood/overmod-extension and ask it to implement the local blocking functionality.
I separate mine by a bunch of categories which might be a bit complicated, but I was hoping perhaps people might not care about some of the categories https://wiki.roshangeorge.dev/w/Overmod#My_Stuff
e.g. I don't like endless repetitious "but corporations" stuff and I also don't like "but they sell your data" repetitively but maybe others want to block category A but not category B.
I think that wasn't a sound idea, though. Either people trust you to block for them as well or they don't.
Not sure why you're inventing a stance for me to be arguing against, when the Zig compiler stance is publicly articulated as exactly what I'm describing.
The zig team is not that big. They don't have 200 core contributors to filter through the noise and mine PRs for "gems".
I think an outright rejection of AI contributions makes sense, regardless, and has nothing to do with politics. A Zig developer was forced into writing a long-form post to justify rejecting Bun's awful contribution (lest their PR be sullied, and then it was anyways), and the act of writing that post probably took 10 or 20x more human time and effort than Bun's contribution. Now multiply that by 100 for every random fucking moron with an LLM submitting a contribution. That is not sustainable. Open source maintainers of popular projects would have to make rejecting AI PRs their full time job and stop developing the project itself altogether, if they took them seriously and reviewed at length to conclusively identify whether a PR is good or bad. Given that 99.99% of AI PRs are bad, it's simply not worth it. You cannot possibly expect humans to spend more time reviewing code than drive-by contributors spent generating it, especially when many of them are unpaid volunteers. It's an absolutely ridiculous expectation.
I've seen large rewrites and migrations take both approaches -- in my experience, the former usually works out better.
What I was specifically referring to is Deno (originally) trying to fix the (glaring, fundamental) problems that Node imposes on the world, vs just do them faster.
And to offer a counter example, something like Dart appeared much more ambitious to me.
Surely we can agree that one of those positions is relatively less ambitious?
Though if you look relative to the team size and resources going into it, a project like Deno can still be considered ambitious. Creating an alternative ecosystem to nodejs is a large undertaking.
One example: https://github.com/immunant/c2rust/issues/1678
I firmly believe the right way to port C and C++ (and Zig) programs to Rust is to do it module by module ("Ship of Theseus"). It needs scrutiny by folks who know both languages deeply, and you can port test cases too so you can detect UB at runtime (using tools like Miri). That's what fish did, and their port has been quite successful.
Blindly trusting the results of a machine translation is never a good idea. Especially when the translator has a temperature parameter.
2022 discussion on HN.[1]
There's a DARPA funded effort called TRACTOR, Translate All C To Rust, which has funded some efforts to develop a usable translator.[2] It's about 10 months after award, with no reported progress. I've been checking the personal sites of the academics involved, and they barely mention the project, although $5 million has been allocated to it.[3] The approach comes from U.C. Berkeley - let the LLM generate slop, check it using formal methods.[4] Not expecting near-term results.
[1] https://news.ycombinator.com/item?id=30169263
[2] https://csl.illinois.edu/news-and-media/translating-legacy-c...
There are also some papers being published that were funded by TRACTOR, such as https://homes.cs.washington.edu/~mernst/pubs/c-rust-macros-p...
Here are the test cases for evaluation #1.[1] There's good coverage of the C language, but the individual tests are mostly simple exercises of one C feature. The next round of test cases will probably be closer to useful programs.
[1] https://github.com/DARPA-TRACTOR-Program/PUBLIC-Test-Corpus
That doesn’t really mean anything.
> It's more verbose than the original and harder to work on, but no safer. You lose the C idioms that people understand, while not gaining Rust idioms.
Yes, and?
The value of c2rust is that you now have the entire codebase working with the rust toolchain, you’re not juggling toolchains and you’re not managing a wavefront of FFI, only a wavefront if unsafe.
C2rust is not the end, it’s the start. It’s never claimed to be anything more (the official website even mentions galois and immunant are working on tooling to convert unsafe to safe / idiomatic rust though i don’t know if that got anywhere yet).
I'm much more bullish on the opposite approach. Perform the naive translation, let the LLM loose on cleaning it up...
And realistically, essentially 100% of the people criticizing this don't have the the credentials to do so meaningfully.
But yes, URL imports have a variety of other issues (duplicated dependencies, no resource integrity), though Deno solved them in later versions (npm registry support, lock files).
The only benefit of Deno is its permissions system, which has been great for safely letting agents write and run scripts on my file system.
* In order to follow convention, you need to decide on git web hosting infrastructure before you start writing code. The tooling asks you for a URL the moment you run 'go mod init'. My preferred way of doing things is to start work on a project just on my computer and then maybe put it on one or more online git web host eventually, if the project goes anywhere. That order doesn't work with ideomatic Go. To work around this, I write mostly non-ideomatic Go where I use the name of the project instead of a URL as a package name.
* I view hosting infrastructure as incidental. I may throw a project on GitHub. I may change my mind and move it to Codeberg. I may move it to my own git forge. I may get tired of hosting my own git forge and move it to sr.ht. With Go, each of these moves requires a huge "touch a bunch of lines in every file" style commit if you're using the ideomatic "git web host as package identifier" style required to work with 'go get'. In other languages, it requires at most a readme change, and for dependencies, it requires at most a git submodule or package manifest change.
* Go requires that you use a Go-compatible git web host. Because Go decided to make URLs look like 'example.com/foo/bar/baz/qux', it has no way to determine which part of that is the git repo and which part is a subdirectory of the repo; should it 'git clone example.com/foo/bar/baz.git' and look at the 'qux' subfolder or should it 'git clone example.com/foo.git' and look for 'bar/baz/qux'? The only solution is for Go to make an HTTP request to 'example.com/foo/bar/baz/qux?go_get=1' and parse the response HTML and look for a Go-specific meta tag which tells Go what part is a git repo. This is an immense "layering violation" and extremely ugly hack in my opinion. This feels so unnecessary too, since this is an easily solvable problem: just make URLs look like 'example.com/foo/bar/baz:qux', so that Go knows to look for 'qux' in 'example.com/foo/bar/baz.git'.
* Private repos are a horrible experience. You need to convince Go to not look them up in Google's package checksum database, you need to convince Go to not get them from Google's caching infrastructure, you need to make a ~/.netrc file with credentials, you need a git host web frontend which understands and supports the way Go + .netrc makes authenticated GET requests. If any of these things are misconfigured, you get a cryptic error message about how terminal prompts are disabled on Google's servers. It's all very brittle and hard to debug, and the guidance has changed drastically over time (editing your global .gitignore to rewrite relevant HTTP sources to use SSH used to be the advice, but that had its own significant problems).
* It has the "feeling" of being decentralized since it's all just git URLs, but in reality, Go's tooling depends heavily on Google's centralized package cache and checksum infrastructure which has been introduced over time to smooth over foundational issues with the design.
I was once part of separating a complex project out of a company and moving it to its own infrastructure on a different domain name and git host. The Rust and C++ repositories were a breeze, just change the URL in a CI job. The node.js repositories required changing some references in the source code from one NPM org name to another but were otherwise painless. The Go repositories were absolute hell.
I have considered writing a blog post about all this.
* No relative imports.
* The `require` directives from the `go.mod` files of your dependencies are always ignored.
Those two combined, mean that there's no easy way to fork a dependency. It's doable, but some of the maintenance overhead could have been avoided.
We don't even get a `go mod tidy` flag that lets us say, "yes, I understand the risks, just copy any `replace` directives that you find in my dependencies". With a flag like that, even if the `replace` directive is still copied everywhere, at least it's automatically copied during a routine `go mod tidy` invocation.
They already have `// indirect` comments, so those could have a `// indirect, replaced by X` comment or something like that.
Thanks for your time writing that. A blog post would be great.
This is optional, but also really, really handy for standalone scripts that don't need to come with a package-lock.json or deno.lock file (if you're not aware, Deno did a lot of changes to package management in later versions).
The newer posts go into detail about the rearchitecting that follows.
citation needed
> and continue pushing the boundaries and our imaginations onward.
what percentage are doing it pro bono?
The business value the Bun team needed to deliver (to make the acquisition pay out) might very well be this controversial, but nevertheless spectacular, 6-day Zig→Rust port.
But beyond that, now Bun is just tooling used internally at Anthropic, which also happens to be open-source.
Certainly the recent layoffs¹ of ~half-or-so of the Deno team doesn't bode well for it, as AFAIK Bun was the only other significant player trying (to make it a business).
¹: https://www.reddit.com/r/Deno/comments/1rwjaeb/whats_going_o...