# Prometheus rewrites Lua source into a table of encrypted strings and flattened control flow

> Prometheus is a Lua obfuscator written in pure Lua that applies AST transformations such as control-flow flattening and constant encryption to make source hard to read and reverse. It ships as a CLI, a browser playground and a Docker-based test suite.

**prometheus-lua/Prometheus** — Lua Obfuscator written in pure Lua

- Repository: https://github.com/prometheus-lua/Prometheus
- Website: https://prometheus-lua.github.io/Prometheus/
- Stars: 531 · Forks: 233
- Language: Lua
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/prometheus-lua-prometheus

## An obfuscator that works on the AST rather than on the text

Prometheus is a Lua obfuscator written in pure Lua. The mechanism it describes is AST-based transformation: it applies a range of transformations to make source code significantly harder to read, analyze and reverse engineer, and the named techniques are control-flow flattening and constant encryption, along with other Lua-specific obfuscation strategies.

That distinction matters more than it might sound. A text-level obfuscator mangles identifiers and comments, which is a cosmetic layer over a program whose structure is still visible. An AST-level tool can restructure the program itself, replacing a sequence of statements with a state machine that dispatches on a numeric state variable, and can move every string literal into a table that gets decoded at runtime. The result is not the original program with ugly names, it is a different program that computes the same thing.

The project says it was inspired by the javascript-obfuscator, which is the closest conceptual reference: a JavaScript tool that does the same family of transformations for the same reasons.

The target platforms are Lua 5.1 and LuaU, with LuaU described as basic support available but still not fully finished. The topic tags on the repository list lua51, luajit and luau, plus minification and obfuscation, which tells you the intended deployment surface is Roblox-style and game scripting rather than server-side Lua in a large backend.

## The one-line install ships its own Lua runtime

There are three ways to run it, and the packaging decision in the first one is worth noticing. The README asks you to try the browser version first, pointing at a playground hosted on GitHub Pages, which is a sensible default when the tool is a pure Lua program that runs anywhere a Lua interpreter does.

For the command line on Linux and macOS, the install is a single pipe:

```bash
curl -fsSL https://raw.githubusercontent.com/prometheus-lua/Prometheus/master/install.sh | sh
```

Once that is in place, the CLI is called directly:

```bash
prometheus-lua --version
prometheus-lua --preset Medium ./your_file.lua
```

The important detail here is that the release bundle includes a Lua runtime, so no separate Lua install is required for the packaged CLI. That removes the usual friction of a toolchain that expects you to already have a specific interpreter version.

Maintenance of the install is handled by the CLI itself, with a dedicated subcommand:

```bash
prometheus-lua update
```

And removal is a manual step rather than a flag, which tells you where the tool put things on disk:

```bash
rm -f ~/.local/bin/prometheus-lua && rm -rf ~/.local/share/prometheus-lua
```

Both paths in that command matter. The binary lives in ~/.local/bin and the data, including the bundled runtime, lives under ~/.local/share/prometheus-lua.

## Running from source needs a Lua 5.1 interpreter and cli.lua

If you would rather not pipe a script into a shell, the source route is three commands:

```bash
git clone https://github.com/prometheus-lua/Prometheus.git
cd Prometheus
lua cli.lua --preset Medium ./your_file.lua
```

The third command is the same as the packaged CLI invocation with the interpreter in front of it, which makes the relationship between the two paths obvious. The packaged prometheus-lua binary is a wrapper around the same cli.lua entry point.

The requirements differ between the two routes and the README is explicit about it. Packaged CLI releases include a bundled Lua runtime. For source usage, Prometheus requires LuaJIT or Lua 5.1+, and Lua 5.1 binaries are pointed at a SourceForge download of the 5.1.5 tools executables.

So the interpreter requirement is LuaJIT or 5.1 and up, and the version the project tests against is 5.1. If your code targets a newer Lua dialect, note that the project lists Lua 5.1 as a supported target and LuaU as partially supported, and nothing in the documentation claims support for the 5.2, 5.3 or 5.4 line.

The repository is also a mixed-language workspace. Alongside the Lua sources there is a package.json declaring a pnpm workspace with honkit for the documentation and a web package, a pnpm-workspace.yaml, a Dockerfile and a docker-test-runner.lua. The documentation site and the browser playground are part of the same tree, built with node scripts, while the core obfuscator is Lua.

## What the obfuscated output actually looks like

The README demonstrates the transformation on the smallest possible input. The original file is two lines, a comment and a print:

```lua
-- input.lua
print("Hello, World!");
```

The obfuscated file comes back as a single return of an immediately invoked function whose body opens with a local table of encoded strings. The visible fragment is a long list of base64-shaped values assigned to a local named L, followed by more table entries, and the README notes that the remaining obfuscated output is omitted.

Read that shape carefully and you can see the constant encryption working. The string literals are no longer literals in the source; they are table entries that the runtime decodes, which is why the values look like encoded blobs rather than the words they represent. The function wrapper with the ... variadic parameter is there because the decoded values have to be handed to the program somehow, and the immediate call keeps the original top-level statements inside a scope where the decoded table is in reach.

Control-flow flattening is not visible in this particular example, because a single print has no branch to flatten. The README example is deliberately trivial, so the real structure of a flattened program is something you have to see in the documentation, where the configuration and preset options are described.

## Presets decide how far the transformations go

The CLI invocation in every example uses a preset, and the value used throughout the documentation is Medium. A preset is the knob that controls which transformations are applied and how aggressively, which is the standard arrangement for this class of tool and the thing you will spend most of your time tuning.

