Skip to content

Plugin Specification

plugin.json sits at the root of every full-featured plugin (and the same schema is embedded in script-plugin comments). Wox reads it to decide whether the plugin can load on the current platform, which runtime/entry file to run, and how to register trigger keywords and commands.

plugin.json fields

FieldRequiredDescriptionExample
IdStable unique id (UUID recommended)"cea0f...28855"
NameDisplay name"Calculator"
DescriptionShort summary for the store and settings UI"Calculate simple expressions"
AuthorAuthor name"Wox Team"
VersionPlugin semantic version (MAJOR.MINOR.PATCH)"1.0.0"
MinWoxVersionMinimum Wox version required"2.0.0"
WebsiteHomepage/repo link"https://github.com/Wox-launcher/Wox"
RuntimePYTHON, NODEJS, SCRIPT (Go is reserved for system plugins)"PYTHON"
EntryEntry file relative to plugin root. For script plugins this is filled automatically by Wox."main.py"
IconWoxImage string (emoji/base64/relative path)"emoji:🧮"
TriggerKeywordsOne or more trigger keywords. Use "*" for global trigger.["calc"]
CommandsOptional commands (see Query Model)[{"Command":"install","Description":"Install plugins"}]
SupportedOSAny of Windows, Linux, Macos. Empty defaults to all for script plugins.["Windows","Macos"]
FeaturesOptional feature flags with parameters (see below)[{"Name":"debounce","Params":{"IntervalMs":"200"}}]
SettingDefinitionsSettings schema rendered in Wox settings[...]
I18nInline translations (see Internationalization){"en_US":{"key":"value"}}

Icon formats

Icon uses the WoxImage string format:

  • emoji:🧮
  • data:image/png;base64,<...> or bare base64 (png assumed)
  • relative/path/to/icon.png (resolved relative to the plugin folder)
  • Absolute paths are accepted but avoid them for portable plugins.

Example plugin.json

json
{
  "Id": "cea0fdfc6d3b4085823d60dc76f28855",
  "Name": "Calculator",
  "Description": "Quick math in the launcher",
  "Author": "Wox Team",
  "Version": "1.0.0",
  "MinWoxVersion": "2.0.0",
  "Runtime": "PYTHON",
  "Entry": "main.py",
  "Icon": "emoji:🧮",
  "TriggerKeywords": ["calc"],
  "SupportedOS": ["Windows", "Linux", "Macos"],
  "Features": [{ "Name": "debounce", "Params": { "IntervalMs": "250" } }, { "Name": "ai" }],
  "SettingDefinitions": [
    {
      "Type": "textbox",
      "Value": {
        "Key": "api_key",
        "Label": "API Key",
        "Tooltip": "Get it from your provider",
        "DefaultValue": ""
      }
    }
  ]
}

Feature flags

Add items to Features when your plugin needs extra capabilities:

  • querySelection – receive selection/drag/drop queries (QueryTypeSelection).
  • debounce – avoid flooding query while the user types. Params: IntervalMs (string ms).
  • ignoreAutoScore – opt out of Wox frequency-based auto scoring.
  • queryEnv – request query environment data. Params: requireActiveWindowName, requireActiveWindowPid, requireActiveWindowIcon, requireActiveBrowserUrl ("true"/"false").
  • ai – allow usage of AI APIs from plugins.
  • deepLink – enables custom deep links exposed by the plugin.
  • resultPreviewWidthRatio – control result list vs preview width. Params: WidthRatio between 0 and 1.
  • mru – enable Most Recently Used support; implement OnMRURestore in your plugin.
  • gridLayout – display results in a grid layout instead of a list. Useful for visual items like emoji, icons, or colors. See Grid Layout for details.

SettingDefinitions

Settings are rendered in the Wox settings UI and passed to the plugin host:

TypeDescriptionKeys
headSection headerContent
labelRead-only textContent, Tooltip, optional Style
textboxSingle/multi-line textKey, Label, Suffix, DefaultValue, Tooltip, MaxLines, Style
checkboxBooleanKey, Label, DefaultValue, Tooltip, Style
selectDropdownKey, Label, DefaultValue, Options[] { Label, Value }, Tooltip, Style
selectAIModelDropdown of available AI models (populated dynamically by Wox)Key, Label, DefaultValue, Tooltip, Style
tableEditable table rowsKey, Columns, DefaultValue, Tooltip, Style
dynamicPlaceholder that will be filled by the plugin via APIKey only
newlineVisual separator(no value)

