Skip to content

LuaU Globals

These are present in every script (preamble, handler, grouping) regardless of permissions.

APISignature
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") end
return json.encode({ source = "...", inline = {} })

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).

FunctionSignatureDescription
get_node(id)int -> string|nilReturns the node’s full JSON, or nil.
find_struct_by_name(name)string -> int|nilReturns the registry ID of a struct by unqualified name (first match across all parsed sources).
struct_has_attribute(id, name)int, string -> bool|nilTrue if the struct carries [[codegen::name]] (or any namespaced attribute named name).
struct_has_method(id, name)int, string -> bool|nilTrue if the struct has a member function, static member function, or constructor with this name.
struct_has_member(id, name)int, string -> bool|nilTrue if the struct has a member or static member variable with this name.
struct_has_default_constructor(id)int -> bool|nilTrue if the struct has no constructors, or if any constructor’s parameters all have default values.
get_base_classes(id)int -> string|nilReturns 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|nilReturns 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.”

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.

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.

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).

Available subset (the LuaU sandbox restricts the unsafe parts):

LibraryUse
tableinsert, remove, concat, sort, unpack
stringformat, find, gmatch, gsub, sub, len, rep, upper, lower
mathfloor, ceil, min, max, abs, huge, pi
Globalsipairs, pairs, tostring, tonumber, error, pcall, xpcall, type, select, assert, unpack

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).

APISignature
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.

The following are explicitly not provided:

  • require and any module loading mechanism
  • io (file I/O)
  • os (process/time/system access — os.getenv is 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 for http.get internally; user scripts cannot create their own)
  • loadstring / loadfile
  • Any FFI
Key Takeaways
  • json.encode / json.decode and 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.