Lua runner with rich builtin stdlib
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Ondřej Hruška ccdbf1307c Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
.claude add sqlite module 3 weeks ago
assets Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
docs Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
lua Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
src Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
tmp expand tui with shorthand markup etc 2 weeks ago
.gitignore feat: add standard library — math, table, utils, os, log 3 weeks ago
.luarc.json fix up lua lib and language server config, add stubs, move demos 2 weeks ago
.stylua.toml add require support 2 weeks ago
Cargo.lock Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
Cargo.toml Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
Makefile Rework http to not reinvent the wheel for cookies, add fs.getScriptDir() 2 weeks ago
README.md add prototype permission based fs access 2 weeks ago

README.md

a

a embeds a Lua interpreter and adds a standard library and IO access, so a script can reach the outside world — today an HTTP client, SQLite and interactive terminal prompts, with more of the surface below planned — without additional setup.

a file.lua   # run a script
a            # start an interactive REPL

Run a with a script path to execute it, or with no arguments to start an interactive REPL.

The REPL

Running a with no arguments starts a read-eval-print loop in the same sandboxed environment used for scripts, with the full standard library available. It is convenient for trying out the library or exploring data.

  • Bare expressions print their value (1 + 12); tables are pretty-printed with utils.dump.
  • Statements that span several lines (a for loop, a function body) are detected as incomplete and keep reading until they parse.
  • Async calls such as os.sleep, http.get, and task.join suspend and resume just as they do in a script — each entry runs on the async executor.
  • Line editing and history are provided, with history persisted to ~/.a_history. Press Ctrl-D to exit (os.exit is not available in the sandbox).

Each entry is compiled as its own chunk, so a local declared on one line is not visible on the next — assign to a global (drop the local) to keep a value across entries.

What it is

a is not a Lua implementation; it embeds Lua 5.5 (via mlua) and adds the parts stock Lua omits. Plain Lua ships almost no standard library and no way to reach the outside world without C modules and a build toolchain. a provides a standard library written partly in Rust and partly in Lua, together with IO access.

The result is a single binary that runs a .lua file. There is no package manager, build step, or project scaffolding.

The standard library

The standard library is the main purpose of a. Available today:

  • Networking — HTTP client (WebSocket and MQTT are planned).
  • SQLite — access to embedded SQLite databases.
  • Filesystem — whole-file read/write and directory listing via fs, guarded by a per-script folder permission system (interactive grants recorded in access.json; --allow-fs, --no-fs and --sandbox override it).
  • Terminal UI — interactive prompts (confirm, text, select, password, number, date), styled/colored output, and terminal control (cursor addressing, alternate screen, scroll regions) via tui.
  • Core helpersmath, table, and utils extensions, structured log, os time helpers, and task.join concurrency.

Planned:

  • Filesystem ergonomics — glob/walk on top of the existing fs core.
  • TUI widgets & input — progress bars, tables, and raw key/mouse events on top of the existing terminal control.

The intent is for the common case to be a single call rather than a multi-step setup.

How it works

  • Embeds Lua 5.5 via mlua, on an async core (tokio) so IO-heavy scripts don't block.
  • A single self-contained binary. No LuaRocks, no make, no virtualenv.
  • Scripts run in a sandboxed environment modeled on Luau's safe environment: io, package, and debug are not loaded; os is trimmed to its time functions; the bytecode/chunk-loading escape hatches (load, loadfile, dofile, string.dump) are removed. The library a provides is the supported way to reach the outside world.
  • A leading #! shebang line is skipped (after an optional UTF-8 BOM), so scripts can be made executable directly. Script files need not be valid UTF-8 — Lua source is byte-oriented.
  • Scripts can be split into files with a sandboxed require: modules are looked up next to the main script (symlinks resolved, so an executable script symlinked into ~/.local/bin finds its files) and in $A_INCLUDE_PATHS, which can also be set in a .env beside the script.

Building

cargo build --release
# binary at target/release/a

cargo run -- lua/test.lua   # run a script during development

Requires a Rust toolchain (2024 edition). Lua is vendored and built from source, so no system Lua is needed.