Extensions
Extensions add features without touching the launcher binary: custom pages, batch operations on instances, third-party integrations, multiplayer helpers.
Want to start from code?
Template repos for six languages are ready: Language templates. Clone one, change the id, and ship.
Layout
my-ext/
├─ manifest.json id, name, version, runtime, entry, permissions
├─ main.jar entry point (.py / .js / .exe also fine)
└─ lib/ optional dependenciesDrop it into extensions/ inside the data directory and it shows up under Settings → Extensions.
See Import & manage for importing, permissions and the per-extension buttons.
Trust
The first load hashes the whole package and records it in extensions/trusted.json:
{
"hello-go": { "sha": "9f2c…", "enabled": true }
}- Any change to the package breaks the hash, and the launcher refuses to load it.
- This is tamper detection, not antivirus. Do not install extensions from untrusted sources.
- Disabling only flips
enabledtofalse; files stay untouched.
Lifecycle
scan → read manifest → validate → compare trusted.json
→ check runtime → extract to temp (chmod +x for native)
→ spawn entry process → stdio channel → hello
→ runtime messages
→ exit / disable → cleanupExtensions run as separate processes. A crash never takes the launcher down, and the launcher reaps child processes when it exits.
Permissions
| Permission | Meaning |
|---|---|
fs.read | Read the data directory |
fs.write | Write the data directory |
net | Network requests |
process | Spawn child processes |
ui | Dialogs, notifications, custom pages |
launch | Trigger a game launch |
Undeclared calls are rejected and logged.
Size limits
| Item | Limit |
|---|---|
| Single file | 8 MiB |
| Extracted package | 16 MiB |
| manifest.json | 64 KiB |
Native binaries hit the limit quickly — strip before packing:
go build -ldflags "-s -w" -o main.exe .
cargo build --release && strip target/release/my-ext