Natalie compiles Ruby ahead of time and borrows the Ruby specs
a work-in-progress Ruby compiler, written in Ruby and C++
At a glance
- What is it?
- Natalie is a work-in-progress Ruby implementation written in Ruby and C++, with an ahead-of-time compiler that uses gcc or clang as the backend and a REPL that performs incremental compilation. The parts that make it interesting to read are the honest warning that there is much work left to do, the test suite split between the community's ruby/spec files and the project's own tests, and the copyright table that tracks every borrowed file.
- Who is it for?
- Natalie is worth following if you are interested in how a Ruby implementation is put together, because it is small enough to read, it uses the same conformance suite as every other Ruby implementation, and the maintainer works in public with hacking session videos. It is not a Ruby you should run anything real on, since the documentation says plainly that there is much work left to do before it is useful, and it is a poor fit for a team that needs a supported interpreter.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 67 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
An ahead-of-time compiler with an incremental REPL on top
Natalie is described in one line as a work-in-progress Ruby implementation, and the two sentences after that give the shape. It provides an ahead-of-time compiler using C++ and gcc or clang as the backend, and the language has a REPL that performs incremental compilation. That combination is the interesting engineering decision. A Ruby implementation that runs a bytecode virtual machine inherits a large amount of machinery, and one that interprets the source directly gives up the performance argument entirely, so compiling to native code through a C++ backend is the choice that could eventually make Natalie fast, and the REPL is how you can work on a compiler while it is still incomplete. The primary language of the repository is Ruby, with C++ underneath, which is why the compiler itself runs inside another Ruby. The maintainer is candid, with the note that there is much work left to do before it is useful and an invitation to help.
The compiler needs a system Ruby, and that is where the build breaks
Natalie requires a system Ruby, MRI, to host the compiler, for now, and the build prerequisites are listed in full: git, autoconf, automake, libtool, GNU make, gcc or clang, and Ruby 3.2 or higher with dev headers. rbenv is preferred for installing Ruby, and the documentation notes that installing rbenv-aliases alongside rbenv helps match Ruby versions like 3.2 to the latest patch release. ccache and compiledb are optional but recommended, and Natalie is tested on macOS and Ubuntu Linux, with Windows not yet supported. The build itself is three commands:
git clone https://github.com/natalie-lang/natalie
cd natalie
rakeThe troubleshooting section is worth reading before you build, because the failure modes are specific. The first rule is do not use sudo, and if you have already made that mistake you should sudo rm -rf build and try again. The second class of failure is a file permission error, such as being unable to write to /usr/lib/ruby, which means the gems are installed somewhere that needs root, and the two fixes are to use rbenv so the Ruby and its gems live in your home directory, checked with rbenv version and selected with rbenv shell, or to set GEM_HOME yourself, for example by creating ~/gems and exporting GEM_HOME=~/gems, with the trade that you have to remember it in every new terminal. The third is a missing bundler, which means the system did not install it alongside Ruby, and gem install bundler fixes it.
Three ways to run it, from a prompt to a native binary
The usage section is three commands, and the difference between them is the compiler story. The REPL is bin/natalie on its own, and because it compiles incrementally it is the fast loop for experimenting with the language. Running a Ruby script is bin/natalie examples/hello.rb. And compiling a file to an executable is:
bin/natalie -c hello examples/hello.rb
./helloThat last form is the one that shows what the project is for, since it produces a native program rather than a script that has to be interpreted. The examples directory shows the range of what the implementation covers, with about.rb, boardslam.rb, evaluate.rb, fib.rb, gtk3.rb, hello.rb, linenoise.rb, sslsocket.rb and webserver.rb, so there is a graphical example and two network ones, which is a reasonable sample of what a Ruby implementation has to reach before it is interesting. The Dockerfile takes the same image further, building from a ruby:4.0 base and installing build-essential, autoconf, libtool, clang, lcov, clang-tidy, libclang-dev, lldb, gdb, python3 and ccache, and the entrypoint is the natalie binary itself, so a container gives you a REPL, a script runner and a compiler with no host setup at all.
ruby/spec for conformance, test/ for the gaps
The test arrangement is the part of this repository that other implementation projects borrow. The files in spec/ come from the ruby/spec project, a community-curated repository of test files that any Ruby implementation can use to compare its conformance to what MRI, Matz's Ruby Interpreter, does, and the project copies specs over as it implements the part of the language they cover. Everything in test/ is written by the Natalie project itself, tests that helped bootstrap certain parts of the language or that were not covered as much as the project would like by the official specs, and the stated purpose is to supplement the specs in spec/. Running a single test is like running a normal Ruby script, bin/natalie spec/core/string/strip_spec.rb, which runs the test and reports failures, and running everything expected to pass is rake test. When you only want a handful, there is a helper script at test/runner.rb:
bin/natalie test/runner.rb test/natalie/if_test.rb test/natalie/loop_test.rbThe value of the arrangement is that it makes the size of the remaining work measurable, since the spec suite is a shared yardstick and a gap in the spec directory is a gap in the language.
The Docker image is the path of least resistance
For anyone who wants to look at the project without installing a toolchain, the container is the answer, and the documentation gives five ways to use it:
docker build -t natalie .
docker run -it --rm natalie
docker run -it --rm natalie -e "p 2 * 3"
docker run -it --rm -v$(pwd)/myfile.rb:/myfile.rb natalie /myfile.rb
docker run -it --rm --entrypoint bash natalieThe third line evaluates an expression immediately, the fourth runs a file from the host, and the fifth drops you into a shell inside the image. The Dockerfile itself is a good summary of the toolchain, and two details in it are worth noting. It runs git submodule update --init --recursive after copying the.git directory and the.gitmodules file, because the build depends on submodules, and it has two optional build arguments, NEED_VALGRIND and NEED_CASTXML, that build Valgrind 3.24.0 from source and fetch a prebuilt CastXML when they are needed. The comment explains why Valgrind is not simply installed, that the version on the image is too old to handle compressed debug symbols. The environment is pinned further with ENV LLVM_CONFIG pointing at llvm-config and LC_ALL set to C.UTF-8, and the build runs rake build_${NAT_BUILD_MODE} with the mode defaulting to release.
Contributing means finding a method that is not there yet
The contribution guidance is unusually concrete, and the reason is that the project is small and the work is a long tail. The easiest way to get started right now is to find a method on an object that is not yet implemented and make it yourself, and the project also points at its good first issues list. The maintainer works in public, with a playlist of hacking session videos on YouTube, and there is a Discord server, described as very quiet, that you are invited to join. The repository layout supports that kind of work, with src/ for the C++ compiler, ext/ for the extension code, include/ for the headers, lib/ for the Ruby parts of the compiler, bin/ for the driver, spec/ and test/ for the two test suites, examples/ for the sample programs, plus a Gemfile, a Rakefile, a Makefile that is one line and tells you to run rake instead, a .clang-format and a .clang-tidy configuration, a .devcontainer, an .amazonq directory, a .streerc, and a .ruby-version. There is no separate build system to learn beyond rake, and the one-line Makefile is an honest signal of that.
MIT, with a table of borrowed code
Natalie is copyright 2025, Tim Morgan and contributors, and is licensed under the MIT License, with the full text in the LICENSE file. The copyright section then does something most projects do not, which is list every file that was copied from elsewhere and who owns it. Some parts of the program are copied from other sources and the copyright belongs to the respective owner, and such notices are either at the top of the respective file, in the same directory in a file named LICENSE, or both. The table runs to more than a dozen rows. abbrev.rb is Akinori Musha under BSD, benchmark.rb is Gotoken under BSD, bigint.{h,c} is 983 under the Unlicense, cgi.rb and cgi/ are Wakou Aoyama under BSD, crypt.{h,c} is The Regents of the University of California under BSD, delegate.rb and formatter.rb are Yukihiro Matsumoto under BSD, dtoa.c is David M. Gay, Lucent Technologies, under a custom permissive licence, erb/util.rb is Masatoshi SEKI under BSD, ipaddr.rb is Hajimu Umemoto and Akinori Musha under BSD, find.rb is Kazuki Tsujimoto under BSD, linenoise is S. Sanfilippo and P. Noordhuis under BSD, matrix.rb is Marc-Andre Lafortune under BSD, minicoro.h is Eduardo Bart under MIT, and net/http and net/protocol.rb are Yukihiro Matsumoto and Minero Aoki under BSD. For a Ruby implementation, that is the most Ruby source code you can get your hands on, and the attribution is the price of it.
Editorial conclusion
Natalie is worth following if you are interested in how a Ruby implementation is put together, because it is small enough to read, it uses the same conformance suite as every other Ruby implementation, and the maintainer works in public with hacking session videos. It is not a Ruby you should run anything real on, since the documentation says plainly that there is much work left to do before it is useful, and it is a poor fit for a team that needs a supported interpreter. Before you try it, read the build prerequisites carefully, because the compiler runs inside a system MRI and the failure modes when that MRI is installed with sudo are the ones the troubleshooting section spends most of its words on, and check the spec directory to see how much of the language is actually covered rather than assuming.
Frequently asked questions
What is Natalie and how does it compile Ruby?
It is a work-in-progress Ruby implementation written in Ruby and C++, providing an ahead-of-time compiler that uses gcc or clang as the backend, plus a REPL that performs incremental compilation. The documentation is explicit that there is much work left to do before it is useful.
How do I build and run Natalie?
You need git, autoconf, automake, libtool, GNU make, gcc or clang and Ruby 3.2 or newer with dev headers, then run git clone, cd natalie and rake. The compiler itself runs inside a system MRI. To run it, use bin/natalie for the REPL, bin/natalie examples/hello.rb for a script, and bin/natalie -c hello examples/hello.rb to compile an executable.
What is the difference between the spec and test directories in Natalie?
The files in spec/ come from the ruby/spec project, the community-curated conformance suite any Ruby implementation can use to compare itself with MRI, and they are copied over as the language is implemented. Everything in test/ was written by the Natalie project to bootstrap parts of the language or to cover gaps the official specs do not.
Does Natalie support Windows?
Not yet. It is tested on macOS and Ubuntu Linux, and Windows is not yet supported. The project also ships a Dockerfile so you can build and run it in a container without a host toolchain.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/natalie-lang-natalie)Was this useful?