Wox Documentation

A cross-platform launcher that simply works

RAW Doc

File: README.md

A launcher that stays out of your way

You already know what you want to do. Wox helps you get there: open an app, find a file, run an action โ€” then get out of the way.

Wox is a fully native, open-source launcher for macOS, Linux, and Windows โ€” with GPU rendering on every platform. Everyday use typically stays around ~150 MB of memory, so it can live in the background without feeling like another heavy desktop app.

Local search, keyboard-first actions, and an extensible plugin system stay in one focused input.

Download Wox ยท Browse plugins ยท Read the docs

Press Alt/Command + Space, type what you need, and press Enter.

https://github.com/user-attachments/assets/1b282fde-c1c5-426a-b45d-cd0aa329386a

Why Wox

Fully native Full native GPU rendering on macOS, Linux, and Windows โ€” not Electron, not a browser shell.
~150 MB memory Built to stay light while idle and during everyday queries, so the launcher can stay resident without taxing the machine.
Keyboard-first Open apps, find files, run actions, and finish the next step without leaving the input.
Plugin-driven Start with built-ins, then extend with Node.js, Python, or script plugins from the store.

Install

Platform Method Command or instructions
macOS Homebrew brew install --cask wox
Windows Winget winget install -e --id Wox.Wox
Windows Scoop scoop install extras/wox
Windows Chocolatey choco install wox
Arch Linux AUR yay -S wox-bin
Debian / Ubuntu .deb Download wox-linux-amd64.deb from Releases, then sudo apt install ./wox-linux-amd64.deb
Fedora / RHEL .rpm Download wox-linux-amd64.rpm from Releases, then sudo dnf install ./wox-linux-amd64.rpm
openSUSE .rpm Download wox-linux-amd64.rpm from Releases, then sudo zypper install ./wox-linux-amd64.rpm
macOS / Linux / Windows Manual Download the latest stable package from Releases and run it directly

Documentation

Contributing

Contributions are welcome through issues, discussions, and pull requests.

Sponsors

Free code signing on Windows provided by SignPath.io, with certificates from SignPath Foundation.

Project Activity


File: screenshots/README.md

APP

AI Chat

Setting

Auto Theme


File: wox.core/common/README.md

Due to the GO's cyclic reference limitation, some common type definitions are defined in this package


File: wox.core/migration/README.md

Migration (one file per migration)

Wox uses an application-level migration runner (separate from Gorm AutoMigrate) for data / settings compatibility upgrades.

How it works

  • Each migration is a Go file under wox.core/migration/ (same package: migration).
  • Each file registers itself via init() + migration.Register(...).
  • Migrations run in lexicographic order of ID().
  • Applied/skipped migrations are persisted in SQLite table migration_records (model: database.MigrationRecord).

Create a new migration

  1. Add a file like wox.core/migration/mYYYYMMDD_short_name.go
  2. Implement the interface:
go
type Migration interface {
    ID() string
    Description() string
    Up(ctx context.Context, tx *gorm.DB) error
}
  1. Register it:
go
func init() { Register(&myMigration{}) }

Optional hooks

  • If a migration only applies under certain conditions, implement:
go
type ConditionalMigration interface {
    Migration
    IsNeeded(ctx context.Context, db *gorm.DB) (bool, error)
}
  • If a migration needs filesystem actions after DB commit (e.g. rename legacy files), implement:
go
type PostCommitMigration interface {
    Migration
    AfterCommit(ctx context.Context) error
}

File: wox.core/plugin/system/mediaplayer/woxmr/README.md

WoxMR (MediaRemote XS Bridge)

Why do we need WoxMR?

  • On macOS 15+, Apple restricts the private MediaRemote framework: only processes with bundle ids starting with com.apple.* may call it.
  • The Wox process is not com.apple.*, so calls would be rejected even with dynamic loading from Go/CGO.
  • The system /usr/bin/perl process has the bundle id com.apple.perl, which is permitted to access MediaRemote.
  • Therefore we run MediaRemote inside the com.apple.perl process and pass results back to Wox.

