Skip to main content

Manifest Reference

Every plugin requires a manifest.json file in its root directory. This page documents all available fields.

Base Fields (All Plugin Types)

FieldTypeRequiredDescription
idstringUnique plugin identifier (must match directory suffix)
versionstringSemantic version (e.g. "1.0.0")
namestringDisplay name (or i18n key like "meta.name")
typestringPlugin type: "controller", "effect", "extension", or "pack"
languagestring✅ for runtime pluginsRuntime language. Use "lua" or "native-c"; Core also accepts "c-abi" and "native" as aliases for native-c.
abistring✅ for native-cNative ABI identifier, e.g. "skydimo-effect-c-v3"
entrystring or object✅ for runtime pluginsRuntime entry. Lua uses a script path. Native-c can use a shared library path or platform entry map.
permissionsstring[]Required permissions
localesobjectInline locale dictionaries keyed by locale code. Recommended for marketplace-ready plugin metadata
publisherstringAuthor or organization name
descriptionstringHuman-readable description (or i18n key)
repositorystringSource repository URL
licensestringLicense identifier (e.g. "MIT")

Example (Base)

{
"id": "my_plugin",
"version": "1.0.0",
"name": "My Plugin",
"type": "effect",
"language": "lua",
"entry": "main.lua",
"permissions": ["log"],
"publisher": "Your Name",
"description": "A cool plugin",
"license": "MIT"
}

Entry Platform Map

entry can be a single relative path or a platform map. Platform maps are recommended for native-c plugins:

{
"entry": {
"windows-x86_64": "native/windows-x86_64/my_plugin.dll",
"linux-x86_64": "native/linux-x86_64/libmy_plugin.so",
"macos-aarch64": "native/macos-aarch64/libmy_plugin.dylib",
"default": "native/windows-x86_64/my_plugin.dll"
}
}

Supported platform keys are windows-x86_64, windows-aarch64, linux-x86_64, linux-aarch64, macos-x86_64, and macos-aarch64. default is optional fallback. Entry paths must be relative to the plugin directory and cannot contain .. or absolute path prefixes.

Example (Native-C)

{
"id": "my_native_effect",
"version": "1.0.0",
"name": "My Native Effect",
"type": "effect",
"language": "native-c",
"abi": "skydimo-effect-c-v3",
"entry": {
"windows-x86_64": "native/windows-x86_64/my_native_effect.dll",
"linux-x86_64": "native/linux-x86_64/libmy_native_effect.so",
"macos-aarch64": "native/macos-aarch64/libmy_native_effect.dylib",
"default": "native/current/libmy_native_effect.so"
},
"permissions": ["log"],
"publisher": "Your Name"
}

Plugin Pack Manifest

A pack manifest groups child plugins and does not have language, abi, or entry. Core reads id, name, publisher, type: "pack", and plugins; version is recommended for distribution metadata.

{
"id": "my_effect_pack",
"version": "1.0.0",
"name": "My Effect Pack",
"publisher": "Example",
"type": "pack",
"plugins": [
"Rainbow",
{ "path": "Audio/Bars" }
]
}

Pack plugin paths must stay inside the pack directory. Nested packs are ignored.


Controller-Specific Fields

match

Defines how the controller matches hardware devices.

FieldTypeRequiredDescription
match.protocolstring"serial", "hid", or "mdns"
match.rulesMatchRule[]USB matching rules
match.baud_ratenumberSerial baud rate (serial only)
match.timeout_msnumberI/O timeout in milliseconds

MatchRule

FieldTypeDescription
vidstringUSB Vendor ID in hex (e.g. "0x1A86")
pidstringUSB Product ID in hex (e.g. "0x7523")
interface_numbernumberUSB interface number (optional). When specified, Core only matches the device on that interface. See protocol-specific notes below.
tip