Style supports PaddingLeft/Top/Right/Bottom, Width, and LabelWidth. Settings are provided to plugins as part of init parameters and (for script plugins) as WOX_SETTING_<KEY> environment variables.

SettingDefinitions examples

Minimal layout with AI model pick:

json
{
  "SettingDefinitions": [
    { "Type": "head", "Value": "API" },
    {
      "Type": "textbox",
      "Value": {
        "Key": "api_key",
        "Label": "API Key",
        "Tooltip": "Get it from your provider",
        "DefaultValue": "",
        "Style": { "Width": 320, "LabelWidth": 90 }
      }
    },
    {
      "Type": "selectAIModel",
      "Value": {
        "Key": "model",
        "Label": "Model",
        "DefaultValue": "",
        "Tooltip": "Use a configured AI provider"
      }
    },
    { "Type": "newline" }
  ]
}

Table + dynamic setting populated at runtime:

json
{
  "SettingDefinitions": [
    { "Type": "head", "Value": "Mappings" },
    {
      "Type": "table",
      "Value": {
        "Key": "rules",
        "Tooltip": "Key/value rules",
        "Columns": [
          { "Title": "Key", "Width": 150 },
          { "Title": "Value", "Width": 240 }
        ],
        "DefaultValue": [
          ["foo", "bar"],
          ["hello", "world"]
        ]
      }
    },
    {
      "Type": "dynamic",
      "Value": {
        "Key": "runtime_options"
      }
    }
  ]
}

How values reach your plugin:

  • Full-featured plugins: read/write with GetSetting + SaveSetting in the host SDK. Provide dynamic content via the SDK’s dynamic setting callback.
  • Script plugins: Wox exports each key as WOX_SETTING_<UPPER_SNAKE_KEY> environment variables.

Dynamic setting callback (backend wiring)

Python (wox-plugin):

python
from wox_plugin import Plugin, Context, PluginInitParams
from wox_plugin.models.setting import PluginSettingDefinitionItem, PluginSettingDefinitionType, PluginSettingValueSelect

class MyPlugin(Plugin):
    async def init(self, ctx: Context, params: PluginInitParams) -> None:
        self.api = params.api

        async def get_dynamic(key: str) -> PluginSettingDefinitionItem:
            if key == "runtime_options":
                return PluginSettingDefinitionItem(
                    type=PluginSettingDefinitionType.SELECT,
                    value=PluginSettingValueSelect(
                        key="runtime_options",
                        label="Runtime Options",
                        default_value="a",
                        options=[
                            {"Label": "Option A", "Value": "a"},
                            {"Label": "Option B", "Value": "b"},
                        ],
                    ),
                )
            return None  # Unknown key

        await self.api.on_get_dynamic_setting(ctx, get_dynamic)

Node.js (SDK types):

typescript
import { Plugin, Context, PluginInitParams, PluginSettingDefinitionItem } from "@wox-launcher/wox-plugin";

class MyPlugin implements Plugin {
  private api: any;

  async init(ctx: Context, params: PluginInitParams): Promise<void> {
    this.api = params.API;

    await this.api.OnGetDynamicSetting(ctx, (key: string): PluginSettingDefinitionItem | null => {
      if (key !== "runtime_options") return null;
      return {
        Type: "select",
        Value: {
          Key: "runtime_options",
          Label: "Runtime Options",
          DefaultValue: "a",
          Options: [
            { Label: "Option A", Value: "a" },
            { Label: "Option B", Value: "b" },
          ],
        },
      };
    });
  }
}

Heads-up: dynamic settings are fetched on demand when the settings page is opened. Keep callbacks fast and deterministic; cache remote data if needed to avoid slowing the UI.

Internationalization

Wox supports plugin internationalization (i18n) so your plugin can display text in the user's preferred language. There are two ways to provide translations:

Define translations directly in plugin.json using the I18n field. This is especially useful for script plugins that don't have a directory structure:

json
{
  "Id": "my-plugin-id",
  "Name": "My Plugin",
  "Description": "i18n:plugin_description",
  "TriggerKeywords": ["mp"],
  "I18n": {
    "en_US": {
      "plugin_description": "A useful plugin",
      "result_title": "Result: {0}",
      "action_copy": "Copy to clipboard"
    },
    "zh_CN": {
      "plugin_description": "一个有用的插件",
      "result_title": "结果: {0}",
      "action_copy": "复制到剪贴板"
    }
  }
}