What the README does not spell out is the list of preset names beyond Medium, or the exact set of transformations each one turns on. That detail lives in the documentation site, which the README points to for the full documentation including the getting started guide, and for more advanced use cases, configuration and presets.

The same split applies to configuration generally. The test runner accepts a custom config file through a -c flag, which tells you a configuration file is a first-class concept rather than just a preset name on the command line. Since the tool is written in pure Lua, a config is presumably a Lua file, and the test script is named config.lua in the example, which supports that reading.

So the practical workflow is: run a preset, look at what happened to your file, and if the balance is wrong, write a config and pass it in. The one thing the README does not do is document a rollback, so keep the original file under version control before you overwrite it.

## The test suite runs in Docker against both lua5.1 and Luau

The tests are not run with a plain interpreter. The README says the test suite runs inside Docker with lua5.1 and Luau, and the runner script is invoked like this:

```bash
./scripts/run-tests.sh           # Run all tests (default: 10 iterations)
./scripts/run-tests.sh -b        # Build image and run tests
./scripts/run-tests.sh -n 5      # Run with 5 iterations
./scripts/run-tests.sh -c config.lua  # Use a custom config
./scripts/run-tests.sh -v        # Verbose output
```

The default of 10 iterations is a hint about how the suite is structured. A single obfuscation run is deterministic, so repeating it ten times suggests the suite is fuzzing or sampling the transformation pipeline, checking that generated output still parses and still behaves. The -n flag lets you change that count.

The Dockerfile shows exactly what the environment contains. It starts from ubuntu:24.04, installs lua5.1 along with git, unzip and curl, and then downloads a pre-built Luau binary from the luau-lang releases, unpacks just the luau executable into /usr/local/bin and makes it executable. The image verifies both interpreters at build time by running lua5.1 -v and by writing and running a one-line print check under luau. The entrypoint is lua5.1 running docker-test-runner.lua.

Two things follow from that. You need Docker to run the suite, and the CI image pins Ubuntu 24.04 with the latest Luau release rather than a versioned one, so the Luau side of the test matrix can change under you when that release changes.

## The Prometheus License asks for visible attribution in commercial products

The licence is the part of this project most likely to surprise you, and it is not MIT despite being described as modified MIT-style.

Prometheus is licensed under the Prometheus License, a modified MIT-style license. You are free to use, modify and distribute the software, including for commercial purposes, under stated conditions. The first condition is that any commercial product, wrapper or service, including SaaS or hosted solutions, that uses or integrates Prometheus must include clear attribution, in the form of this line:

```text
Based on Prometheus by Elias Oelschner, https://github.com/prometheus-lua/Prometheus
```

The attribution has to be visible in the product's UI, its documentation and its public website. That is a stricter requirement than a copyright notice in a source header, because it demands a user-facing surface. It also applies to SaaS and hosted solutions, so if you offer the obfuscator as a service you owe credit in the interface.

Two carve-outs are explicit. The obfuscated output files generated by Prometheus do not need to include any license or copyright notice, so your end users do not have to see the attribution, only you do. And derivative works and public forks must include a statement in their README noting that they are based on Prometheus.

The repository licence is recorded as a custom one that GitHub cannot classify, so the LICENSE file linked from the README is the authoritative text. This is a documentation point rather than legal advice, but if you are shipping a commercial product built on it, get the attribution wording right before launch rather than after.

On maintenance, the last push to the repository was on 2026-07-27, with recent releases v0.2.11.1 and v0.2.10 both on 2026-05-06 and v0.2.9 on 2026-03-28. The version is still in the 0.2 range, which is worth keeping in mind before you depend on the output format.

## Conclusion

Prometheus suits a Lua developer who needs to make a shipped script harder to read or modify, and who can accept that the result is slower and harder to debug, on Lua 5.1 or with basic LuaU support. It does not suit anyone who needs LuaU to be fully finished, who needs source maps or debuggable output, or who is looking for protection against a determined reverse engineer rather than casual reading. Before adopting, run prometheus-lua --preset Medium over a script and confirm the result still executes, and read the attribution terms in the Prometheus License, which require visible credit in any commercial product that uses or integrates it.

## FAQ

### How do I install the Prometheus Lua obfuscator?

On Linux or macOS run the install script from the README, which pipes install.sh into sh and places the CLI in ~/.local/bin. The release bundle includes a Lua runtime, so no separate Lua install is needed.

### Which Lua versions does Prometheus support?

Lua 5.1 is fully supported and LuaU has basic support that the README says is still not fully finished. For source usage, Prometheus requires LuaJIT or Lua 5.1+.

### Can I use Prometheus in a commercial product?

Yes, under the Prometheus License, which is a modified MIT-style license. Any commercial product, wrapper or service that uses or integrates it must include visible attribution in its UI, documentation and public website, while the obfuscated output files themselves need no notice.

### How do I run the Prometheus test suite?

The suite runs inside Docker using ./scripts/run-tests.sh, which defaults to 10 iterations against lua5.1 and Luau. Use -b to build the image, -n to change the iteration count, -c for a custom config and -v for verbose output.

## Sources

- [Issues](https://github.com/prometheus-lua/Prometheus/issues)
- [Project website](https://prometheus-lua.github.io/Prometheus/)
- [prometheus-lua/Prometheus on GitHub](https://github.com/prometheus-lua/Prometheus)
- [README](https://github.com/prometheus-lua/Prometheus/blob/master/README.md)
- [Releases](https://github.com/prometheus-lua/Prometheus/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/prometheus-lua-prometheus
