www/docs/development/plugins/single-file-plugin.md
A single-file SDK plugin is one .py or CommonJS .js file that loads into Wox's existing Python or Node.js runtime host. It has the full Public API of a packaged SDK plugin, without a .wox package and without starting a new process for each query.
Script Plugin
= one file + a new process per call + stdin/stdout JSON-RPC
Single-file SDK Plugin
= one file + the shared SDK runtime host + full Public API
SDK Plugin
= .wox package + the shared SDK runtime host + full Public API
| Need | Choose |
|---|---|
| A one-shot shell or command wrapper | Script Plugin |
| One file, and you need the Wox API | Single-file SDK Plugin |
| Dependencies, resources, TypeScript, or multiple files | SDK Plugin |
Script plugins are not version 1 of this feature, and they are not deprecated.
Query and action on a single-file SDK plugin reuse the host process. Wox does not start a plugin-specific Python or Node process. Host crash recovery still uses the existing watchdog.
Use wpm create <name> and pick Python Single-file SDK Plugin or Node.js Single-file SDK Plugin. WPM writes:
~/.wox/wox-user/plugins/single-file/Wox.Plugin.<Name>.py
~/.wox/wox-user/plugins/single-file/Wox.Plugin.<Name>.js
Then opens the file. Saving it reloads the plugin.
This is also the direct WPM path for a Python SDK plugin. You do not need to clone the packaged Python template unless you need extra files or pip dependencies.
Python files use runtime PYTHON. You can import wox_plugin and use SDK models, helpers, and the full Public API.
# {
# "Id": "com.example.weather",
# "Name": "Weather",
# "Author": "Example",
# "Version": "1.0.0",
# "MinWoxVersion": "2.4.2",
# "Runtime": "PYTHON",
# "Description": "Show current weather",
# "Icon": "emoji:🌤️",
# "TriggerKeywords": ["weather"],
# "SupportedOS": ["Windows", "Linux", "Macos"]
# }
from wox_plugin import PluginInitParams, Query, QueryResponse, Result, WoxImage
class WeatherPlugin:
async def init(self, ctx, params: PluginInitParams):
self.api = params.api
async def query(self, ctx, query: Query):
return QueryResponse(results=[
Result(
title="Weather",
icon=WoxImage.new_emoji("🌤️"),
)
])
plugin = WeatherPlugin()
Node.js files use runtime NODEJS. The first version is CommonJS only:
.jsmodule.exports.pluginparams.APIimport / require @wox-launcher/wox-pluginWoxImage are object literalsThe first version does not support .mjs, ESM, TypeScript, npm dependencies, or SDK npm helpers. The Node host compiles dynamic import() to require(), so CommonJS can reuse the existing loader and require.cache reload.
// {
// "Id": "com.example.weather",
// "Name": "Weather",
// "Author": "Example",
// "Version": "1.0.0",
// "MinWoxVersion": "2.4.2",
// "Runtime": "NODEJS",
// "Description": "Show current weather",
// "Icon": "emoji:🌤️",
// "TriggerKeywords": ["weather"],
// "SupportedOS": ["Windows", "Linux", "Macos"]
// }
class WeatherPlugin {
async init(ctx, params) {
this.api = params.API
}
async query(ctx, query) {
return {
Results: [{
Title: "Weather",
Icon: {
ImageType: "emoji",
ImageData: "🌤️"
},
Actions: []
}]
}
}
}
module.exports.plugin = new WeatherPlugin()
Put a JSON object in the leading # or // comments. A shebang on the first line is allowed.
Required in the header:
IdNameVersionMinWoxVersionRuntimeTriggerKeywordsAlso supported: Author, Description, Icon, Website, Commands, SupportedOS, Features, Glances, SettingDefinitions, QueryRequirements, I18n.
Wox sets Entry to the file name and Directory to plugins/single-file. The header must not declare Entry or Directory.
Runtime must match the suffix. Wox does not guess or fall back:
| File | Valid Runtime |
|---|---|
.py | PYTHON |
.js | NODEJS |
Do not put a PYTHON or NODEJS file in plugins/scripts/. Script plugins without Runtime still load as SCRIPT. An explicit PYTHON/NODEJS Runtime in the scripts directory is rejected with a message to move the file to plugins/single-file/.
Saving the file reloads it after a short debounce (about 500ms).
init() runs once after each load or reload.Register unload callbacks whenever you start background work.
All single-file plugins live in plugins/single-file/. They do not load a shared lang/ folder. Use inline I18n in the header.
Metadata icons cannot be relative paths. Dynamic results should also avoid relative images. Supported image forms:
If you need extra resource files, package a .wox plugin. Settings and WPM locate the plugin file instead of opening the mixed shared directory.
The store does not add a new manifest field. Wox classifies the download from Runtime plus the URL path suffix (query strings are ignored):
| Runtime | URL suffix | Type |
|---|---|---|
PYTHON | .py | Single-file SDK Plugin |
NODEJS | .js | Single-file SDK Plugin |
PYTHON / NODEJS | .wox | Packaged SDK Plugin |
SCRIPT | script file | Script Plugin |
Unknown suffixes, missing suffixes, and mismatches such as PYTHON + .js are rejected. A plugin ID cannot change delivery form between .wox and single-file during update.
Single-file store rows must declare MinWoxVersion at or above the first Wox release that can load them. Header Id, Runtime, and Version must match the store manifest. Uninstall moves only that file to the trash.