Create a lang/ directory in your plugin root with JSON files named by language code:

my-plugin/
├── plugin.json
├── main.py
└── lang/
    ├── en_US.json
    └── zh_CN.json

Each language file contains a flat key-value map:

json
// lang/en_US.json
{
  "plugin_description": "A useful plugin",
  "result_title": "Result: {0}",
  "action_copy": "Copy to clipboard"
}
json
// lang/zh_CN.json
{
  "plugin_description": "一个有用的插件",
  "result_title": "结果: {0}",
  "action_copy": "复制到剪贴板"
}

Using Translations

To use a translation, prefix your text with i18n: followed by the key:

python
# Python example
result = Result(
    title="i18n:result_title",
    sub_title="i18n:action_copy"
)

# Or use the API to get translated text programmatically
translated = await api.get_translation(ctx, "i18n:result_title")
typescript
// Node.js example
const result: Result = {
  Title: "i18n:result_title",
  SubTitle: "i18n:action_copy",
};

// Or use the API
const translated = await api.GetTranslation(ctx, "i18n:result_title");

Translation Priority

Wox looks up translations in this order:

  1. Inline I18n in plugin.json (current language)
  2. lang/{current_lang}.json file
  3. Inline I18n in plugin.json (en_US fallback)
  4. lang/en_US.json file (fallback)
  5. Return the original key if no translation found

Supported Languages

CodeLanguage
en_USEnglish (US)
zh_CNChinese (Simplified)
pt_BRPortuguese (Brazil)
ru_RURussian

Tip: Always provide en_US translations as the fallback language.

Grid Layout

The gridLayout feature enables displaying results in a grid format instead of the default vertical list. This is ideal for plugins that display visual items such as emoji, icons, colors, or image thumbnails.

Configuration

Add the gridLayout feature to your plugin.json:

json
{
  "Features": [
    {
      "Name": "gridLayout",
      "Params": {
        "Columns": "8",
        "ShowTitle": "false",
        "ItemPadding": "12",
        "ItemMargin": "6"
      }
    }
  ]
}

Parameters

ParameterTypeDefaultDescription
Columnsstring"8"Number of columns per row
ShowTitlestring"false"Whether to show title text below each icon ("true" or "false")
ItemPaddingstring"12"Padding inside each grid item (in pixels)
ItemMarginstring"6"Margin around each grid item (in pixels)

Result Structure

When using grid layout, each result should have:

  • Icon: The main visual element displayed in the grid cell (required)
  • Title: Shown below the icon if ShowTitle is "true" (truncated with ellipsis if too long)
  • Group: Optional grouping to organize items into sections with headers

Example: Emoji Picker Plugin

json
{
  "Id": "emoji-picker-plugin",
  "Name": "Emoji Picker",
  "TriggerKeywords": ["emoji"],
  "Features": [
    {
      "Name": "gridLayout",
      "Params": {
        "Columns": "12",
        "ShowTitle": "false",
        "ItemPadding": "12",
        "ItemMargin": "6"
      }
    }
  ]
}
python
from wox_plugin import Plugin, Context, Query, Result

class EmojiPlugin(Plugin):
    async def query(self, ctx: Context, query: Query) -> list[Result]:
        emojis = ["😀", "😃", "😄", "😁", "😅", "😂", "🤣", "😊"]
        return [
            Result(
                title=emoji,
                icon=f"emoji:{emoji}",
                group="Smileys"
            )
            for emoji in emojis
        ]

Grouping Items

Use the group field to organize grid items into sections. Items with the same group value will be displayed together under a group header:

python
results = [
    Result(title="😀", icon="emoji:😀", group="Smileys"),
    Result(title="😃", icon="emoji:😃", group="Smileys"),
    Result(title="❤️", icon="emoji:❤️", group="Hearts"),
    Result(title="💙", icon="emoji:💙", group="Hearts"),
]

This produces a layout with "Smileys" and "Hearts" section headers, each followed by their respective emoji in a grid.

Layout Calculation

The grid automatically calculates item sizes based on:

  1. Available width divided by number of columns = cell width
  2. Icon size = cell width - (ItemPadding + ItemMargin) × 2
  3. Cell height = cell width + title height (if ShowTitle is enabled)

Adjust ItemPadding and ItemMargin to control spacing between items. Larger values create more breathing room; smaller values fit more items on screen.

Released under the GPL-3.0 License.