go-embedded-ruby (rbgo) is a from-scratch Ruby — lexer, parser, compiler, bytecode VM and an AOT backend — that embeds in any Go program and cross-compiles to a single CGO-free binary. Built in the open as a digital common (commun numérique), free to use, study, modify and share under the BSD-3-Clause licence.
language/+core/ examples passing~100% of real Ruby parsed6 64-bit arches# a real Ruby, no cgo, no Ruby installed $ rbgo -e 'puts (1..20).reduce(:*)' 2432902008176640000 # AOT-compile the hot path and drop the front-end $ rbgo build --closed app.rb -o app rbgo build: app (1 method(s) AOT-compiled: Object#fib) rbgo build: closed-world — front-end dropped rbgo build: binary size 172.5 MiB # the real Puppet CLI, end to end $ rbgo run puppet_apply.rb Notice: Compiled catalog for in environment production in 0.00 seconds Notice: hi from rbgo cli Notice: /Stage[main]/Main/Notify[hello]/message: defined 'message'
No FFI, no libruby, no system Ruby. Drop a genuine, monkey-patchable Ruby object model into your Go binary and ship it anywhere.
A real object model — classes, mixins, method_missing, metaprogramming, Fiber. The Go API is deliberately small today: ruby.Run(src, out) runs a program on a fresh VM and writes its output to one writer. Calling a Ruby method from Go is not exposed yet.
CGO=0 by default. Cross-compiles to amd64, arm64, riscv64, loong64, ppc64le and s390x.
Ahead-of-time compilation of integer-bound methods to unboxed Go. Measured on this project’s own micro-benchmarks (darwin/arm64, whole-process wall time): 8.7× MRI+YJIT on the tight-loop case, 2.0× on recursive fib(35). Only methods the compiler can lower benefit.
23,511 ruby/spec language/ + core/ examples pass, gated in CI file by file: no spec file may pass fewer examples than its recorded row, so a regression is named rather than absorbed in a total. Only language/ and core/ are swept: library/, optional/ and security/ are not run, so this is not a percentage of Ruby. Front-end: ~100% of valid Ruby parsed across Rails + Puppet (2026-06).
rbgo build --closed bakes the program to bytecode and drops the front-end for a smaller binary.
Built from the go-ruby-* family — each a 100%-coverage, 6-arch stdlib module, bound natively.
fib(35))language/+core/ examples passing · gated per file, not by a totalLexer → parser → compiler → bytecode VM, end to end.
Classes, modules, inheritance, mutable method tables, @ivars, new/initialize, constants, include mixins, super, blocks & yield, block_given…
Integer (with Bignum promotion + arbitrary-precision literals, radix literals 0x/0o/0b/0d, bitwise/shift << >> & | ^ ~), Float, mutable …
Exception hierarchy, raise/rescue/ensure/else/retry (block- and method-level), non-local break/next, Kernel#loop, and the eager Enumerator…
define_method, instance_eval/instance_exec, class_eval/module_eval/class_exec, send/public_send, respond_to?, instance_variable_get/set/…
Interpolation, keyword args, endless methods (def foo = expr), beginless/endless ranges, the stabby lambda, multiple assignment, full …
Regexp bridge landed: /re/imx literals, Regexp/MatchData, =~/match/scan/gsub/sub/split and the match globals, on the pure-Go Onigmo engine (…
rbgo build landed: AOT method compilation to native Go (unboxed int64 kernels beat MRI+YJIT ~4×), and closed-world builds (rbgo build --…
Since July the work has been runtime conformance, measured against [ruby/spec](https://github.
One binary. Six architectures. No cgo, no runtime to install. Embed a real Ruby — or compile it away. Open infrastructure, governed as a commons.
Read the source on GitHub →