For HID devices that expose multiple interfaces (e.g. keyboards with separate input and lighting endpoints), specifying interface_number in the match rule lets Core filter at the matching stage — before on_validate() is called — avoiding unnecessary device handle opens and duplicate claims.

This HID usage is already verified and is the recommended approach for multi-interface HID devices.

Serial interface_number — Not Yet Verified

This warning applies only to Serial (CDC) matching. HID interface_number matching is already verified.

For Serial (CDC) devices, interface_number is now read from the OS USB enumeration API (requires the usbportinfo-interface feature of the serialport crate) and will be matched against this field. This enables distinguishing multiple serial interfaces on the same composite USB device.

This usage has not been verified in production and is not recommended. Available in version 3.0.1 and later.

Example (Serial Controller)

{
"id": "skydimo_serial",
"version": "1.0.0",
"name": "Skydimo Serial Controller",
"type": "controller",
"language": "lua",
"entry": "main.lua",
"permissions": ["serial:read", "serial:write", "log"],
"match": {
"protocol": "serial",
"baud_rate": 115200,
"timeout_ms": 200,
"rules": [
{ "vid": "0x1A86", "pid": "0x7523" }
]
}
}

Example (Serial Controller with interface_number)

Not Yet Verified

Matching Serial devices by interface_number has not been verified in production and is not recommended. Available in version 3.0.1 and later.

For composite USB devices that expose multiple serial interfaces (e.g. a single USB device that has both a control CDC interface and a data CDC interface), you can target a specific interface:

{
"id": "my_composite_serial",
"version": "1.0.0",
"name": "Composite Serial Controller (Interface 1)",
"type": "controller",
"language": "lua",
"entry": "main.lua",
"permissions": ["serial:read", "serial:write", "log"],
"match": {
"protocol": "serial",
"baud_rate": 115200,
"timeout_ms": 200,
"rules": [
{ "vid": "0x1A86", "pid": "0x7523", "interface_number": 1 }
]
}
}

Example (HID Controller with interface_number)

{
"id": "my_hid_keyboard",
"version": "1.0.0",
"name": "My HID Keyboard",
"type": "controller",
"language": "lua",
"entry": "main.lua",
"permissions": ["hid:read", "hid:write", "log"],
"match": {
"protocol": "hid",
"timeout_ms": 200,
"rules": [
{ "vid": "0x1532", "pid": "0x024E", "interface_number": 3 },
{ "vid": "0x1532", "pid": "0x0293", "interface_number": 2 }
]
}
}

Effect-Specific Fields

FieldTypeRequiredDescription
categorystringEffect category for sorting (or i18n key)
iconstringLucide icon name (e.g. "Waves", "Zap", "Music")
paramsParamDefinition[]Configurable parameters

ParamDefinition

FieldTypeRequiredDescription
keystringParameter identifier
labelstringDisplay label (or i18n key)
kindstring"slider", "select", "toggle", "color", "multi-color"
defaultanyDefault value
groupstringGroup label for UI organization
dependencyDependencyConditional visibility

Kind-specific fields:

KindExtra Fields
slidermin, max, step
selectoptions: [{label, value}]
toggle(none)
color(none)
multi-colorfixedCount, minCount, maxCount

Dependency

Controls when a parameter is visible or enabled:

{
"key": "preset",
"equals": 0,
"behavior": "hide"
}
FieldTypeDescription
keystringKey of the parameter to depend on
equalsanyShow only when dependency equals this value
not_equalsanyShow only when dependency does NOT equal this value
behaviorstring"hide" or "disable"

Example (Effect)

