Mohamed Elashri

Mojo is not there yet

I’d been hearing about Mojo for a while. The idea of combining Pythonic syntax with low-level performance sounded compelling, especially for someone coming from scientific computing and systems programming. Every now and then, I’d see a flashy demo or benchmark claim and think: “When I get a moment, I’ll try it myself.”

Eventually, I got that moment. Rather than just reading blog posts, I wanted to build something meaningful. So I picked a small, self-contained project: write an MVP of uproot in Mojo. The goal was simple. Read a ROOT file, parse a TTree, decompress a ZLIB block, and extract a float[] branch.

This is compact and practical challenge, with no ML involved, just a good test of Mojo’s capabilities as a systems language.

That’s when things started going sideways.

First, installation. Mojo no longer ships with the old mojo.magic environment—it’s deprecated. In its place, you’re told to install Mojo using either pixi, uv, or conda. Not one universal way . A three separate Python-centric approaches for what should be a language-level toolchain. All of them bring their own virtual environments, shell integrations, and version quirks. Just picking one feels like a decision tree you’re not qualified to reason about yet.

But the real issue isn’t just the install process. It is what you get at the end. There’s no simple mojo binary to drop into your $PATH. Everything is wrapped inside a managed environment that depends on the “Modular SDK.” What’s inside this SDK? Compiler, runtime, debugger, yes. But it’s bundled together in an opaque way. You’re not told what’s included or why. You can’t just install only the compiler. And worse, there’s no way to develop with Mojo outside of these boxed-in setups.

Even once installed, writing anything non-trivial reveals another layer of pain. Want to read a file? Good luck. Need to work with raw bytes? You’re mostly on your own. The documentation focuses almost entirely on ML use cases, with little support for anything else. For a language trying to position itself as general-purpose, that’s not a great look.

Then there’s the churn.

Mojo’s standard library is in constant flux. Types, modules, and even basic constructs get deprecated frequently. This is expected in an experimental phase, but the rate at which things break or disappear is unusually high even for a new language. Features that were available one week vanish the next. Documentation lags behind. Community examples become stale. It doesn’t feel like you’re riding the cutting edge and it feels like the floor is being pulled out from under you mid-sentence.

And this hits especially hard when you’re trying to build something unfamiliar to the Mojo ecosystem. My goal was modest, decompress a ZLIB chunk and parse floats. It ended up feeling more difficult than doing the same thing in C++. At least C++ won’t deprecate ifstream out of nowhere.

All of this creates an ecosystem where ML developers inside curated environments may feel at home but everyone else is left fumbling. No REPL. No quick scripting. No clean binary to compile and run your program. It’s a maze of tools, environments, and rapidly shifting APIs that offer little to someone just trying to write software.

Mojo doesn’t need to be perfect. But it does need to stop actively working against its early adopters. The potential is real but if you’re serious about growing the user base, start with stability, transparency, and simplicity

Until then, Mojo remains a great idea gated behind unnecessary friction.