Creating Plugins

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

Prerequisites

  • An Extism-compatible language SDK (Rust, Go, JavaScript, C, etc.)
  • Basic understanding of WebAssembly

Extism provides PDKs (Plugin Development Kits) for multiple 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, and 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 (containing manifest.json and plugin.wasm) in Windshift's plugin directory. Windshift scans for plugins at startup.

Plugins can be enabled/disabled from the admin panel without restarting the server.

Resource Limits

Plugins run with these default constraints:

Limit Value
Execution timeout 5 seconds
Memory 64 MB

Plugins that exceed these limits are terminated automatically.