A pure-Go implementation of Ruby — one static binary, full dynamism, zero cgo.
🌐 Website · 📚 Documentation
go-embedded-ruby compiles Ruby to bytecode and runs it on a stack VM in the
mruby/YARV lineage, with the lexer, parser and compiler embedded in the
binary so eval and runtime require keep working. Ruby objects are Go heap
objects, so Go's garbage collector is reused — there is no GC to write.
Because it is pure Go with cgo disabled, it cross-compiles trivially and is
the first Ruby you can embed inside a Go program with no C toolchain
(go-mruby needs cgo).
It is not another tree-walking interpreter: dispatch goes through mutable
per-class method tables (the project's objc_msgSend), so monkey-patching,
define_method, method_missing, singleton classes and reflection all fall out
for free. Semantics track Ruby 4.0, grown test-first against an MRI 4.0.5
and JRuby differential oracle, with systematic performance benchmarks against
both and validation across all six 64-bit Go targets.
| Repo | What it is |
|---|---|
| ruby | the interpreter: token/lexer/ast/parser/compiler/bytecode/vm/object, plus the rbgo CLI |
| docs | MkDocs Material documentation, versioned with mike, served at /docs/ |
| go-embedded-ruby.github.io | the Hugo landing page |
| brand | logos and brand assets |
The regexp engine lives in a sibling org: go-ruby-regexp/regexp — a pure-Go reimplementation of Onigmo (Ruby's regexp engine), reusable beyond Ruby.
- Pure Go, zero cgo. Trivial cross-compilation; a static binary by default.
- Bytecode VM + embedded front-end. Ruby's dynamism —
eval, runtimerequire, monkey-patching,method_missing— stays available at runtime. - Reuse Go's GC. Ruby objects are Go heap objects; nothing to collect by hand.
- Build-time stdlib selection. Only the libraries the
requiregraph reaches are embedded (build tags +//go:embed); the Go linker drops the rest. - Ruby 4.0 semantics, test-driven growth. Conformance is verified against
two independent Ruby 4.0 references — MRI (CRuby) 4.0.5 and JRuby — via a
three-way differential oracle, plus a subset of ruby/spec. The bar is real-world
Ruby: idioms and suites from reference applications such as Rails
(ActiveSupport
core_ext) and OpenVox/Puppet drive the work by demand. - Benchmarked and portable. Performance is measured against MRI and JRuby (pure-Go CGO=0 vs C and the JVM JIT), accelerated with go-asmgen where it helps, and validated on all six 64-bit architectures (amd64, arm64, riscv64, loong64, ppc64le, s390x).
- 100% test coverage is the target, enforced as a CI gate.
Phases 0–7 — done (core); Phase 8 (conformance & performance) active. The object model and essentially all of idiomatic Ruby run today, every feature differential-tested against MRI Ruby 4.0.5 (and JRuby) with 100% coverage enforced in CI across all six 64-bit arches:
- Values: integers, floats, strings, symbols, arrays, ordered hashes, ranges
(incl. beginless/endless),
Proc/lambda,Regexp/MatchData,Struct. - Methods & blocks: the full argument system (required/optional/
*splat/ keyword/**rest/&block),{ }/do…endblocks,yield,block_given?,Proc/lambda/stabby->(){},&procblock-pass,Symbol#to_proc, setter defsdef name=, endless methodsdef foo = expr,super. - Classes & modules: inheritance,
@ivars,new/initialize, constants and constant assignment, class methodsdef self.foo,includemixins,attr_accessor/reader/writer,Struct.new. - Metaprogramming:
method_missing,send/public_send,respond_to?,define_method,instance_eval/instance_exec,class_eval/module_eval/class_exec,instance_variable_get/set/defined?. - Control flow:
if/unless/while/until+ modifiers,case/when,begin/rescue/ensure/else/retry,break/next. - Collections: Array/Hash/Range with
EnumerableandComparable, both written once in embedded Ruby. - Strings: interpolation,
%/format/sprintf, and a broad method set. - Regular expressions:
/re/imxliterals,Regexp/MatchData,=~/match/scan/gsub/sub/splitand the match globals, on the pure-Go go-ruby-regexp/regexp engine (build stays CGO=0).
Mutable String, pattern matching case/in, Fiber, Thread and arbitrary-precision
Bignum have all landed; rbgo also binds 181 pure-Go go-ruby-* modules as
native require-able libraries — from the stdlib through
databases (mysql2, mongo, etcd, bolt), messaging (nats, kafka),
RPC / data (grpc, google/protobuf, arrow, parquet), web / security
(faraday, puma, graphql, saml, webauthn, acme, rbnacl, age) and
docs / observability (prawn, bleve, opentelemetry). (In the js/wasm
build the socket/OS-bound backends among these are compiled out — require
raises LoadError.) Still ahead is Phase 8
(conformance & performance); the
roadmap has the detail.
BSD-3-Clause.
