Skip to content

Manifest Reference (komari-plugin.json)

komari-plugin.json must be located at the root of the plugin ZIP. It declares the plugin's metadata, permissions, configuration items, and injected pages. The server validates this file on install, load, and enable.

All Fields

FieldTypeRequiredDefaultDescription
namestring | i18n objectYesPlugin name. An empty string or empty map fails validation
shortstringYesUnique plugin short name, also used as the directory name under data/plugin. Only [A-Za-z0-9_-], must not be default
descriptionstring | i18n objectNoPlugin description
authorstring | i18n objectNoAuthor
versionstringNoPlugin version (required for market publishing)
urlstringNoProject homepage / repository URL
iconstringNoIcon path; must be a relative path inside the plugin directory
komaristringNo""Server version constraint, e.g. >=1.0.0 (see below)
entrystringNo"script.js"Entry script; must be a relative path inside the plugin directory
permissionsobjectNoall zeroCapability declarations, see below
configurationobjectNoConfiguration item declarations, same shape as themes, see below
pagesarrayNo[]Injected admin pages, see below

i18n fields

name, description, author and page title can be plain strings or i18n objects such as {"zh_CN": "...", "en": "..."}. The frontend resolves them against the current locale; -/_ key spellings are interchangeable (e.g. zh-CN equals zh_CN). Resolution order: exact match → normalized match → base language (zh) → language family prefix → first value.

Version Constraint komari

Constrains the running server version. Supported syntax (optional leading v):

SyntaxMeaning
emptyany version
1.0.0 or =1.0.0exact match
>=1.0.0 / >1.0.0minimum version
<=1.0.0 / <1.0.0maximum version

Installation is rejected when the constraint is not satisfied, and loading also fails. The komari field in the market catalog must exactly match the manifest.

Permissions

Except for node, maxHTTPBodyBytes, maxChildOutputBytes, and timeout, every field defaults to false/0nothing is granted unless declared.

FieldTypeDefaultDescriptionTriggers approval
nodebooleanfalseEnable Node.js compatibility modules (events/path/os/process/fs/child_process/net/http/stream/crypto and the Buffer/process/global globals)No
allowSystemRPCbooleanfalseAllow server.call to invoke system RPC with admin authorityYes
allowRoutesbooleanfalseAllow server.route to register HTTP routes on the host engineYes
allowHooksbooleanfalseAllow server.hook to modify HTTP requests/responsesYes
allowExecbooleanfalseAllow child_process to execute child processesYes
allowListenbooleanfalseAllow net/http Servers to listen on local portsYes
allowAllFileAccessbooleanfalseAllow accessing files outside the plugin directoryYes
maxHTTPBodyBytesint32 MiBBuffering limit for fetch response bodies and HTTP request bodiesNo
maxChildOutputBytesint1 MiBstdout/stderr cap for child processesNo
timeoutint30Per-turn execution timeout in secondsNo

Always granted

server.registerRPC, server.getConfig, and read/write access inside the plugin directory are always granted — no manifest declaration needed and no approval triggered.

Approval mechanism

When any of allowSystemRPC / allowRoutes / allowHooks / allowExec / allowListen / allowAllFileAccess is true, enabling the plugin requires admin approval. The approval hash covers only these 6 fields; later changes to node, timeout, or size limits do not re-trigger approval, but changing a sensitive capability does.

Configuration

Same shape as theme configuration, supporting declarative config with type: "managed": the admin UI generates a form automatically, and the plugin reads values via server.getConfig() (saved values are merged with manifest defaults).

json
{
  "configuration": {
    "type": "managed",
    "data": [
      { "key": "greeting", "name": "Greeting", "type": "string", "default": "Hello" },
      { "key": "count", "name": "Count", "type": "number" },
      { "key": "enabled", "name": "Enabled", "type": "switch", "default": true },
      { "key": "mode", "name": "Mode", "type": "select", "options": "json,text" },
      { "key": "note", "name": "Note", "type": "string", "help": "Usage instructions" }
    ]
  }
}

Item fields

FieldTypeRequiredDescription
keystringYesConfiguration key
namestring | i18nYesForm label
typestringYesstring / number / select / switch / title / richtext
optionsstringNoOptions for select, comma-separated
defaultanyNoDefault value
requiredbooleanNoWhether the field is required
helpstring | i18nNoHelp text

Default value merge rules

server.getConfig() returns the merge of "saved values + manifest defaults"; saved values take precedence. Unsaved keys are filled with these fallbacks:

TypeFallback without default
selectfirst option
number0
switchfalse
others""

Configuration is stored in the plugin_configurations table of the main database.

Pages

Plugins can inject pages into the admin UI (shown in the plugin group of the sidebar).

json
{
  "pages": [
    { "file": "admin.html", "title": "Admin Panel", "icon": "icon.png" },
    { "type": "redirect", "title": "Go to Nodes", "url": "/" },
    { "file": "pub.html", "title": "Public Page", "visibility": "public" }
  ]
}

Page fields

FieldTypeRequiredDescription
filestringrequired for iframeRelative path inside the plugin directory, rendered as an iframe
titlestring | i18nYesPage title
iconstringNoIcon, relative path inside the plugin directory
type"iframe" | "redirect"NoDefault iframe
urlstringrequired for redirectInternal site path (see below)
visibility"admin" | "public"NoDefault admin

Access URLs

visibilitytypeAccess pathAuth
adminiframe/api/admin/plugin/<short>/<file>admin login required
publiciframe/api/plugin/<short>/<file>no auth (public)
redirectanynavigates to an internal site path
  • public pages require the plugin to be enabled and can only serve files under a declared public page's directory; pages are rendered in a sandboxed iframe (sandbox="allow-forms allow-modals allow-popups allow-same-origin allow-scripts").
  • A redirect url must be a same-origin internal path: starts with /, must not start with //, and must not contain backslashes, URL schemes (e.g. http:), or .. segments.

Complete Example

json
{
  "name": {
    "zh_CN": "示例插件",
    "en": "Example Plugin"
  },
  "short": "example",
  "description": {
    "zh_CN": "演示插件开发",
    "en": "Demonstrates plugin development"
  },
  "author": "komari",
  "version": "1.0.0",
  "url": "https://github.com/your-name/komari-example",
  "icon": "assets/icon.png",
  "komari": ">=1.0.0",
  "entry": "script.js",
  "permissions": {
    "node": true,
    "timeout": 10,
    "maxHTTPBodyBytes": 67108864,
    "allowSystemRPC": true,
    "allowRoutes": true
  },
  "configuration": {
    "type": "managed",
    "data": [
      {
        "key": "interval",
        "name": { "zh_CN": "刷新间隔", "en": "Refresh Interval" },
        "type": "number",
        "default": 5,
        "required": true
      }
    ]
  },
  "pages": [
    {
      "file": "admin.html",
      "title": { "zh_CN": "示例页面", "en": "Example Page" }
    }
  ]
}

Installation validation rules (ZIP package)

RuleLimit
komari-plugin.json locationmust be at the ZIP root
File count≤ 10,000
Per-file size≤ 128 MiB
Total extracted size≤ 512 MiB
Manifest size≤ 1 MiB
Path safetypackages containing traversal entries (../, absolute paths) are rejected entirely
File existenceentry and all page files must exist (checked at install)

Released under the MIT license.