Guide
Bundles and the manifest
A local script is one .lua file. A marketplace script is a bundle: a zip that holds a manifest.json, the entry file and any other files the script needs. The backend signs the bundle when it is published, and the device verifies that signature before it loads anything.
manifest.json
{
"name": "shot-logger",
"version": "1.2.0",
"author": "sam",
"capabilities": ["math"],
"deps": { "sam/vectors": "2.0.1" },
"entry": "script.lua"
}
| Field | Meaning |
|---|---|
name |
The bundle name. Letters, digits, - and _. |
version |
Semantic version, three numbers. |
author |
Your marketplace author name. author/name is the bundle’s identity. |
capabilities |
The gated capability groups the script uses. A gated global not listed here is nil. See Capabilities. |
deps |
Libraries the script requires, each pinned to one exact version. See require and pinned dependencies. |
entry |
The file that runs. Usually script.lua. |
The runtime reads capabilities from the manifest and installs exactly those gated groups. A loose local development script is granted every group instead.
Reserved paths
A path inside the archive is refused when it:
- starts with
/or a drive letter, - contains
.., - is
manifest.jsonin any directory other than the root, - collides with another entry after case folding.
Every bundle installs into its own directory, so two bundles cannot overwrite each other’s files.
Signing
When a version is published the backend hashes the archive with SHA-256 and signs the hash with the current signing key. The signature and the key id travel with the bundle. Keys rotate; an old key stays valid for verifying bundles signed while it was current.
Verification on the device
Before a bundle loads, the runtime:
- checks the signature against the key id’s public key,
- checks the archive hash matches the signed hash,
- reads the manifest and refuses any reserved path,
- resolves every dependency and verifies each one the same way,
- compiles the entry file as text.
A bundle that fails any step does not load, and the tab shows why. A modified bundle fails step 2.
No bytecode
Only text source compiles. A .luac file, or a file that starts with the Lua bytecode signature, is refused at compile time whether it is local or in a bundle. string.dump is removed, so a script cannot produce bytecode either.