Skip to content

Manifest Reference

manifest.json describes plugin identity, version, entry file, capabilities, and settings. Plugins should not declare which metadata fields they may return, which host APIs they need, or how fields should be written to audio tags.

Field application policy belongs to Lyrico. Plugins return data at runtime.

Field Overview

FieldTypeRequiredDefaultDescription
idstringYes-Unique plugin ID in reverse-domain format
namestringYes-Display name
versionCodeintYes-Version code, at least 1
versionNamestringYes-Version name
apiVersionintYes-Plugin API version
minHostApiVersionintNo1Minimum host API version
authorstringNo""Author
descriptionstringNo""Description
entrystringNo"source.js"Entry JavaScript file
includeDirsstring[]No[]Local helper script directories
iconstring | nullNonullRelative icon path
capabilitiesstring[]No[]Plugin capabilities
configFieldsConfigField[]No[]User-configurable fields
i18nobject | nullNonullDefault locale and resource path mapping, see Plugin Internationalization

Text in names, descriptions, and settings is always a plain string: a value starting with @ references a key in the language resources, anything else is shown literally. See Plugin Internationalization.

Fields used by older protocols to declare host APIs, returned fields, or write policies are no longer needed. New plugins should not include them.

Example

json
{
  "id": "com.example.source",
  "name": "Example Source",
  "versionCode": 1,
  "versionName": "1.0.0",
  "author": "Plugin Author",
  "description": "Example source plugin",
  "apiVersion": 5,
  "minHostApiVersion": 1,
  "entry": "source.js",
  "includeDirs": ["lib"],
  "capabilities": ["searchSongs", "getLyrics", "searchCovers"],
  "configFields": [
    {
      "key": "lyrics_source",
      "title": "Lyrics source",
      "summary": "Choose which lyrics source the plugin should prefer",
      "type": "dropdown",
      "required": true,
      "defaultValue": "official",
      "options": [
        { "value": "official", "label": "Official lyrics" },
        { "value": "user", "label": "User-uploaded lyrics" }
      ]
    }
  ]
}

Field Details

id must use reverse-domain format, such as com.example.music_source.

apiVersion is used for plugin protocol compatibility. The current plugin protocol is version 5 and accepts plugins whose apiVersion is 1, 2, 3, 4, or 5. Newer versions are rejected. This is independent of the Platform host API version, which is currently 4. See API Version History for the exact differences.

minHostApiVersion declares the minimum host API version actually required by the plugin. It must be at least 1 and cannot exceed the current host version. Plugins can still inspect Platform.runtime.getInfo().supportedHostApis for individual capabilities; missing capabilities are returned as runtime errors.

capabilities supports:

CapabilityFunction
searchSongssearchSongs(request)
getLyricsgetLyrics(request)
searchCoverssearchCovers(request)

Plugins are only exposed in host flows that match their declared capabilities. The three capabilities are independent: neither getLyrics nor searchCovers requires searchSongs. Legacy plugins with a missing or empty capability list are treated as supporting searchSongs only.

The host displays the capabilities declared by the plugin directly:

Capability typeDeclared capability
MetadataSupports searchSongs
LyricsSupports getLyrics
CoversSupports searchCovers

Capabilities are not mutually exclusive. A plugin with all three capabilities displays Metadata, Lyrics, and Covers labels beneath its name. The plugin manager exposes only Metadata, Lyrics, and Covers source types. Metadata sources are shared by single-song Main Search and batch metadata matching. Single-song operations expose Main Search, Lyrics, and Covers; batch operations expose separate Metadata, Lyrics, and Covers entries and do not automatically join capabilities inside one task. Capability information is shown in the install preview, plugin manager, and plugin configuration screen. The capability combination is persisted by the host during installation and updated with the manifest whenever the plugin is upgraded.

includeDirs can only reference relative directories inside the plugin package. Absolute paths, .., network URLs, and cross-plugin files are not allowed.

configFields

configFields declares user-configurable options. Saved values are passed into every plugin function call through request.config.

Config field JSON structure:

FieldTypeRequiredDefaultDescription
keystringYes-Config key, read via request.config[key] in JS
titlestringYes-Label shown in the config UI
summarystringNonullDescriptive text shown below the input
groupstringNo""Group name; fields with the same group are rendered together in a card. Defaults to "Basic"
typestringYes-Input control type, determines UI rendering
requiredbooleanNofalseWhether the field must be filled before saving
defaultValuestringNo""Initial value when the plugin is first loaded
optionsOption[]No[]Option list, required only for dropdown type
dependencyDependencyNonullConditional visibility rule, see Dependency System

Option structure:

FieldTypeDescription
valuestringActual value stored in config
labelstringDisplay text in the dropdown list
summarystringExtra description shown in grey in the dropdown

Type Reference

Each type controls how the field appears and behaves in the UI.

text — Single-line text

json
{ "key": "server_url", "title": "Server URL", "summary": "Base URL of the API", "type": "text", "required": true, "defaultValue": "https://api.example.com" }

password — Secret / token

Input is masked. Suitable for API keys, tokens, cookies, and other sensitive data.

json
{ "key": "api_token", "title": "API Token", "summary": "Get from your service provider dashboard", "type": "password", "required": true, "defaultValue": "" }

number — Numeric input

Restricts input to digit characters. Useful for timeout seconds, page size, etc.

json
{ "key": "timeout", "title": "Timeout (seconds)", "summary": "HTTP request timeout", "type": "number", "defaultValue": "15" }

switch — Toggle

Boolean-like control stored as the string "true" or "false". Convert explicitly in JS.

