GitHub - Water-Run/luainstaller: A tool that packages Lua scripts into a binary executable.

4 min read Original article ↗

luainstaller packages a Lua script into a standalone executable that does not require a system lua command at runtime (similar to PyInstaller). The binary runs on the same platform family as the build host.

It supports official Lua 5.1 through 5.5 (LuaJIT is rejected) and is released under LGPL-3.0-or-later at GitHub.

The interpreter used for packaging, the headers, the linked runtime, and any Lua C modules copied into the bundle must share the same major.minor Lua ABI.

Install

A complete official Lua environment and luarocks are required:

luarocks install luainstaller

Confirm with:

Note

Lua 5.5 requires LuaRocks 3.13.0 or newer. Older LuaRocks releases do not recognize the 5.5 install ABI.

Usage

luainstaller can be used in two ways: as a command-line tool, or as a library from a .lua script.

The CLI has two names: luainstaller and luai. They share the same features (analyze, trace, build, and so on) but use different input syntax and different terminal output. luainstaller is the modern subcommand-style interface; luai is the short-option style closer to traditional Lua tooling. The grammars must not be mixed. Mapping:

Action luai luainstaller

Help

luai -h

luainstaller help

Version

luai -v

luainstaller version

Analyze

luai -a <entry>

luainstaller analyze <entry>

Trace

luai -t <entry>

luainstaller trace <entry>

Build

luai -b <entry>

luainstaller build <entry>

Logs

luainstaller logs

Unless noted otherwise, command-line examples use luai. Details: Usage.

Command line

Suggested order: confirm the source program runs → analyze/trace dependencies → build a directory bundle (onedir) → run with LUA_PATH and LUA_CPATH cleared → then build a single-file (onefile) if needed. The directory form exposes the manifest, generated C, and native libraries; onefile is self-extracting—if it fails, verify the matching directory bundle first.

Example:

lua test/runtime_bundle/main.lua direct
luai -a test/runtime_bundle/main.lua --max-deps 120
luai -t test/runtime_bundle/main.lua --max-deps 120
luai -b --dir test/runtime_bundle/main.lua \
  -o build/runtime-demo --max-deps 120
build/runtime-demo/runtime-demo Ada

After the directory bundle works:

luai -b --file test/runtime_bundle/main.lua \
  -o build/runtime-demo-onefile --max-deps 120
build/runtime-demo-onefile Ada

Expected output begins with hello Ada.

Common luai options:

  • --dir — directory bundle (default)

  • --file — single-file executable

  • -o — output path

  • --max-deps — limit on auto-discovered Lua dependencies (default is small; raise it for large apps)

  • -d static|runtime|manual — discovery mode (default static)

Before release, run the artifact at least once without a system lua and without LUA_PATH / LUA_CPATH, so missing dependencies are not hidden by the host. Platform limits: Platforms and native modules. Diagnosis: Troubleshooting.

Every generated distribution contains the Lua MIT notice, the luainstaller LGPL/GPL texts, third-party notices, generated C source, and relinking instructions. Preserve them when redistributing an artifact and add the notices/source required by application dependencies. Details: Relinking generated bundles.

Library use from .lua

After install, require("luainstaller") uses the same implementation as the CLI. The structured result contract applies to analyze, trace, compatibility, and bundle only. Success sets ok = true; failure sets ok = false and error (with type, message, and related fields). getLogs returns a list of log records; clearLogs returns a boolean. Version string: require("luainstaller").VERSION.

local luainstaller = require("luainstaller")

local analysis = luainstaller.analyze({
    entry = "app/main.lua",
    discovery_mode = "static",
    max_deps = 120,
})
if not analysis.ok then
    io.stderr:write(analysis.error.type, ": ", analysis.error.message, "\n")
    os.exit(1)
end

local built = luainstaller.bundle({
    entry = "app/main.lua",
    mode = "onedir",
    out = "build/app",
    max_deps = 120,
})
if not built.ok then
    io.stderr:write(built.error.type, ": ", built.error.message, "\n")
    os.exit(1)
end
print(built.executable)

Option meaning matches the CLI. Full API notes are in Usage.

Tested environments

luainstaller is exercised on systems of these types:

System Architecture

Windows 11

x86_64

Debian 13

x86_64

Rocky Linux 10

x86_64

Ubuntu 24.04 LTS

ARM64

macOS 26.x

ARM64

Documentation