iris-decompiler
v1.1.1
Published
decompiles bytecode into readable luau
Readme
iris-decompiler
A Luau / Roblox bytecode decompiler. Parses compiled Luau bytecode and reconstructs readable Luau source. Ships as a library plus a small CLI — no server, no runtime dependencies (Node's standard library only).
Install / build
npm install
npm run build # compiles src -> dist (CommonJS + .d.ts types)Library usage
import { Decompiler } from "iris-decompiler";
// From raw bytes (Uint8Array / Buffer)
const result = Decompiler.decompile(uint8Array); // or { bytes }
console.log(result.source); // reconstructed Luau
// From a base64 string
const r2 = Decompiler.decompile({ base64: b64String }); // r2.decodedFromBase64 === true
// Disassembly instead of decompilation
const asm = Decompiler.disassemble(uint8Array); // all protos
const one = Decompiler.disassembleProto({ bytes }, 0); // single proto by index
// Low-level parse only (inspect the IR)
const { program } = Decompiler.parse(uint8Array);decompile accepts either a Uint8Array or an object { bytes?, base64?, name? }.
It returns { source, program, decodedFromBase64 }. Malformed input throws
DecompilerError.
Direct function exports
import { decompile, disassemble, parseBytecode, base64Decode, Op, ConstKind } from "iris-decompiler";| Export | Purpose |
|---|---|
| Decompiler | Object API (methods above) |
| decompile(program) / decompileProto(...) | Core decompiler |
| disassemble(program) / disassembleProto(program, i) | Disassembly |
| parseBytecode(bytes, program, err) | Low-level parser |
| base64Decode(str) | Base64 → Uint8Array |
| Op, ConstKind, Program, Proto, Constant | Types / enums |
| DecompilerError | Error thrown on invalid input |
CLI
node bin/cli.js <file> # decompile to stdout
node bin/cli.js --disasm <file> # disassemble to stdoutThe CLI also accepts a base64 file and auto-decodes it.
After npm link or global install it's available as iris-decompiler.
Browser usage
Build the standalone bundle (needs the dev deps installed):
npm run bundle # writes browser/iris-decompiler.js (~56 KB, minified)Then drop it into any HTML page — everything runs client-side, nothing is uploaded:
<script src="iris-decompiler.js"></script>
<script>
// bytes: Uint8Array of Luau bytecode
const source = IrisDecompiler.decompile(bytes);
const asm = IrisDecompiler.disassemble(bytes);
const src2 = IrisDecompiler.decompileBase64(base64String);
</script>A ready-made demo page lives at browser/example.html
(file picker + base64 paste box). Preview it locally with node serve.js
then open http://127.0.0.1:8123/example.html
Bytecode version support
Luau bytecode versions 3–13 (and the version-100 "classes" format). Anything
outside that range is rejected with a clear error, e.g. current Roblox client
bytecode is version 14 → bytecode version mismatch (expected [3..13], got 14).
Test fixtures
test-fixtures/ contains sample bytecode. animate.bin and last_raw.bin
decompile to ~568 lines of Luau; health.bin is version 14 and is expected to
be rejected.
node bin/cli.js test-fixtures/animate.bin