json
{ "key": "use_proxy", "title": "Use proxy", "summary": "Route requests through a proxy server", "type": "switch", "defaultValue": "false" }

JS: var useProxy = request.config.use_proxy === "true";

json
{
  "key": "lyrics_source",
  "title": "Lyrics source",
  "summary": "Which lyrics source the plugin should prefer",
  "type": "dropdown",
  "required": true,
  "defaultValue": "official",
  "options": [
    { "value": "official", "label": "Official lyrics", "summary": "LRC provided by the copyright holder" },
    { "value": "user", "label": "User-uploaded lyrics", "summary": "Translation submitted by users" }
  ]
}

textarea — Multi-line text

Suitable for long JSON config, custom scripts, multi-line notes.

json
{ "key": "custom_headers", "title": "Custom headers", "summary": "One header per line, format: Key: Value", "type": "textarea", "defaultValue": "" }

markdown — Explanatory text

Display-only field. Not included in request.config. Use for usage instructions, notes, sponsorship info. defaultValue is rendered as Markdown body; title as heading.

json
{
  "key": "help_note",
  "title": "Usage instructions",
  "type": "markdown",
  "defaultValue": "### How to get an API Key\n\n1. Register an account\n2. Go to API Management\n3. Click Generate Key\n\n> Free tier: 1000 requests/day"
}

Grouping

Fields sharing the same group value are rendered together in a single card, with the group name as the card title. Empty values default to "Basic".

json
"configFields": [
  { "key": "api_key", "title": "API Key", "group": "Authentication", "type": "password", "required": true },
  { "key": "api_secret", "title": "API Secret", "group": "Authentication", "type": "password" },
  { "key": "region", "title": "Region", "group": "Request", "type": "dropdown", "defaultValue": "cn", "options": [...] },
  { "key": "timeout", "title": "Timeout (s)", "group": "Request", "type": "number", "defaultValue": "15" },
  { "key": "cover_size", "title": "Cover size", "group": "Cover", "type": "dropdown", "defaultValue": "800", "options": [...] }
]

The UI renders three cards: Authentication (2 items), Request (2 items), Cover (1 item).

Dependency System (dependency)

dependency controls field visibility: the field only appears in the UI when its condition is satisfied. Four sub-types are supported:

TypeDescription
matchVisible when a specified field equals a given value
andVisible when all sub-conditions are met
orVisible when any sub-condition is met
notVisible when the condition is NOT met

match — Simple equality

json
{
  "key": "proxy_url",
  "title": "Proxy URL",
  "type": "text",
  "dependency": { "match": { "key": "use_proxy", "value": "true" } }
}

and — All conditions

json
{
  "key": "token_url",
  "title": "Token endpoint",
  "type": "text",
  "dependency": {
    "and": {
      "conditions": [
        { "match": { "key": "auth_type", "value": "oauth" } },
        { "match": { "key": "custom_server", "value": "true" } }
      ]
    }
  }
}

or — Any condition

json
{
  "key": "proxy_exclude",
  "title": "Proxy exclusion domains",
  "type": "text",
  "dependency": {
    "or": {
      "conditions": [
        { "match": { "key": "use_proxy", "value": "true" } },
        { "match": { "key": "use_vpn", "value": "true" } }
      ]
    }
  }
}

not — Negation

json
{
  "key": "custom_host",
  "title": "Custom host",
  "type": "text",
  "dependency": {
    "not": {
      "condition": { "match": { "key": "server_mode", "value": "auto" } }
    }
  }
}

Complete Config Example

Combining all features into a realistic configFields array:

json
"configFields": [
  {
    "key": "help_intro",
    "title": "Welcome",
    "type": "markdown",
    "defaultValue": "This plugin connects to the **MusicApi** service.\n\nEnter your API Key below to get started."
  },
  {
    "key": "api_key",
    "title": "API Key",
    "summary": "Get one at https://example.com/console",
    "group": "Authentication",
    "type": "password",
    "required": true
  },
  {
    "key": "use_custom_host",
    "title": "Custom server",
    "group": "Authentication",
    "type": "switch",
    "defaultValue": "false"
  },
  {
    "key": "custom_host",
    "title": "Server host",
    "group": "Authentication",
    "type": "text",
    "dependency": { "match": { "key": "use_custom_host", "value": "true" } }
  },
  {
    "key": "lyrics_source",
    "title": "Lyrics source",
    "group": "Lyrics",
    "type": "dropdown",
    "defaultValue": "official",
    "options": [
      { "value": "official", "label": "Official lyrics" },
      { "value": "translated", "label": "Translated lyrics" }
    ]
  },
  {
    "key": "cover_size",
    "title": "Cover size",
    "group": "Cover",
    "type": "dropdown",
    "defaultValue": "800",
    "options": [
      { "value": "300", "label": "300 × 300" },
      { "value": "800", "label": "800 × 800" },
      { "value": "1200", "label": "1200 × 1200" }
    ]
  },
  {
    "key": "timeout",
    "title": "Timeout (s)",
    "group": "Request",
    "type": "number",
    "defaultValue": "15"
  },
  {
    "key": "help_footer",
    "title": "Notes",
    "type": "markdown",
    "defaultValue": "> Free tier: 1000 requests/day\n> Open an issue on GitHub for support"
  }
]

Runtime Data Return

Plugin functions return search data through two JSON objects: fields (host-standard metadata fields like title, artist) and internal (plugin-private context like platform IDs, tokens).

See Configuration And Result Fields for the full standard field list, internal size constraints, and host write policies.