Manifest reference
manifest.json is a plugin’s identity file, located at the root of the .qplugin package. It describes the plugin’s metadata, permissions, entries, and extension points.
Generating a valid manifest skeleton with qomicex create <id> is recommended (it sets up id / layers / permissions / entry automatically); then validate it with qomicex verify. This page covers every field so you can adjust them as needed.
Complete structure
Field summary
entry object
If you omit
entry.frontend, the plugin is not activated (activatePlugin only renders and marks active when entry.frontend exists), so it cannot register methods or provide UI. Even for purely functional plugins, providing an empty page entry is recommended. The one exception is a pure L3 (wasm) plugin: when layers contains only l3 (no l2/l4), the CLI allows entry to be omitted (the gateway loads it from the fixed file name plugin.wasm), but such a plugin still has no page entry and is never activated or rendered.
contributes object
Plugin-owned i18n (l10n)
Declare"l10n": "l10n" at the manifest top level (a directory inside the package, relative to the .qplugin root):
key → string map. Manifest display strings reference entries with %key% (e.g. "name": "%plugin.name%", installModes labels/descriptions); the host resolves them at manifest load time using the launcher’s current locale (missing keys in the locale bundle fall back to the default bundle, then to the raw %key%). Plugin runtime UI reads the same merged bundle through the bridge:
icon field spec (menus / install modes / top-level icon)
Choose in priority order:- Font Awesome class name (recommended):
"fa-solid fa-server". Zero assets, follows the theme color (currentColor), resolved by the launcher (sidebar and install dialogs render uniformly).- Do not hardcode the available set: the built-in table evolves with the launcher. Get the full list at runtime with
call('listIcons'), or offline from theICON_NAMESexport of@qomicex/plugin-ui. - Names outside the table render blank (historically ignored silently).
qomicex verify/lintvalidate them statically, report an error, and suggest the closest built-in names. - In-page icons should not call
getIconSvg; use<Glyph>with per-icon subpath imports (see Plugin API — Icons).
- Do not hardcode the available set: the built-in table evolves with the launcher. Get the full list at runtime with
- In-package relative path:
"dist/icon.svg"(for multicolor/brand icons; resolved to the plugin file-service URL). - Absolute URL / emoji / plain text: e.g.
"https://…/icon.png","🏆","A". Emoji do not follow the theme color and do not scale well; prefer option 1 or 2. - Private icons (
contributes.iconTheme): point at an in-packageicon-theme.jsonshaped as{ "schemaVersion": 1, "icons": { "<icon key>": { "type": "svg", "path": "M…" } } }. Declared keys show up inlistIcons()and are resolved first bygetIconSvg— you can ship icons the built-in table lacks without waiting for a launcher release.
installModes array elements
When installing modpacks and other resources, the install dialog’s “Install as” option group lists entries contributed by active plugins (the default entry is the launcher built-in “Create instance”). Once the user selects one and confirms, the launcher invokes the
installMode:{id} method through the plugin registry (the plugin must register it with __PLUGIN_API__.registerMethod), passing a resource context:
registerMethod (config:write) permission model. For a worked example see the server manager plugin (top.qomicex.server-manager, the “Install as a server” install mode).
hooks array elements
The declaration documents the hook and allows a permission pre-check; the actual handler is registered at runtime with
__PLUGIN_API__.registerHook.
menuItems array elements
settingsPages array
Collect a plugin’s settings UI into the launcher, so settings entry points are not scattered around.- Each path is the relative path of an HTML file inside the
.qpluginpackage; the tab disappears automatically when the plugin is disabled - The launcher renders one tab per path under Settings → Plugins → Plugin settings (vertical tabs on the left list each plugin; the right side is an iframe sandbox with the same
__PLUGIN_API__bridge as plugin pages) - For the full development guide (writing the settings HTML, using getSettings/setSettings, openPluginSettings navigation, lifecycle rules), see Plugin settings page
icon examples
http://localhost:5000/api/plugins/{id}/files/dist/icon.png, with nothing extra needed on the plugin side.
Top-level icon (library plugin icon)
BesidesmenuItems[].icon, icon is also supported at the manifest top level, so library plugins without contributes.menuItems show an icon in plugin management / the list:
- The supported forms match
menuItems[].icon(emoji / absolute URL / relative path inside the package / FontAwesome class name) - Plugin management cards read them in this order:
contributes.menuItems[0].icon ?? manifest.icon - Library plugins should use the top-level
iconand should not declarecontributes.menuItems(which creates a sidebar entry) - Prefer FontAwesome class names for icons (such as
fa-solid fa-file-lines,fa-brands fa-markdown; they must be in the launcher’sBuiltinIcons.tsxpreset list): SVG paths rendered through<img>stay black and do not follow the theme, whereas FA class names follow the light and dark themes
overlay object
layers layer definitions
layers sorts plugins by complexity, from pure declarations to executable logic, and determines a plugin’s capabilities and how it runs:
How to declare:
layers is an array, so you can declare several layers at once:
-
The iframe sandbox is the default rendering mode: plugins with
entry.frontenduse the iframe sandbox by default (<iframe sandbox="allow-scripts">plus a postMessage bridge), isolated from the main UI’s DOM/CSS (opaque origin, preventing CSS leakage and same-origin theft). Inline rendering (same context as the main UI, compatible with older plugins) only happens when the manifest explicitly declares"render": "inline". -
The iframe sandbox also supports all
__PLUGIN_API__methods,.p-*component styles, andregisterMethod/callPlugin(relayed across windows) -
Sandboxed plugin scripts run automatically when the
srcdocis parsed, without visiting the page -
Plugin activation conditions: after installation a plugin starts in the
installedstate, and actual activation depends on two things: ①entry.frontendexists (activatePluginonly renders and marksactivewhenentry.frontendexists); ② the user enables it in the plugin list. This is independent of thelayersdeclaration; a pure["l3"]plugin withentry.frontendis still activated (using the iframe sandbox by default). -
Differences between the iframe sandbox and inline rendering:
-
L0/L1 are currently reserved declarative layers with no standalone runtime mechanism yet; L3 WASM is implemented: plugins that declare
l3and shipplugin.wasmin the package are loaded and executed by the launcher’s Rust layer (wasmtime) (see WASM plugins) -
L4 remote WebView is implemented: for plugins that declare
render:"webview"or include"l4"inlayers, the main window callscreateRemoteWebviewon activation to open a standalone Tauri WebviewWindow (process-level isolation from the main UI); the plugin UI renders inside that window, and API calls are forwarded to the main window through Tauri events for execution (see L4 remote WebView) - Plugins that need an isolated environment or a long-running script (such as AI assistants or tool panels) → use the default iframe sandbox
-
Pure UI/theme plugins, or lightweight plugins that depend on the main UI DOM → explicitly declare
"render": "inline" -
If the plugin will later add WASM backend logic, you can layer
"l3"on top -
Heavy UI / untrusted / process-isolation plugins (such as complex editors or game UI enhancements) → declare
"render": "webview"or include"l4"inlayers(standalone window, so a busy loop does not affect the main UI)
Version range syntax
dependencies[].version supports the following forms:
Comparison rules:
- Segments are split on
.and compared numerically one by one;-(prerelease) and+(build number) suffixes are ignored - A missing segment counts as 0 (so
1.0equals1.0.0) ^,~,*, thexwildcard,||, and commas are not supported
minLauncherVersion itself, but the store does: POST /plugins/check-updates compares semver and drops versions whose minimum version is above the current launcher from the update list, and GET /plugins?minLauncherVersion= filters on it as well. The CLI (qomicex verify) additionally requires the field to be present. So always fill it in, otherwise CLI validation fails and the store cannot apply compatibility filtering.