{
"id": "rainbow",
"version": "1.0.0",
"name": "meta.name",
"type": "effect",
"language": "lua",
"entry": "main.lua",
"category": "meta.category",
"icon": "Waves",
"permissions": ["log"],
"params": [
{
"key": "speed",
"label": "params.speed",
"group": "params.groups.animation",
"kind": "slider",
"default": 2.5,
"min": 0.0,
"max": 5.0,
"step": 0.1
},
{
"key": "preset",
"label": "params.preset",
"kind": "select",
"default": 0,
"options": [
{"label": "Custom", "value": 0},
{"label": "Rainbow", "value": 1}
]
},
{
"key": "colors",
"label": "params.colors",
"kind": "multi-color",
"default": ["#FF0000", "#00FF00", "#0000FF"],
"minCount": 2,
"maxCount": 16,
"dependency": {
"key": "preset",
"equals": 0,
"behavior": "hide"
}
}
]
}

Native Library Configuration

Available since: 3.0.0-dev.3

The optional native object controls how the plugin runtime loads native (C/Rust/…) Lua modules and their shared-library dependencies. All paths are relative to the plugin directory and must not escape it (no .. or absolute paths).

This section is only for Lua plugins that load C modules through Lua's require(). It is different from the native-c runtime, where the plugin entry itself is a shared library. See Native-C Plugin Runtime.

FieldTypeDefaultDescription
native.module_dirsstring[][".", "lib"]Extra directories appended to package.cpath so Lua require() can find .dll / .so C modules.
native.dll_dirsstring[][".", "lib", "bin"]Extra directories registered as DLL search paths (Windows: AddDllDirectory). Affects transitive dependency resolution.
native.preload_dllsstring[][]Relative paths to DLL files that must be loaded before the plugin entry script runs. Use this to satisfy dependencies that aren't loadable via normal search paths.
note

module_dirs and dll_dirs always include their defaults (".", "lib", "bin") in addition to any extra paths you declare.

Windows-only

dll_dirs and preload_dlls only have effect on Windows. On other platforms the fields are accepted but silently ignored.

Permission required

Plugins that declare native configuration must include "native" in their permissions array.

Example (Extension with native DLL preload)

{
"id": "signalrgb_bridge",
"version": "1.0.0",
"name": "meta.name",
"type": "extension",
"language": "lua",
"entry": "init.lua",
"permissions": ["hardware:hid", "native", "system:info"],
"native": {
"preload_dlls": ["lua54.dll", "libmcfgthread-2.dll"]
}
}

Example (Extension with custom module and DLL search dirs)

{
"id": "my_native_extension",
"version": "1.0.0",
"name": "My Native Extension",
"type": "extension",
"language": "lua",
"entry": "init.lua",
"permissions": ["native", "log"],
"native": {
"module_dirs": ["native/modules"],
"dll_dirs": ["native/deps"],
"preload_dlls": ["native/deps/libfoo.dll"]
}
}

Extension-Specific Fields

FieldTypeRequiredDescription
pagestringPath to embedded HTML page (e.g. "page/dist/index.html"). Desktop app only.
page_urlstringExternal URL for the extension page (e.g. "http://localhost:5173"). Works in both desktop app and browser.
Version

page_url is available since 3.0.0-dev.4.

caution

page and page_url are mutually exclusive — you must not declare both. page_url must use http:// or https:// scheme.

Example (Extension with local page)

{
"id": "openrgb",
"version": "1.0.0",
"name": "meta.name",
"type": "extension",
"language": "lua",
"entry": "init.lua",
"permissions": ["network:tcp", "process", "log"],
"publisher": "Skydimo",
"page": "page/dist/index.html"
}

Example (Extension with external URL page)

{
"id": "my_extension",
"version": "1.0.0",
"name": "meta.name",
"type": "extension",
"language": "lua",
"entry": "init.lua",
"permissions": ["log"],
"publisher": "Skydimo",
"page_url": "http://localhost:5173"
}

Internationalization (i18n) Keys

Fields like name, description, label, category, and group can use i18n keys instead of literal strings. Put the translations directly in the top-level locales object in manifest.json.

Marketplace-ready plugins should keep display metadata in manifest.json so plugin listings can be read without running plugin code or loading extra translation files.

See Internationalization for details.