How it works

  • We ship a tiny Perl XS module woxmr.bundle that is loaded and executed inside the Perl process.
  • In the XS module (Objectiveโ€‘C), we dynamically load MediaRemote (dlopen + dlsym) and call:
    • MRMediaRemoteGetNowPlayingInfo
    • MRMediaRemoteGetNowPlayingApplicationIsPlaying
    • MRMediaRemoteGetNowPlayingApplicationPID
  • We assemble Now Playing data (title/artist/album/duration/position/playing, plus appName/bundleIdentifier) and return JSON to Perl.
  • Wox runs a small Perl adapter (adapter.pl) to get the JSON and then parses it.

Why not Go/CGO directly?

  • Even with dynamic loading from CGO, the caller remains the Wox process (not com.apple.*) and will be denied by the system.
  • Moving the callsite into /usr/bin/perl (com.apple.perl) naturally bypasses the restriction with zero extra requirements on endโ€‘user machines.

Why not an external framework?

  • Avoid shipping a large private framework: simpler distribution, signing, and maintenance.
  • We only ship a tiny woxmr.bundle (XS) + WoxMR.pm + adapter.pl: small, stable, and maintainable.

Build & distribution

  • Build happens only on a developer machine (requires Xcode CLT and system Perl).
  • End users need no dependencies. Distribute:
    • resource/others/woxmr/woxmr.bundle
    • resource/others/woxmr/WoxMR.pm
    • resource/others/woxmr/adapter.pl
  • The topโ€‘level Makefile exposes woxmr-build:
    • It autoโ€‘cleans, builds for the current arch (arm64/x86_64), forceโ€‘signs, and copies artifacts to the paths above.
    • It is also invoked automatically by the overall make build.

Runtime flow

  1. Wox runs adapter.pl:
    • /usr/bin/perl resource/others/woxmr/adapter.pl get
  2. adapter.pl uses WoxMR to load and execute the XS code inside Perl:
    • The XS code accesses MediaRemote and returns a JSON string.
  3. Wox parses the JSON and displays the Now Playing information.

File: wox.plugin.nodejs/README.md

Wox Plugin SDK for TypeScript/JavaScript

TypeScript type definitions and SDK for developing Wox plugins in TypeScript/JavaScript.

Quick Start

Installation

bash
npm install wox-plugin

Basic Plugin

This example returns QueryResponse, so the plugin's plugin.json should set
MinWoxVersion to 2.0.4 or newer. Return Result[] directly if you need the
same plugin build to run on older Wox releases.

typescript
import { Plugin, Context, Query, QueryResponse, Result, NewContext, WoxImage } from "wox-plugin"

class MyPlugin implements Plugin {
  private api: PublicAPI

  async init(ctx: Context, initParams: PluginInitParams): Promise<void> {
    this.api = initParams.API
    await this.api.Log(ctx, "Info", "MyPlugin initialized")
  }

  async query(ctx: Context, query: Query): Promise<QueryResponse> {
    const results: Result[] = []

    for (const item of this.getItems(query.Search)) {
      results.push({
        Title: item.name,
        SubTitle: item.description,
        Icon: { ImageType: "emoji", ImageData: "๐Ÿ”" },
        Score: 100,
        Actions: [
          {
            Name: "Open",
            Icon: { ImageType: "emoji", ImageData: "๐Ÿ”—" },
            IsDefault: true,
            Action: async (ctx, actionCtx) => {
              await this.openItem(item)
            }
          }
        ]
      })
    }

    return { Results: results }
  }
}

Key Components

Plugin Interface

Every plugin must implement the Plugin interface:

typescript
interface Plugin {
  init: (ctx: Context, initParams: PluginInitParams) => Promise<void>
  query: (ctx: Context, query: Query) => Promise<QueryReturn>
}

Returning Result[] directly is deprecated. The Node.js host still accepts it
for compatibility with older Wox releases. Use QueryResponse only when
plugin.json declares MinWoxVersion >= 2.0.4 so results, refinements, and
layout hints are carried together.

