PowerToys Run is a quick launcher for Windows. It is open-source and modular for additional plugins.

Official plugins include:

  • Calculator
  • Unit Converter
  • Value Generator
  • Windows Search

At the time of writing there are 20 plugins out of the box.

If you think the official plugins are not enough, you can write our own. The easiest way to get started is to look at what others did.

Browsing through some of the GitHub repos found above, gives you an idea of how the source code of a plugin looks like.


Demo Plugin

As a demo, I created a simple plugin that counts the words and characters of the query.

Demo Plugin

  • ActionKeyword: demo


Demo Settings

  • Count spaces: true | false

The source code:

Throughout this blog post, the demo plugin will be used as an example.


Before you create your own project, first take a look at the official checklist:

Key takeaways from the checklist:

  • Project name: Community.PowerToys.Run.Plugin.<PluginName>
  • Target framework: net8.0-windows
  • Create a Main.cs class
  • Create a plugin.json file

In Visual Studio, create a new Class Library project.

The edit the .csproj file to look something like this:

  • Platforms: x64 and ARM64
  • UseWPF to include references to WPF assemblies
  • Dependencies: PowerToys and Wox .dll assemblies

The .dll files referenced in the .csproj file are examples of dependencies needed, depending on what features your plugin should support.

Unfortunately, these assemblies do not exist as packages on NuGet.

Therefore I like to commit these .dll files to the repo in a libs folder.

I’ll copy the x64 versions of the .dll files from the installation location:

  • C:\Program Files\PowerToys\
    • Machine wide installation of PowerToys
  • %LocalAppData%\PowerToys\
    • Per user installation of PowerToys

In the case of the ARM64 versions of the .dll files, I’ll build them from source. I don’t own an ARM64 machine to install PowerToys on.

Other people like to resolve the dependencies by referencing the PowerToys projects directly. Like the approach by Lin Yu-Chieh (Victor):

The project should start out with these files:

  • Images\*.png
    • Typically dark and light versions of icons
  • Main.cs
    • The starting point of the plugin logic
  • plugin.json
    • The plugin metadata


Create a plugin.json file that looks something like this:

The format is described in the Dev Documentation:


Create a Main.cs file that looks something like this:

The Main class must have a public, static string property named PluginID:

public static string PluginID => "AE953C974C2241878F282EA18A7769E4";
  • 32 digits Guid without hyphens
  • Must match the value in the plugin.json file

In addition, the Main class should implement a few interfaces.

Let’s break down the implemented interfaces and the classes used in the example above.


Some interfaces of interest from the Wox.Plugin assembly:

  • IPlugin
  • IPluginI18n
  • IDelayedExecutionPlugin
  • IContextMenu
  • ISettingProvider


The most important interface is IPlugin:

public interface IPlugin
    List<Result> Query(Query query);

    void Init(PluginInitContext context);

    string Name { get; }

    string Description { get; }
  • Query is the method that does the actual logic in the plugin
  • Init is used to initialize the plugin
    • Save a reference to the PluginInitContext for later use
  • Name ought to match the value in the plugin.json file, but can be localized


If you want to support internationalization you can implement the IPluginI18n interface:

public interface IPluginI18n
    string GetTranslatedPluginTitle();

    string GetTranslatedPluginDescription();


The IDelayedExecutionPlugin interface provides an alternative Query method:

public interface IDelayedExecutionPlugin
    List<Result> Query(Query query, bool delayedExecution);

The delayed execution can be used for queries that take some time to run. PowerToys Run will add a slight delay before the Query method is invoked, so that the user has some extra milliseconds to finish typing that command.

A delay can be useful for queries that performs:

  • I/O operations
  • HTTP requests


The IContextMenu interface is used to add context menu buttons to the query results:

public interface IContextMenu
    List<ContextMenuResult> LoadContextMenus(Result selectedResult);
  • Every Result can be enhanced with custom buttons


If the plugin is sophisticated enough to have custom settings, implement the ISettingProvider interface:

public interface ISettingProvider
    Control CreateSettingPanel();

    void UpdateSettings(PowerLauncherPluginSettings settings);

    IEnumerable<PluginAdditionalOption> AdditionalOptions { get; }
  • CreateSettingPanel usually throw a NotImplementedException
  • UpdateSettings is invoked when the user updates the settings in the PowerToys GUI
    • Use this method to save the custom settings and update the state of the plugin
  • AdditionalOptions is invoked when the PowerToys GUI displays the settings
    • Use this property to define how the custom settings are renderer in the PowerToys GUI


Some classes of interest from the Wox.Plugin assembly:

  • PluginInitContext
  • Query
  • Result
  • ContextMenuResult


A PluginInitContext instance is passed as argument to the Init method:

