Creating Plugins

This guide covers how to build, package, and install a Windshift plugin.

Prerequisites

  • An Extism-compatible language SDK, such as Rust, Go, JavaScript, or C.
  • A basic understanding of WebAssembly.

Extism provides Plugin Development Kits (PDKs) for several languages. See extism.org for the full list.

Project Structure

my-plugin/
├── manifest.json      # Plugin metadata and extensions
├── src/               # Plugin source code
├── plugin.wasm        # Compiled WASM binary
└── index.html         # Optional UI (for iframe extensions)

Manifest

Every plugin requires a manifest.json:

{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "What this plugin does",
  "entryPoint": "plugin.wasm",
  "extensions": []
}

Fields

Field Required Description
name Yes Unique plugin identifier
version Yes Semantic version
description Yes Human-readable description
entryPoint Yes Path to the WASM binary
extensions No List of UI extension registrations

Extensions

To add a UI tab in the admin panel:

{
  "extensions": [
    {
      "point": "admin.tab",
      "id": "my-plugin-tab",
      "label": "My Plugin",
      "displayMode": "iframe",
      "component": "index.html",
      "group": "Tools"
    }
  ]
}
Field Description
point Extension point (e.g., admin.tab)
id Unique extension identifier
label Display name in the UI
displayMode How to render: iframe for HTML content
component Path to the HTML file
group Group name in the admin sidebar

Writing Plugin Code

Plugins export functions that Windshift calls. They import host functions to interact with the platform.

Example (Go with Extism PDK)

package main

import (
    "github.com/extism/go-pdk"
)

//export run
func run() int32 {
    // Call a host function
    pdk.Log(pdk.LogInfo, "Plugin executing")

    // Read input
    input := pdk.Input()

    // Do work...

    // Write output
    pdk.OutputString("done")
    return 0
}

func main() {}

Example (JavaScript with Extism PDK)

function run() {
  Host.log("info", "Plugin executing");

  const input = Host.inputString();

  // Do work...

  Host.outputString("done");
  return 0;
}

module.exports = { run };

Building

Compile your plugin to a WASM binary using the Extism toolchain for your language:

# Go
tinygo build -o plugin.wasm -target wasi .

# Rust
cargo build --target wasm32-wasi --release
cp target/wasm32-wasi/release/my_plugin.wasm plugin.wasm

# JavaScript (using Extism JS PDK)
extism-js src/index.js -o plugin.wasm

Installing

Place the plugin directory, including manifest.json and plugin.wasm, in Windshift's plugin directory. Windshift scans for plugins when it starts.

You can enable or disable plugins in the admin panel without restarting the server.

Resource Limits

Plugins run with these default constraints:

Limit Value
Execution timeout 5 seconds
Memory 64 MB

Windshift terminates plugins that exceed these limits.