LuaU Globals
Always-available globals
Section titled “Always-available globals”These are present in every script (preamble, handler, grouping) regardless of permissions.
| API | Signature |
|---|---|
json.encode(value) | any -> string |
json.decode(s) | string -> any (returns nil on parse error) |
Tables with integer keys serialise as JSON arrays; tables with string keys serialise as objects. Mixed tables are not supported.
local node = json.decode(input)if not node then error("invalid input") endreturn json.encode({ source = "...", inline = {} })Native introspection API
Section titled “Native introspection API”These functions are registered by the engine and use stable opaque integer IDs (the _registryId field on the entity payload, or the result of a lookup).
| Function | Signature | Description |
|---|---|---|
get_node(id) | int -> string|nil | Returns the node’s full JSON, or nil. |
find_struct_by_name(name) | string -> int|nil | Returns the registry ID of a struct by unqualified name (first match across all parsed sources). |
struct_has_attribute(id, name) | int, string -> bool|nil | True if the struct carries [[codegen::name]] (or any namespaced attribute named name). |
struct_has_method(id, name) | int, string -> bool|nil | True if the struct has a member function, static member function, or constructor with this name. |
struct_has_member(id, name) | int, string -> bool|nil | True if the struct has a member or static member variable with this name. |
struct_has_default_constructor(id) | int -> bool|nil | True if the struct has no constructors, or if any constructor’s parameters all have default values. |
get_base_classes(id) | int -> string|nil | Returns a JSON array of {access, name, qualifiedName, id} for each base class. id is null when the analyzer can’t resolve the symbol. |
get_definition_header(name) | string -> string|nil | Returns the path to the header that defines a given qualified or unqualified name, when known to the analyzer. |
All functions return nil on bad arguments (wrong type or missing); only the lookup functions return nil for “not found.”
Context objects
Section titled “Context objects”Preamble context
Section titled “Preamble context”Injected via the input parameter to preamble.luau:
{ "language": "cpp", "outputFile": "path/to/output.cpp", "ruleName": "RuleName", "params": { /* rule.params */ }, "entities": [ { "registryId": 42, "qualifiedName": "app::MyStruct", "structName": "MyStruct", "namespaces": ["app"], "inputFile": "include/app/my_struct.hpp", "includes": ["<vector>"] } ]}The entities array contains every entity bound to this output file. Use it to conditionally emit includes or other file-level content.
Grouping context
Section titled “Grouping context”Injected via the input parameter to grouping.luau:
{ "params": { /* rule.params */ }, "entities": [ { "registryId": 42, "qualifiedName": "app::MyStruct", "structName": "MyStruct", "namespaces": ["app"], "inputFile": "include/app/my_struct.hpp", "defaultPath": "include/app/my_struct.g.cpp" } ]}The defaultPath is the 1:1 output path (derived from the input header). Override it by returning a map from registryId to a new path.
Handler context
Section titled “Handler context”Injected via the input parameter to transform.luau:
The full entity JSON from the codex AST, with these synthetic fields added:
_namespaces(array of strings, the qualifying namespace path)_registryId(integer, stable identifier)_outputPath(string, the post-grouping output file path)params(object, copied from rule config)
The _outputPath is the final output file this entity will land in (after grouping, if present).
Standard LuaU library
Section titled “Standard LuaU library”Available subset (the LuaU sandbox restricts the unsafe parts):
| Library | Use |
|---|---|
table | insert, remove, concat, sort, unpack |
string | format, find, gmatch, gsub, sub, len, rep, upper, lower |
math | floor, ceil, min, max, abs, huge, pi |
| Globals | ipairs, pairs, tostring, tonumber, error, pcall, xpcall, type, select, assert, unpack |
Permission-gated globals
Section titled “Permission-gated globals”These appear only when the corresponding capability is requested via permissions: in the rule config (or via CLI overrides).
Enabled when permissions.http.allowlist is non-empty (or the CLI passes --allow-http).
| API | Signature |
|---|---|
http.get(url) | string -> string (response body), or yields (nil, error_string) on transport failure |
The URL’s host component is matched against the allowlist (exact host, *.domain wildcard, or * as escape hatch — see permissions.http.allowlist). A URL whose host is not on the allowlist raises a runtime error and emits diagnostic E010. Concurrent requests on the same VM are not supported.
Enabled when permissions.env.os_allowlist is non-empty, or when any dotenv source is configured (per-rule .env, shared <rulesDir>/../shared/.env, or CLI --env KEY=VALUE).
The env module exposes the allowlisted OS env vars and the merged dotenv (CLI --env > per-rule .env > shared .env). See the Permissions page for the surface API.
Absent globals
Section titled “Absent globals”The following are explicitly not provided:
requireand any module loading mechanismio(file I/O)os(process/time/system access —os.getenvis not the env capability; that’s a separate module)debug(Lua debug library; the DAP debugger is a separate feature, see VS Code DAP Debugger)coroutine(the engine drives the coroutine forhttp.getinternally; user scripts cannot create their own)loadstring/loadfile- Any FFI
json.encode/json.decodeand the native introspection API are always present.- HTTP and env access are opt-in via
permissions:in the rule config; nothing else opens the sandbox. - The native API gives scripts cross-entity lookup (base classes, definition headers, finding structs by name) without re-implementing the analyzer.