37 comments

[ 2.5 ms ] story [ 59.4 ms ] thread
If it wasn't built by Matz I'd have severe doubts, but it's clearly defined and I presume he knows all limitations of the Ruby semantics well.

My thesis work (back when EcmaScript 5 was new) was an AOT JS compiler, it worked but there was limitations with regards to input data that made me abandon it after that since JS developers overall didn't seem to aware of how to restrict oneself properly (JSON.parse is inherently unknown, today with TypeScript it's probably more feasible).

The limitations are clear also, the general lambda calculus points to limits in the type-inference system (there's plenty of good papers from f.ex. Matt Might on the subject) as well as the Shed-skin Python people.

eval, send, method_missing, define_method , as a non-rubyist how common are these in real-world code? And how is untyped parsing done (ie JSON ingestion?).

It seems like a compiler from Ruby to Objective C could support all the Ruby features while still being more performant than interpreted Ruby.
I'm one of those who use eval often. Could I avoid it, possibly, but it seems more ergonomic for me.
>eval, send, method_missing, define_method, as a non-rubyist how common are these in real-world code?

The interesting bunch (to me, based on experience) is `eval`, `exec`, and `define_method` (as well as creating new classes with `Class.new` `Struct.new`). My sense is that the majority of their use is at the time of application boot, while requiring files. In some ways, it is nearly a compilation step already.

Given how common it is rails and how much it uses those, everywhere!
I find the current documentation difficult to understand.

This is a problem I see with many ruby projects. How would I reword this?

Well, first thing, after stating what spinel is, I would show a simple example. Ideally a standalone .rb file or something like that, that can be downloaded (or whatever other format). Yes, the README shows this, but believe it or not, I have realised that I am usually below average when trying to understand something that is now. I even manage to make copy/paste mistakes. This is why I think one or two standalone as-is examples would be best.

And then I would explain use cases.

The current structure of the document is strange. Has that been written with AI? If AI replaces the human individual, why is it then expected that real people should read that? So many questions here ...

Also, I would really like for the ruby ecosystem to not be split up into different entities. I understand that mruby does not have the same goals as MRI ruby, but still, there is fragmentation. Now there is spinel - how does it relate to other parts of ruby? Why are truffleruby and jruby separate? (I know why, so I am not objecting to the rationale; I am pointing out that for a USER it would be better if things would be more unified here in general.)

Ruby really needs to focus on its inner core. The base should be solid. Even more so when it is harder to attract genuinely new developers.

if spinel gets to where it can compile 100% of mruby there could be some nice synergies there.
Given it's built by Matz, how realistic is it that this becomes a core part of Ruby? And if so, how threatening is that for Crystal?
wow, I wanted to have this for a long time. I looked at Crystal, but it never sat right with me.

I think some of the limitations can still be implemented (definitely Threads and Mutex), and I'd prefer it to compile to LLVM-IR or something, not C, but overall I think it is great to see Matz playing around with AOT compiling.

This is really cool, I've been looking for an AOT compiler for ruby for a long time.

The lack of eval/meta-programming fallbacks is a shame though, but I guess they kept the focus on a small, performant subset.

It would be nice to have gems compiled with this AOT compiler that can interact well with MRI.

When it comes to packaging/bundling more standard ruby (including gems) we'll still need tebako, kompo, ocran – and then there's a bunch of older projects that did similar things too like ruby-packer, traveling ruby, jruby warbler etc.

It's nice to have another option, but still, I'm hoping for a more definitive solution with better developer UX.

Yeah I had to fork warbler recently since it hasn't been updated in forever
is this done by matz and claude? :)
For some context, just presented by Matz at RubyKaigi 2026. It’s experimental but he built it with help from Claude in about a month. Successful live demo.

It’s named after his new cat, which is named after a cat in Card Captor Sakura, which is the partner to another character named Ruby.

The most recent cartoon Spinel in my mind is from Steven Universe, so I hadn't noticed the Spinel/Ruby (Moon) pun, that made my day.
That cat story seems more than a little suspicious given the Ruby Central drama / its relation to the founders of Spinel.coop. This project feels likely vindictively named.
As someone who spent a few years working on a compiler in this space — it’s tough, but are the results of instant startup and immediately decent performance without warm-up satisfying to use in practice. I really hope this takes off and yet another language can break free from dominant interpreter + jit compiler monoculture that we currently have for higher-level programming languages.
Wow, written in just over a month. Say what you will about AI, but it has enabled serious speedups in the hands of a talented coder.
Even Matz now uses claude code...
While obviously super-impressive, it is clearly not maintanable without AI agent. It has spinel_codegen.rb is 21k lines of code with up to 15 levels of nesting in some methods.

Compilers code was never pretty, but even by those standard, I feel like it is a very-very hard to maintain code by humans.

spinel_codegen.rb is an eldritch horror. I always get spaghetti code like this when using Claude, and I've been wondering if I'm doing something wrong. Now I see an application that looks genuinely interesting (not trivial slop) written by someone I consider to be a top notch programmer, and the code quality is still pretty garbage in some places.

