Moonaku 0.1.0-preview.4
dotnet add package Moonaku --version 0.1.0-preview.4
NuGet\Install-Package Moonaku -Version 0.1.0-preview.4
<PackageReference Include="Moonaku" Version="0.1.0-preview.4" />
<PackageVersion Include="Moonaku" Version="0.1.0-preview.4" />
<PackageReference Include="Moonaku" />
paket add Moonaku --version 0.1.0-preview.4
#r "nuget: Moonaku, 0.1.0-preview.4"
#:package Moonaku@0.1.0-preview.4
#addin nuget:?package=Moonaku&version=0.1.0-preview.4&prerelease
#tool nuget:?package=Moonaku&version=0.1.0-preview.4&prerelease
Moonaku
Moonaku is a small Lua runtime for C# focused on source-generated bindings, AOT-friendly execution, and sandboxed scripts.
Minimal Usage
Install:
dotnet add package Moonaku --version 0.1.0-preview.4
using Moonaku;
var lua = LuaRuntime.Create();
await using var session = lua.Session(Sandbox.Untrusted);
var result = await session.Run<long>("return 21 * 2");
Console.WriteLine(result.Unwrap());
Generated Bindings
Projects that define Moonaku generated bindings, such as [LuaModule],
[LuaFn], or [LuaUserdata], must enable unsafe blocks because the source
generator emits Lua C callback function pointers:
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
Projects that only consume LuaRuntime to run scripts and do not declare
generated bindings do not need this setting.
Production applications can keep unsafe code out of the main app project by
placing generated bindings in a separate class library, for example
MyApp.Scripting, and enabling unsafe blocks only in that binding project.
NativeAOT publish has been validated for linux-x64 runtime-only consumers,
generated module bindings, generated userdata bindings, and async generated
bindings. Published apps still need lua5.4 available at run time.
Generated modules and userdata are registered explicitly:
var lua = LuaRuntime.Create(b => b.Module<MathModule>());
[LuaModule("mathx")]
public partial class MathModule
{
[LuaFn("add")]
public static long Add(long left, long right) => left + right;
}
Userdata bindings use [LuaUserdata] and are returned by generated module
functions:
[LuaModule("vec")]
public partial class VecModule
{
[LuaFn("new")]
public static Vec2 New(double x, double y) => new(x, y);
}
[LuaUserdata("vec2")]
public partial class Vec2(double x, double y)
{
[LuaProp("x", ReadOnly = true)]
public double X { get; } = x;
[LuaFn("length")]
public double Length() => Math.Sqrt(X * X + Y * Y);
}
Lua scripts normally call module functions with . and userdata instance
methods with ::
local v = vec.new(3, 4)
return v:length()
Moonaku consumes the Lua userdata receiver internally and exposes it to C# as
the instance (this). Do not declare a LuaValue self parameter on C#
userdata methods; use LuaValue only for ordinary Lua values where supported.
Async module functions and userdata instance methods are supported with
ValueTask and ValueTask<T>:
[LuaFn("fetch", Async = true)]
public async ValueTask<string> Fetch([LuaContext] LuaContext ctx, string id)
{
await Task.Delay(10, ctx.Cancellation);
return id;
}
Task faults are surfaced as Lua errors by the coroutine wrapper, so Lua pcall
can catch them when the sandbox exposes pcall. Host cancellation remains
terminal for the active execution.
API Tooling Outputs
Generated bindings can also produce API tooling files:
<MoonakuGenerateApiManifest>true</MoonakuGenerateApiManifest>
<MoonakuGenerateLuaLsDefinitions>true</MoonakuGenerateLuaLsDefinitions>
<MoonakuGenerateApiDocs>true</MoonakuGenerateApiDocs>
The build writes moonaku.api.json, moonaku.d.lua, and moonaku-api.md to
$(MoonakuApiOutputDir), which defaults under obj/.../moonaku-api. Set
MoonakuApiOutputDir for CI artifacts or editor integration.
Manual generation is also possible from generated providers:
File.WriteAllText("moonaku.api.json", Moonaku.Generated.MoonakuApiManifestProvider.Json);
File.WriteAllText("moonaku.d.lua", Moonaku.Generated.MoonakuLuaLsDefinitionProvider.Lua);
File.WriteAllText("moonaku-api.md", Moonaku.Generated.MoonakuApiDocumentationProvider.Markdown);
Enable the matching generation properties in the project file so these provider classes are generated. Providers are internal to the generated-binding assembly, so manual export code must run in that same assembly. XML summaries, remarks, parameter docs, return docs, examples, and exception docs flow into the manifest and Markdown output when available.
For VS Code LuaLS, point your workspace at the generated moonaku.d.lua
definition file, for example through Lua.workspace.library.
Native Lua Requirement
Moonaku uses an internal P/Invoke bridge to Lua 5.4. The host environment must
provide a compatible Lua 5.4 native library discoverable as lua5.4.
Native binaries are not bundled in this preview. Future native packaging would
make deployment easier, but it is not expected to materially change Lua VM speed,
Lua-to-C# transition cost, userdata allocation cost, or async bridge overhead.
Sandbox Basics
Sandbox.Untrusted starts with no capabilities and does not open standard Lua
libraries. Use it, or a stricter custom sandbox, for user-authored scripts.
Custom sandboxes can opt into selected native Lua standard libraries:
var sandbox = Sandbox.Build(b => b.AllowSafeLibs());
The safe profile exposes selected base helpers plus native math, string,
table, and utf8. It does not open io, os, package, debug, or Lua
filesystem loading. Sandbox.Trusted opens all standard libraries and is
intended for trusted host-owned scripts only. Modules can declare a required
capability and are skipped when the active sandbox does not allow it. Capability
names are host-defined labels; they do not grant file, network, or process
access unless your host APIs enforce them.
var sandbox = Sandbox.Build(b => b.Allow(Caps.FileRead));
await using var session = lua.Session(sandbox);
Instruction, time, memory, GC threshold, and Lua call-depth quotas are available
through SandboxBuilder.
Compile/Cache Workflow
For submitted scripts, create a named LuaChunk, compile it to LuaBytecode,
store the bytecode in your host application, and execute it later in a fresh
LuaSession with the trigger identity, services, and sandbox.
Use LuaSession.SetGlobal(...) to expose per-session primitive values or
source-generated userdata such as ctx before a run. Globals are scoped to that
session and can be replaced by the host between runs.
For reusable Lua modules, opt into controlled loading with
LuaRuntimeBuilder.Require. The resolver receives the current LuaContext and
a normalized dot-separated module name, then returns a host-approved LuaChunk
or null. Moonaku does not use package.path, package.cpath, or filesystem
loading by default.
Script Output
For user-authored scripts, prefer an explicit host module such as log.info,
log.warn, and log.error instead of relying on global print. This works in
Sandbox.Untrusted, can be capability-gated, and lets the host attach identity
and route output to its own logging or storage system.
Host-managed require is synchronous, opt-in, and resolver-backed. Async
resolvers, package managers, mod manifests, and automatic filesystem search are
not included in this preview.
Production Checklist
- Use
Sandbox.Untrusted, or a stricter custom sandbox, for user-authored scripts. - Name submitted scripts and compile source to
LuaBytecode. - Do not accept arbitrary external Lua bytecode.
- Create fresh sessions per isolated trigger unless shared globals are intentional.
- Use
LuaFunctionRefonly for callbacks that stay within the owning live session. For later external interactions, store host-side callback IDs or routing data instead of Lua closures. - Inject identity, services, sandbox, and cancellation per execution.
- Collect diagnostics and metrics.
- Treat
Caps.*as labels; host APIs must enforce real IO/network/process policy. - Provide host-controlled logging/output through generated modules.
- Dispose sessions and provide a compatible Lua 5.4 native library.
Errors And Diagnostics
Script failures are returned through LuaResult.Error. Runtime
LuaScriptException values include chunk, line, and Lua traceback information
when Lua provides it. Configure ILuaDiagnostics on LuaRuntimeBuilder to
observe started/completed/failed executions, quota blocks, sandbox blocks, and
final execution metrics.
Docs And Examples
See the repository docs and examples:
README.mdexamples/README.mddocs/getting-started.mddocs/script-author-guide.mddocs/technical-reference.mddocs/roadmap.mdCHANGELOG.mdexamples/
examples/README.md indexes runtime-only examples, generated binding examples,
tooling output examples, and examples/SplitHost/, which demonstrates a
production split where the app project is runtime-only and generated bindings
live in a separate unsafe-enabled class library.
Moonaku also ships a separate Moonaku.Templates package with dotnet new
templates for minimal runners, binding libraries, and split host projects. The
templates are not included in the runtime package.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|
Preview 4 adds per-session SetGlobal APIs, LuaFunctionRef callback references, MNK011 diagnostics, and docs/examples for Lua call style and callback/session lifetime. Native Lua packaging is still not included.