Elden Ring, modded,
on Linux and macOS.
./ermod-engine --mods ~/mods
Lua mods that run in the live game, and modded params without ModEngine. No toolchain, no Windows, no installer, and your game install is only ever read.
Linux x86-64 and macOS Apple Silicon. Both archives carry the same Windows runtime the game loads.
Before you play
Modded play means playing with anti-cheat disabled. These three are not fine print.
- Modded sessions never reach FromSoftware's servers.
-
Easy Anti-Cheat never runs, and the one launch that does risk a ban is
the game's normal Steam launch with a modified
regulation.binin place. The install guide has the rules. - The engine never touches your install.
-
It reads the game directory and writes nothing into it, so Steam's
integrity check has nothing to revert. Your own
regulation.binis never overwritten. - Your vanilla save is never played on.
- Mods run against a profile, a separate save the engine creates. It can copy your characters in, reading your save and never writing it.
What it does
Lua mods, live. Drop .lua files in the mods directory
and they run in the game. Each mod is sandboxed in its own VM with only
the modules it declares; one that misbehaves is disabled on the spot and
the others carry on. Edit a file while the game runs and it reloads
within a second.
The game's live parameter tables, readable and writable: the same
data a regulation.bin holds, edited in the running game.
Mods can also draw an in-game overlay, report frame timing, and keep
their own settings between sessions.
A modded regulation.bin without ModEngine. Point the
engine at one and the game reads it instead of its own file.
Co-op with the same mods. The engine runs its own co-op, peer to peer between the players' machines, and holds a joiner until its game-changing mods match the host's. The co-op guide covers starting a session.
On Linux it runs the game under Proton; on macOS, inside a Wine bottle.
Either way it launches eldenring.exe directly and never the
anti-cheat wrapper, and refuses to run at all while Easy Anti-Cheat is
live.
A mod is one file
This one starts the Vagabond at level 60. Drop it in the mods directory; it loads on the next frame.
local mod = {
name = "level60",
version = "1.0.0",
run_at = "launch",
permissions = { "params", "log" },
}
function mod.on_launch(sdk)
local row = sdk.params.row("CharaInitParam", 3000)
row.soulLv = 60
end
return mod
permissions is the whole of what a mod can reach: a module
not listed is absent from the sdk table it receives, so it
cannot be called rather than merely refused. Eleven worked examples and the
full reference are in
the scripting guide.
Checking the download is ours
Every release is signed. The signature covers SHA256SUMS,
which pins each archive by hash, and travels as a Sigstore bundle
alongside it.
cosign verify-blob SHA256SUMS \
--bundle SHA256SUMS.sigstore.json \
--certificate-identity 18033717+Benehiko@users.noreply.github.com \
--certificate-oidc-issuer https://github.com/login/oauth
sha256sum --ignore-missing -c SHA256SUMS # macOS: shasum -a 256 --ignore-missing -c SHA256SUMS
Signature first, then checksums: checksums from the same page as the archive only prove the two agree, not that either came from us. On macOS, Gatekeeper refuses the first run of a browser download; the install guide says how to clear it.
Signing is keyless, so there is no private key to leak: the certificate records the identity that signed and is logged publicly in Sigstore's transparency log.
When the game updates
The engine is keyed to exact game builds. On one it does not recognise it
says so, disables every hook and lets the vanilla game run. It never
guesses. ermod-engine check-build answers why, and a newer
release is the fix.