
Fabric Language Ruby
I don't know my version or loader
Made by Bownlux, A developer of RevivalSMP.net
A note on updates: big updates to this project will not come often, since most of my time goes into RevivalSMP.net and Retromod. Expect smaller maintenance releases (new Minecraft versions, JRuby bumps, bug fixes) rather than a steady stream of features. Issues and pull requests are still welcome.
Write Fabric mods in Ruby! This is a Fabric language module, the Ruby equivalent of fabric-language-kotlin. It is powered by an embedded JRuby runtime that ships inside the mod jar together with the full Ruby standard library.
Your mod's fabric.mod.json points an entrypoint at a .rb script, and this mod does the rest:
it boots JRuby (lazily, only when a Ruby entrypoint is actually needed), evaluates your script, and
hands the resulting Ruby object to Fabric Loader as a regular entrypoint. Ruby method names map to
Java automatically, so def on_initialize implements ModInitializer#onInitialize.
class MyRubyMod
LOGGER = org.slf4j.LoggerFactory.getLogger('my-ruby-mod')
def on_initialize
LOGGER.info("Hello from Ruby #{RUBY_VERSION}!")
end
end
MyRubyMod
Logging note: Minecraft ships slf4j only on 1.18.2+. Targeting older versions? Use Log4j, which exists on every supported version:
LOGGER = org.apache.logging.log4j.LogManager.getLogger('my-ruby-mod'), or just use plainputs.
Supported versions
Every Minecraft version Fabric supports, back to the very first (1.14). Two files are published per release. Install the one matching your Minecraft version:
| File | Minecraft | Java | Bundled runtime |
|---|---|---|---|
fabric-language-ruby-<v>+jruby.10.x.jar |
1.20.5 and newer (incl. 26.x) | 21+ | JRuby 10.0 (Ruby 3.4) |
fabric-language-ruby-<v>+jruby.9.4.x.jar |
1.14-1.20.4 | 8+ | JRuby 9.4 (Ruby 3.1) |
Both are the same mod (fabric-language-ruby, same features, same adapter); they differ only in the
bundled JRuby, because JRuby 10 needs Java 21 while older Minecraft runs on Java 8-17. Modrinth
serves the right file for your game version automatically. Fabric Loader 0.16.0+ is required.
Fabric Language Ruby is fully compatible with fabric-language-kotlin: both language modules can be installed at the same time, so Ruby mods run alongside Kotlin mods in one modpack. This is verified in testing by running both adapters plus a Kotlin-written mod (Ledger) on one server.
For players
If a mod you installed needs this library, download the file matching your Minecraft version from
Modrinth (or the GitHub releases) and drop
it into your mods/ folder, next to the mod that needs it. There is no configuration.
For mod developers
Setting up
Add the ruby adapter to your entrypoints in fabric.mod.json, point the value at a Ruby script
inside your mod jar, and depend on fabric-language-ruby:
{
"schemaVersion": 1,
"id": "my-ruby-mod",
"version": "1.0.0",
"entrypoints": {
"main": [
{
"adapter": "ruby",
"value": "my_ruby_mod/main.rb"
}
]
},
"depends": {
"fabricloader": ">=0.16.0",
"fabric-language-ruby": ">=1.0.0"
}
}
my_ruby_mod/main.rb lives in your mod's resources (so it ends up at that path inside your
jar). Give the directory a unique, mod-specific name, because every mod shares one JVM classpath.
The last expression of the script is the entrypoint. In the example at the top it is the class itself, which the adapter instantiates.
Entrypoint value syntax
value |
Meaning |
|---|---|
"path/to/script.rb" |
Evaluate the script; its last expression is the entrypoint. A class is instantiated with new; a module, instance, or lambda is used as-is. |
"path/to/script.rb::Some::Constant" |
Evaluate the script, then resolve the (namespaced) constant. A class is instantiated; anything else is used as-is. |
"path/to/script.rb::Some::Constant#method_name" |
Resolve the constant and bind method_name. For a class, an instance method wins (a new instance is created for it); otherwise a class/module-level method (module_function, def self.) is bound. For any other constant the method is bound on the object itself. |
Examples of all three forms:
# value: "my_mod/main.rb". The last expression is a lambda, which works for
# single-method entrypoints like ModInitializer.
-> { puts 'initialized!' }
# value: "my_mod/main.rb::MyMod::Initializer"
module MyMod
class Initializer
def on_initialize
# ...
end
end
end
# value: "my_mod/main.rb::MyMod#init"
module MyMod
module_function
def init
# ...
end
end
Method-reference and lambda entrypoints route every method of the entrypoint interface to that
one method/lambda, so they suit single-method interfaces like ModInitializer; implement
multi-method entrypoint interfaces with a class or module instead.
How Ruby objects become Java entrypoints
JRuby coerces your Ruby object into the requested entrypoint interface
(ModInitializer, ClientModInitializer, DedicatedServerModInitializer, custom interfaces, and so on).
Method names map automatically: a Java call to onInitialize dispatches to your Ruby
on_initialize (or a literal onInitialize if you define that instead).
A script is evaluated at most once per mod, no matter how many entrypoints reference it. If the
last expression is a class, each entrypoint reference gets its own instance; if it is an
instance (e.g. MyMod.new) or a module, that one object is shared.
One shared JRuby runtime
All Ruby mods run in a single shared JRuby interpreter. Top-level constants, global variables,
monkey-patches, and java_imports are visible across every Ruby mod, and a later-loading mod can
reopen (or clobber) another mod's top-level classes. Keep everything inside one uniquely-named
module per mod (module MyRubyMod ... end), do java_import inside your own class/module rather
than at the top level, and avoid $globals.
Multi-file mods and the standard library
require_relative works between the scripts in your jar, and the full Ruby standard library is
available with plain require:
require 'json'
require_relative 'helper'
Using gems (build-time vendoring)
Installing gems at runtime is not supported (the stdlib lives inside a jar), but gems can be
vendored into your mod while it is being built. This repository ships a Gradle helper,
gradle/gem-vendor.gradle, that runs the whole pipeline: it resolves
the gems you list (plus their transitive dependencies) from rubygems.org using a build-time JRuby,
copies each resolved gem into your mod's resources, and generates a vendor/setup.rb that puts
every gem on $LOAD_PATH with the uri:classloader: scheme.
Copy the file into your project and wire it up in build.gradle:
apply from: 'gradle/gem-vendor.gradle'
gemVendor {
vendorPath = 'my_ruby_mod/vendor' // resource path the gems land under
gem 'dentaku', '3.5.7'
// more gem 'name', 'version' lines as needed; transitive dependencies
// are resolved automatically, list one explicitly to pin its version
}
Then load the gems from your script with a plain require:
require_relative 'vendor/setup'
require 'dentaku'
What can and cannot work:
- Pure-Ruby gems work, and so do gems that ship a prebuilt JRuby jar (concurrent-ruby, for example). Gems with C extensions fail at install time, which is the right moment to find out.
- Gems that read or write their own files on disk will not work from inside a jar.
- Vendoring redistributes the gems inside your jar. Check that each gem's license permits that and attribute it as the license requires.
- If you release for both variants, build the vendor step per variant (the helper uses the JRuby version you give it), so gem resolution matches the Ruby version your users run.
The example mod in src/testmod vendors dentaku this way, and every CI build
exercises the pipeline on both variants. If you would rather vendor by hand, the generated
setup.rb shows everything that is needed: each gem's require directory added to $LOAD_PATH as
uri:classloader:/<resource path> (all mod resources are on the shared classpath).
Calling Minecraft and Fabric API
Java interop is standard JRuby:
class MyRubyMod
java_import 'net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents'
def on_initialize
on_started = lambda do |server|
puts "server started: #{server.class.java_class.simple_name}"
end
ServerLifecycleEvents::SERVER_STARTED.register(
on_started.to_java(ServerLifecycleEvents::ServerStarted)
)
end
end
MyRubyMod
Important: Fabric API's
Event#register(T)is a generic method, so JRuby cannot infer the listener interface from a bare block. Convert explicitly withlambda.to_java(TheListenerInterface)as above. For non-generic Java methods that take a functional interface, passing a block directly works fine.
A note on class names per Minecraft era: on Minecraft 26.x and newer the game is unobfuscated,
so Ruby scripts can call Minecraft classes by their real (Mojang) names. On older versions
(1.14-1.21.x) Minecraft's own classes have intermediary names at runtime
(net.minecraft.class_310 style). Entrypoint interfaces, Fabric API, Fabric Loader API
(including FabricLoader.getInstance.getMappingResolver to translate names), and all Java
libraries are unaffected and keep their normal names.
Limitations
- No mixins from Ruby. Mixins need compile-time classes; a Ruby mod that requires them should ship a small Java/mixin core alongside its Ruby entrypoints (both can live in one jar).
- No runtime gem installation. Vendor gems at build time instead, as explained above.
- Scripts targeting the legacy file should stick to Ruby 3.1 features (the modern file runs Ruby 3.4).
Example mod
A complete working example lives in src/testmod: a mod written entirely in Ruby
that logs from its main entrypoint, uses require/require_relative, calls a vendored gem
(dentaku), and registers a Fabric API lifecycle callback. Run it against a dev server with:
./gradlew runTestmodServer
Building from source
Requires JDK 25 (the built jars still run on Java 8/21+ as described above).
./gradlew build # modern variant -> build/libs/*+jruby.10.*.jar
./gradlew build -Pvariant=legacy # legacy variant -> build/libs/*+jruby.9.4.*.jar
Each build runs the unit test suite against that variant's JRuby and also produces a standalone
example-mod jar (*-testmod.jar). JRuby is bundled jar-in-jar (org.jruby:jruby-core +
org.jruby:jruby-stdlib); Fabric Loader deduplicates nested jars by version if several installed
mods ship JRuby.
Versioning
<modVersion>+jruby.<bundledJRubyVersion>, for example 1.0.0+jruby.10.0.6.0. This mirrors
fabric-language-kotlin's scheme. Only the part before + participates in dependency resolution, so
"fabric-language-ruby": ">=1.0.0" matches both variant files.
License
- Edition: Minecraft Java
- File type: .jar
- Minecraft versions listed: 1.14, 1.14.1, 1.14.2
- How to install: Install the matching mod loader (Forge, Fabric or NeoForge) for your Minecraft version. → Download the .jar. → Put it in the .minecraft/mods folder and launch that loader profile.
- Where to get it: Opens on Modrinth — not every file is mirrored on our own servers.
Install steps are the general flow for this file type — How to install Minecraft Java mods & modpacks walks through it step by step.
- Ships as fabric-language-ruby-1.0.0+jruby.9.4.15.0.jar — drop this file into the mods folder
- Download size: 30.6 MB
- Download link checked 4 Sept 2026 — working
These come from our own check of the pack file, not from the source page.