## 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](https://github.com/Wox-launcher/Wox/releases) · [Browse plugins](https://wox-launcher.github.io/Wox/store/plugins.html) · [Read the docs](https://wox-launcher.github.io/Wox/)

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

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](https://github.com/Wox-launcher/Wox/releases), then `sudo apt install ./wox-linux-amd64.deb` |
| Fedora / RHEL | `.rpm` | Download `wox-linux-amd64.rpm` from [Releases](https://github.com/Wox-launcher/Wox/releases), then `sudo dnf install ./wox-linux-amd64.rpm` |
| openSUSE | `.rpm` | Download `wox-linux-amd64.rpm` from [Releases](https://github.com/Wox-launcher/Wox/releases), then `sudo zypper install ./wox-linux-amd64.rpm` |
| macOS / Linux / Windows | Manual | Download the latest stable package from [Releases](https://github.com/Wox-launcher/Wox/releases) and run it directly |

## Documentation

- [Project documentation](https://wox-launcher.github.io/Wox/)
- [Plugin store](https://wox-launcher.github.io/Wox/store/plugins.html)
- [Theme store](https://wox-launcher.github.io/Wox/store/themes.html)

## Contributing

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

- [Discussions](https://github.com/Wox-launcher/Wox/discussions)
- [Reddit](https://www.reddit.com/r/WoxLauncher/)
- [Issues](https://github.com/Wox-launcher/Wox/issues)
- [Pull requests](https://github.com/Wox-launcher/Wox/pulls)

## Sponsors



|  | Free code signing on Windows provided by [SignPath.io](https://signpath.io), with certificates from [SignPath Foundation](https://signpath.org). |
| --- | --- |



## Project Activity

---

## File: screenshots/README.md

# APP



# AI Chat



# Setting



# Fallback Search



# 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
}
```

3. 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

- Wox Documentation: https://github.com/Wox-launcher/Wox
- Plugin Examples: https://github.com/Wox-launcher/Wox.Plugin.Nodejs

---

## 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