When a plugin needs to control the preview width or grid layout, set
QueryResponse.Layout.ResultPreviewWidthRatio or QueryResponse.Layout.GridLayout.
The older resultPreviewWidthRatio and gridLayout metadata features are
deprecated because they can only describe static plugin or command defaults.

Query Models

  • Query: User query with search text, type, selection, environment
  • QueryType: INPUT (typing) or SELECTION (selected content)
  • Selection: Text or file paths selected by user
  • QueryEnv: Environment context (active window, browser URL)

Result Models

  • Result: Search result with title, icon, preview, actions
  • ResultAction: User action on a result
  • ResultActionType: EXECUTE (immediate) or FORM (show form)
  • ResultTail: Additional visual elements (text or image)
  • UpdatableResult: Result that can be updated in UI

Image Types

Supported image types:

  • absolute: Absolute file path
  • relative: Path relative to plugin directory
  • base64: Base64 encoded image with data URI prefix (data:image/png;base64,...)
  • svg: SVG string content
  • url: HTTP/HTTPS URL
  • emoji: Emoji character
typescript
// Emoji icon
{ ImageType: "emoji", ImageData: "๐Ÿ”" }

// Base64 image
{ ImageType: "base64", ImageData: "data:image/png;base64,iVBORw0..." }

// Relative path
{ ImageType: "relative", ImageData: "./icons/icon.png" }

Public API

Methods for interacting with Wox:

  • UI Control: showApp(), hideApp(), isVisible(), notify()
  • Toolbar Msg: ShowToolbarMsg(), ClearToolbarMsg(), OnEnterPluginQuery(), OnLeavePluginQuery()
  • Query: changeQuery(), refreshQuery(), pushResults()
  • Settings: GetSetting(), SetSetting(), OnSettingChanged(); legacy SaveSetting() remains available but is deprecated
  • Logging: log()
  • i18n: getTranslation()
  • Results: getUpdatableResult(), updateResult()
  • AI: llmStream()
  • MRU: onMruRestore()
  • Callbacks: onUnload(), onDeepLink()
  • Commands: registerQueryCommands()
  • Clipboard: copy()

Actions

Actions are operations users can perform on results:

typescript
ResultAction({
  name: "Copy",
  icon: { ImageType: "emoji", ImageData: "๐Ÿ“‹" },
  isDefault: true,
  hotkey: "Ctrl+C",
  action: async (ctx, actionCtx) => {
    await this.copyToClipboard(actionCtx.contextData)
  }
})

Settings

Define settings for your plugin:

SetSetting() requires Wox >= 2.4.0 and accepts a single SetSettingOption. Set
IsLocal: true when a value must stay on the current device and remain outside
Cloud Sync. Use legacy SaveSetting() only when the same plugin build must run
on Wox releases before 2.4.0.

typescript
const settings: PluginSettingDefinitionItem[] = [
  {
    Type: "textbox",
    Value: {
      Key: "apiKey",
      Label: "API Key",
      Suffix: "",
      DefaultValue: "",
      Tooltip: "Enter your API key",
      MaxLines: 1,
      Validators: []
    } as PluginSettingValueTextBox,
    DisabledInPlatforms: [],
    IsPlatformSpecific: false
  },
  {
    Type: "checkbox",
    Value: {
      Key: "enabled",
      Label: "Enable Feature",
      DefaultValue: "true",
      Tooltip: ""
    } as PluginSettingValueCheckBox,
    DisabledInPlatforms: [],
    IsPlatformSpecific: false
  }
]

Style is deprecated and should not be used for new settings. Wox owns setting
spacing and control widths so plugin settings remain visually consistent.

AI/LLM Integration

Stream responses from AI models:

typescript
const conversations: AI.Conversation[] = [
  { Role: "system", Text: "You are a helpful assistant.", Timestamp: Date.now() },
  { Role: "user", Text: "Hello!", Timestamp: Date.now() }
]

await api.LLMStream(ctx, conversations, (data: AI.ChatStreamData) => {
  if (data.Status === "streaming") {
    console.log("Chunk:", data.Data)
  } else if (data.Status === "finished") {
    console.log("Complete:", data.Data)
  }
})