For example infer_comparison_type() [1]. This is far from the worst offender - it's not that hard to read - but what's striking here that there is a better implementation that's so simple and obvious and Claude still fails to get there. Why not replace this with

    COMPARISON_TYPES = Set.new(["<", ">", "<=", ">=", "==", "!=", "!"])

    def infer_comparison_type(mname)
      if COMPARISON_TYPES.include?(mname)
          "bool"
      else 
        ""
      end
      # Or even better, strip the else case
      # (Which would return nil for anything not in the set)
    end
This would be shorter, faster, more readable, and more easily maintainable, but Claude always defaults to an if-return, if-return, if-return pattern. (Even if-else seems to be somewhat alien to Claude.) My own Claude codebases are full of that if-return crap, and now I know I'm not alone.

Other files have much better code quality though. For example, most of the lib directory, which seems to correspond to the ext directory in the mainline Ruby repo. The API is clearly inspired by MRI ruby, even though the implementation differs substantially. I would guess that Matz prompted Claude to mirror parts of the original API and this had a bit of a regularizing effect on the output.

[1] https://github.com/matz/spinel/blob/98d1179670e4d6486bbd1547...

Compiler code can be pretty if you have the time to maintain it. Compilers are some of the most modular applications you can build with hard boundaries between subsystems and clear handoffs at each level.

The problem is that people often do not have the time to refactor once they have gotten the thing to work. And the mess keeps growing.

Obviously it doesn't matter much now if it's maintabable by hand or not. If code is passing tests and benchmarks, I am happy.

But I am not sure that huge files are easy for the AI to work with. I try to restrict the files to 300 lines. My thinking is that if it's easy for a human to understand the code, it will be easy for coding agents, too.

Limitations

- No eval: eval, instance_eval, class_eval

- No metaprogramming: send, method_missing, define_method (dynamic)

- No threads: Thread, Mutex (Fiber is supported)

- No encoding: assumes UTF-8/ASCII

- No general lambda calculus: deeply nested -> x { } with [] calls

Assuming UTF-8/ASCII isn’t, IMO, a huge limitation, but some of the others likely are, for quite a few programs. Removing them also will require serious work, I think.

This removes a large portion of the magic of Ruby.
Curious why "no threads" when the ruby scheduler and underlying pthread implementation should work fine in C land. I guess to be "zero dependency"? Seems an odd trade-off to me, unless optional "extensions" are planned / omitted for later implementation etc.
I don’t see anywhere that it’s something they specifically decided not to support. Probably they just haven’t gotten around to it yet? Multithreading is notoriously difficult to get right.
> No eval: eval, instance_eval, class_eval

> No metaprogramming: send, method_missing, define_method (dynamic)

> No threads: Thread, Mutex (Fiber is supported)

Speaking as someone who has written a lot of Ruby code over the years, utilizing every single one of these features of Ruby, I have to say this is the version of Ruby I've evolved to want: simpler and easier to understand but with the aesthetic beauty of Ruby intact.

IMO this more limited variant of Ruby is more practical now that we have extremely productive code generation tools in the form of LLMs. A lot of meta-programming ostensibly exists to make developers more productive by reducing the amount of boilerplate code that has to be written, but that seems no longer necessary now that developers aren't writing code.

The benefit of meta programming was never having less code to write.

It was having less code to read.

I see this being useful in infrastructure tools. Imagine a statically compiled bundler that can also do the job of RVM and friends (installing Ruby) but it is still written in Ruby.

The classic Ruby buildpack is written in Ruby but we have to bootstrap it with bash and it's annoying and has edge cases. The CNB is written in rust to not have that problem and the idea that you can ship a single binary with no dependencies is really powerful.

As the son of a geologist, I find the name a great choice.
i have wanted to be able to compile ruby to a binary for some time – and have dreamed of poking at this problem with claude – so this is pretty cool.

if you can get a Rack compatible web server to build… i'd waste some serious time playing with this.

I will eat the downvotes to say what I actually think.

Unless this gets back eval, metaprogramming and threads this isn't all that interesting as an actual language. There are plenty of compiled languages out there. Metaprogramming is what makes Ruby interesting and expressive.

I know that this is just an experiment, but I've seen plenty of cases where stuff exactly like this gets forced into use in production because someone established in the company thinks some new experimental tool is "cool" and "the future".

---

Also, I would like to direct people to take a look at Factor programming language that both compiles into fairly efficient binaries and has amazing metaprogramming features inspired by Lisp and Smalltalk. It doesn't have real threads either, though, which is extremely unfortunate.

https://factorcode.org/

Antis: "If AI is so useful, where are the AI shovelwares? Where are the AI open source contributions? It's all hype" 6 months later: Matz used Claude and now Ruby runs 86 times faster after 1 month of work

At this point it's impossible to take antis seriously at all. Every claim is disproven simply by the passage of time. History will remember them just like the dot-com antis (that is, it won't)

Would love to see Guido do the same with Python w/ Claude to see what the end result is.
Interesting that Matz built this in about a month with Claude. The limitations (no eval, no metaprogramming) basically define a 'compilable Ruby subset'.. similar to what mruby does but targeting native executables instead of embedded. The pragmatic approach of generating C rather than LLVM IR makes sense for a first version you get portability and debuggability for free.