.agents/skills/wox-plugin-creator/references/sdk_nodejs.md
Wox requires Node.js 20 or later.
pnpm add @wox-launcher/wox-plugin
interface Plugin {
init(ctx: Context, params: PluginInitParams): Promise<void>;
query(ctx: Context, query: Query): Promise<QueryResponse>;
}
Return QueryResponse when plugin.json declares MinWoxVersion >= 2.0.4.
Use QueryResponse.Layout.ResultPreviewWidthRatio and
QueryResponse.Layout.GridLayout for query-scoped layout. The older
resultPreviewWidthRatio and gridLayout metadata features are deprecated
because they can only describe static plugin or command defaults.
interface PluginInitParams {
API: PublicAPI;
PluginDirectory: string;
}
interface Query {
Type: "input" | "selection";
RawQuery: string;
TriggerKeyword: string;
Command: string;
Search: string;
}
interface Result {
Title: string; // Supports "i18n:key" prefix for auto-translation
SubTitle?: string; // Supports "i18n:key" prefix
Icon: WoxImage;
Actions: ResultAction[];
Score?: number; // 0-100, optional
ContextData?: any; // Data passed to actions
}
interface ResultAction {
Id: string;
Name: string;
IsDefault?: boolean;
Action: (ctx: Context, actionContext: ActionContext) => Promise<void>;
}
type WoxImageType = "absolute" | "relative" | "base64" | "svg" | "url" | "emoji" | "lottie";
interface WoxImage {
ImageType: WoxImageType;
ImageData: string;
}
The ctx object is required for all API calls.
ChangeQuery(ctx, query: PlainQuery): Update the search bar text.HideApp(ctx): Hide the Wox window.ShowApp(ctx): Show the Wox window.Notify(ctx, message): Display a system notification.Log(ctx, level, msg): Write to plugin logs. Levels: "Info", "Error", "Debug", "Warning".Copy(ctx, params: CopyParams): Copy text or image to clipboard.IsVisible(ctx): Check if Wox window is visible.If the plugin needs on-disk cache, prefer GetCacheFolder over any custom directory.
GetCacheFolder(ctx): Return ~/.wox/cache/plugins/<plugin-id>/. Wox creates it if needed and deletes it on uninstall.init(), keep the path, and write downloads, thumbnails, and search-result files under it.cache/, tmp/, or downloads/ next to the plugin file, under user data, or under a hardcoded folder name.GetSetting / SetSetting for those.Prefer these APIs for all plugin settings. Values stored here can sync across machines through Wox cloud sync. Do not persist ordinary settings in local files or a custom store.
GetSetting(ctx, key): Retrieve a stored setting.SaveSetting(ctx, key, value, isPlatformSpecific): Save a setting. Normal plugin settings are eligible for cloud sync, so pass true for platform-only values such as local paths, executable paths, shell commands, hotkeys, browser profiles, application paths, and system integrations.OnSettingChanged(ctx, callback): Subscribe to setting changes.OnGetDynamicSetting(ctx, callback): Provide runtime-generated setting definitions for dynamic settings.UpdateResult(ctx, result: UpdatableResult): Update a specific result in real-time (e.g., progress bars).PushResults(ctx, query, results): Append results to the current list.RefreshQuery(ctx, param): Re-run the current query.GetUpdatableResult(ctx, resultId): Get current state of a result.AIChatStream(ctx, model, conversations, options, callback): Stream responses from AI providers.GetTranslation(ctx, key): Get a raw translated string (without formatting).
Note: You must handle string formatting (e.g.,
sprintfor template literals) in your code. This method only returns the raw string from the lang file.
GetSetting, SaveSetting, and OnSettingChanged for plugin settings. These APIs participate in Wox cloud sync across machines. Avoid local files or custom persistence for values the user would expect to follow them to another device.GetCacheFolder(ctx) first. Do not invent a cache directory under the plugin folder or user-data tree.references/plugin_json_schema.md before writing plugin.json settings.references/settings_patterns.md.OnGetDynamicSetting is used together with a dynamic entry in SettingDefinitions.SaveSetting(ctx, key, value, isPlatformSpecific) calls to the setting metadata. Do not hardcode false for dynamically saved settings if their SettingDefinitions entry uses IsPlatformSpecific: true.DisabledInPlatforms only controls where the setting is disabled; it does not isolate cloud-synced values.QueryRequirements in plugin.json when a query requires settings such as API keys. Wox blocks the query before calling query() and shows the built-in query_requirement_settings setup preview.register_query_requirements API. Declare query requirements in metadata.export interface PluginQueryRequirement {
SettingKey: string;
Validators?: PluginSettingValidator[];
Message?: string;
}
export interface PluginQueryRequirements {
AnyQuery?: PluginQueryRequirement[];
QueryWithoutCommand?: PluginQueryRequirement[];
QueryWithCommand?: Record<string, PluginQueryRequirement[]>;
}
Metadata example:
{
"SettingDefinitions": [
{
"Type": "textbox",
"Value": {
"Key": "accessKey",
"Label": "i18n:access_key",
"DefaultValue": "",
"Validators": [{ "Type": "not_empty", "Value": {} }]
}
}
],
"QueryRequirements": {
"AnyQuery": [
{
"SettingKey": "accessKey",
"Message": "i18n:access_key_required"
}
],
"QueryWithoutCommand": [],
"QueryWithCommand": {}
}
}
import { Plugin, Query, Result, WoxImage } from "@wox-launcher/wox-plugin";
class MyPlugin implements Plugin {
private api: any;
async init(ctx, params) {
this.api = params.API;
}
async query(ctx, query) {
// Example: Getting a translation and formatting it
const rawTemplate = await this.api.GetTranslation(ctx, "hello_template"); // "Hello, %s!"
const greeting = rawTemplate.replace("%s", query.Search);
return [
{
Title: greeting,
Icon: { ImageType: "emoji", ImageData: "👋" },
Actions: [{ Id: "copy", Name: "Copy", Action: async () => {} }],
},
];
}
}
export const plugin = new MyPlugin();