Plugin Metadata

Plugins must declare metadata in a plugin.json file:

json
{
  "ID": "com.myplugin.example",
  "Name": "My Plugin",
  "Author": "Your Name",
  "Version": "1.0.0",
  "MinWoxVersion": "2.0.4",
  "Runtime": "nodejs",
  "Entry": "main.js",
  "TriggerKeywords": ["my"],
  "Description": "My awesome Wox plugin",
  "Website": "https://github.com/user/myplugin",
  "Icon": "https://example.com/icon.png",
  "QueryRequirements": {
    "AnyQuery": [
      {
        "SettingKey": "apiKey",
        "Validators": [{ "Type": "not_empty" }],
        "Message": "i18n:my_plugin_api_key_required"
      }
    ],
    "QueryWithoutCommand": [],
    "QueryWithCommand": {
      "download": [
        {
          "SettingKey": "downloadPath",
          "Validators": [{ "Type": "not_empty" }]
        }
      ]
    }
  }
}

Query Flow

  1. User triggers Wox and types trigger keyword (e.g., "my query")
  2. Wox calls plugin.query() with:
    • query.TriggerKeyword = "my"
    • query.Command = ""
    • query.Search = "query"
  3. Plugin returns QueryResponse when MinWoxVersion is at least 2.0.4
  4. Wox displays results sorted by score

For More Information


File: wox.plugin.python/README.md

Wox Plugin Python

This package provides type definitions for developing Wox plugins in Python.

Requirements

  • Python >= 3.8 (defined in pyproject.toml)
  • Python 3.12 recommended for development (defined in .python-version)

Installation

bash
# Using pip
pip install wox-plugin

# Using uv (recommended)
uv add wox-plugin

Usage

This example returns QueryResponse, so the plugin's plugin.json should set
MinWoxVersion to 2.0.4 or newer. Return list[Result] directly if you need
the same plugin build to run on older Wox releases.

python
from wox_plugin import Query, QueryResponse, Result, Context, PluginInitParams, WoxImage

class MyPlugin:
    async def init(self, ctx: Context, params: PluginInitParams) -> None:
        self.api = params.API
        
    async def query(self, ctx: Context, query: Query) -> QueryResponse:
        # Your plugin logic here
        results = []
        results.append(
            Result(
                title="Hello Wox",
                sub_title="This is a sample result",
                icon=WoxImage.new_emoji("๐Ÿ”"),
                score=100
            )
        )
        return QueryResponse(results=results)

# MUST HAVE! The plugin class will be automatically loaded by Wox
plugin = MyPlugin()

Returning list[Result] directly is deprecated. The Python host still accepts
it for compatibility with older Wox releases. Use QueryResponse only when
plugin.json declares MinWoxVersion >= 2.0.4 so results, refinements, and
layout hints are carried together.

When a plugin needs to control the preview width or grid layout, set
QueryResponse.layout.result_preview_width_ratio or
QueryResponse.layout.grid_layout. The older resultPreviewWidthRatio and
gridLayout metadata features are deprecated because they can only describe
static plugin or command defaults.

Saving Settings

set_setting() requires Wox >= 2.4.0 and accepts a SetSettingOption. Set
is_local=True when a value must stay on the current device and remain outside
Cloud Sync. The older save_setting() method remains available for plugins
targeting Wox releases before 2.4.0, but is deprecated for new integrations.

Query Requirements

Plugins can declare settings that must be configured before Wox calls query():

json
{
  "QueryRequirements": {
    "AnyQuery": [
      {
        "SettingKey": "apiKey",
        "Validators": [{ "Type": "not_empty" }],
        "Message": "i18n:my_plugin_api_key_required"
      }
    ],
    "QueryWithoutCommand": [],
    "QueryWithCommand": {
      "download": [
        {
          "SettingKey": "downloadPath",
          "Validators": [{ "Type": "not_empty" }]
        }
      ]
    }
  }
}

License

MIT