public class PluginInitContext
    public PluginMetadata CurrentPluginMetadata { get; internal set; }

    public IPublicAPI API { get; set; }
  • PluginMetadata can be useful if you need the path to the PluginDirectory or the ActionKeyword of the plugin
  • IPublicAPI is mainly used to GetCurrentTheme, but can also ShowMsg, ShowNotification or ChangeQuery


A Query instance is passed to the Query methods defined in the IPlugin and IDelayedExecutionPlugin interfaces.

Properties of interest:

  • Search returns what the user has searched for, excluding the action keyword.
  • Terms returns the search as a collection of substrings, split by space (" ")


A list of Result objects are returned by the Query methods defined in the IPlugin and IDelayedExecutionPlugin interfaces.

Example of how to create a new result:

new Result
    QueryTextDisplay = query.Search, // displayed where the user types queries
    IcoPath = IconPath, // displayed on the left side
    Title = "A title displayed in the top of the result",
    SubTitle = "A subtitle displayed under the main title",
    ToolTipData = new ToolTipData("A tooltip title", "A tooltip text\nthat can have\nmultiple lines"),
    Action = _ =>
        Log.Debug("The actual action of the result when pressing Enter.", GetType());
        For example:
        - Copy something to the clipboard
        - Open a URL in a browser
    Score = 1, // the higher, the better query match
    ContextData = someObject, // used together with the IContextMenu interface


A list of ContextMenuResult objects are returned by the LoadContextMenus method defined in the IContextMenu interface. These objects are rendered as small buttons, displayed on the right side of the query result.

Example of how to create a new context menu result:

new ContextMenuResult
    PluginName = Name,
    Title = "A title displayed as a tooltip",
    FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets",
    Glyph = "\xE8C8", // Copy
    AcceleratorKey = Key.C,
    AcceleratorModifiers = ModifierKeys.Control,
    Action = _ =>
        Log.Debug("The actual action of the context menu result, when clicking the button or pressing the keyboard shortcut.", GetType());
        For example:
        - Copy something to the clipboard
        - Open a URL in a browser

Find the perfect Glyph to use from:


Examples of actions to use with Result or ContextMenuResult:

Action = _ =>
    System.Windows.Clipboard.SetText("Some text to copy to the clipboard");
    return true;
Action = _ =>
    var url = "https://conductofcode.io/";

    if (!Helper.OpenCommandInShell(DefaultBrowserInfo.Path, DefaultBrowserInfo.ArgumentsPattern, url))
        Log.Error("Open default browser failed.", GetType());
        Context?.API.ShowMsg($"Plugin: {Name}", "Open default browser failed.");
        return false;

    return true;


Logging is done with the static Log class, from the Wox.Plugin.Logger namespace. Under the hood, NLog is used.

Five log levels:

Log.Debug("A debug message", GetType());
Log.Info("An information message", GetType());
Log.Warn("A warning message", GetType());
Log.Error("An error message", GetType());
Log.Exception("An exceptional message", new Exception(), GetType());

The logs are written to .txt files, rolled by date, at:

  • %LocalAppData%\Microsoft\PowerToys\PowerToys Run\Logs\<Version>\


If you have the need to add third party dependencies, take a look at what is already used by PowerToys.

NuGet packages and the versions specified in the .props file are candidates to reference in your own .csproj file.

Packages of interest:

  • LazyCache
  • Newtonsoft.Json

If the plugin uses any third party dependencies that are not referenced by PowerToys Run, you need to enable DynamicLoading.

In the plugin.json file:

    // ...
    "DynamicLoading": true
  • true makes PowerToys Run dynamically load any .dll files in the plugin folder


You can write unit tests for your plugin. The official plugins use the MSTest framework and Moq for mocking.

  • Project name: Community.PowerToys.Run.Plugin.<PluginName>.UnitTests
  • Target framework: net8.0-windows

The .csproj file of a unit test project may look something like this:

  • Apart from the actual test assemblies, some package references are also needed
  • As well as references to PowerToys and Wox .dll assemblies

Unit tests of the Main class may look something like this:

Some of the official plugins have unit test coverage:


Unfortunately, the plugin manager in PowerToys Run does not offer support for downloading new plugins.

Community plugins are traditionally packaged in .zip files and distributed via releases in GitHub repositories.

The process is described in a unofficial checklist:

The Everything plugin by Lin Yu-Chieh (Victor) is next level and is distributed via:

  • Self-Extraction Installer (EXE)
  • Manual Installation (ZIP)
  • WinGet
  • Chocolatey


Demo Plugin:

Awesome PowerToys Run Plugins:

Third-Party plugins for PowerToy Run:

Unofficial Visual Studio project template for PowerToys Run plugins:


Dev Documentation:

If you want to look under the hood, fork or clone the PowerToys repo:

Get the solution to build on your machine with the help of the documentation: