Skip to content

Official Plugins

Official plugins are public WebAssembly Component Model packages published by the Sigil project under the sigil-plugins GitHub organization. Their immutable releases carry keyless provenance that Sigil verifies before installation and pins in the project lock.

Run this command for the live inventory:

Terminal window
sigil plugin list-remote

sigil plugin add is the normal way to adopt one. Run it in the project that contains .sigil/sigil.toml; it downloads the package when necessary, declares the exact project dependency, writes the reproducibility lock, and generates the matching LuaLS stub.

PluginReleaseWhat it doesRequested host capabilities
codec1.1.2Reference plugin that echoes a u32None
mysql0.1.2Bounded MySQL 8.4 text-protocol driverNetwork and named secrets
s30.1.0Bounded, read-only S3-compatible object fetchNetwork
parquet0.1.0Parquet metadata inspection and typed scalar readsNone

Codec is the small, capability-free reference plugin. It is useful for checking that plugin installation, locking, LuaLS generation, and the Component Model runtime work end to end. It is not a general-purpose codec library: its current interface exports one echo-u32 function.

Terminal window
sigil plugin add [email protected]
return {
title = "Codec plugin is available",
priority = "P1",
policy = { capabilities = { "wasm.codec" } },
run = function()
local codec = require("wasm.codec")
expect(codec["echo-u32"](42) == 42)
end,
}

View the immutable Codec 1.1.2 release.

MySQL is a bounded MySQL 8.4 Classic Protocol driver. Sigil owns endpoint resolution, TCP, TLS verification, timeouts, byte quotas, secret grants, cancellation, and teardown; the component sees only a logical endpoint and the names of specifically granted secrets.

Terminal window
sigil plugin add [email protected]

Expose the credential names to scenarios, grant those names to this plugin, and map its logical database endpoint to the lane-local service:

[scenario.env]
MYSQL_USER = { from = "MYSQL_USER" }
MYSQL_PASSWORD = { from = "MYSQL_PASSWORD" }
[plugins.grants.mysql]
secrets = ["MYSQL_USER", "MYSQL_PASSWORD"]
[plugins.grants.mysql.network.database]
target = "mysql:3306"
tls = "upgrade"
tls_server_name = "mysql"
tls_ca_file = ".sigil/certs/mysql-ca.pem"
connect_timeout = "5s"
io_timeout = "10s"
max_connections = 2
max_bytes = "16MiB"

Then connect and issue a text query:

return {
title = "MySQL responds to a query",
priority = "P1",
policy = { capabilities = { "wasm.mysql" } },
run = function()
local mysql = require("wasm.mysql")
local connection, connect_error = mysql.connect({
endpoint = "database",
["username-secret"] = "MYSQL_USER",
["password-secret"] = "MYSQL_PASSWORD",
database = "app",
})
expect(connect_error == nil, connect_error and connect_error.message)
local result, query_error =
connection:query("SELECT 'ready' AS marker")
expect(query_error == nil, query_error and query_error.message)
expect(result.tag == "rows")
connection:close()
end,
}

The experimental sigil:sql/[email protected] interface supports TLS upgrade, caching_sha2_password, text queries, and one result. It does not support prepared statements, the binary protocol, multi-statements or multi-results, retry, reconnect, or LOCAL INFILE.

View the immutable MySQL 0.1.2 release.

S3 performs one bounded, path-style HTTP GET from an S3-compatible object store such as MinIO. It is read-only and accepts anonymous access or a caller-supplied presigned query. It does not accept access keys, sign requests, follow redirects, list buckets, issue ranges, or write objects.

Terminal window
sigil plugin add [email protected]

Map the guest-visible object-store endpoint to MinIO. The host byte quota includes request and response framing, so this example budgets 4 MiB for the object plus bounded wire overhead:

[plugins.grants.s3.network.object-store]
target = "minio:9000"
tls = "disabled"
connect_timeout = "5s"
io_timeout = "10s"
max_connections = 1
max_bytes = "4172KiB"
return {
title = "Read an object from MinIO",
priority = "P1",
policy = { capabilities = { "wasm.s3" } },
run = function()
local s3 = require("wasm.s3")
local bytes, download_error = s3["get-object"]({
endpoint = "object-store",
bucket = "results",
key = "run/output.parquet",
["max-bytes"] = 4 * 1024 * 1024,
})
expect(download_error == nil,
download_error and download_error.message)
expect(bytes ~= nil)
end,
}

The Lua max-bytes argument limits the decoded object body; the network grant’s max_bytes limits aggregate request and response bytes on the wire. Before I/O, S3 asks the host to reserve the body ceiling plus exactly 64 KiB of possible response framing. The grant must therefore exceed the Lua ceiling by at least 65,536 bytes—65,535 bytes is refused—and request bytes need separate headroom. The example uses another 12 KiB for an 8 KiB presigned query, a percent-expanded key, endpoint, and HTTP framing: 4 MiB + 64 KiB + 12 KiB = 4,172 KiB.

A reservation that does not fit is an uncatchable PLUGIN_RESOURCE_LIMIT/plugin_infrastructure failure. A response body that exceeds the plugin’s Lua ceiling instead returns nil, {class = "limit", ...} with no partial bytes. That typed result is catchable by design, so scenarios must assert the error return as the sample does rather than relying on pcall. The maximum object body is 16 MiB. The logical endpoint is also the HTTP Host, so a presigned query must target that in-environment name.

View the immutable S3 0.1.0 release.

Parquet accepts a complete file as a binary Lua string, reports flat leaf metadata, and reads one typed scalar cell by column path and zero-based row index. It has no filesystem or network capability. The intended object-store flow composes it with S3 in the scenario, without making either plugin depend on the other:

Terminal window
sigil plugin add [email protected]
sigil plugin add [email protected]

Use the S3 endpoint grant from the preceding section, then pass the downloaded bytes directly to Parquet:

return {
title = "Read one value from a Parquet object",
priority = "P1",
policy = { capabilities = { "wasm.s3", "wasm.parquet" } },
run = function()
local s3 = require("wasm.s3")
local parquet = require("wasm.parquet")
local bytes, download_error = s3["get-object"]({
endpoint = "object-store",
bucket = "results",
key = "run/output.parquet",
["max-bytes"] = 4 * 1024 * 1024,
})
expect(download_error == nil,
download_error and download_error.message)
local cell, read_error = parquet["read-cell"](bytes, {
column = "total",
row = 1,
})
expect(read_error == nil, read_error and read_error.message)
expect(cell.tag == "floating")
expect(cell.value == 27.75)
end,
}

Version 0.1 supports required or optional non-repeated scalar columns, plain or dictionary encoding, and uncompressed or Snappy pages. Nested or repeated columns, INT96, nanosecond temporal values, external column chunks, and other compression codecs fail explicitly. Input is capped at 16 MiB.

View the immutable Parquet 0.1.0 release.

After adding plugins, commit the complete reproducibility generation and lint the scenarios:

Terminal window
git add .sigil/sigil.toml .sigil/sigil.plugins.lock .sigil/types/wasm
sigil scenario lint

See Using Plugins for locking, syncing, updates, removal, third-party sources, and CI behavior.