Quickstart
The following is a minimal guide to running writing an Extism plug-in in your language
of choice. This document should get you from 0
to "Hello, World!"
as quickly as possible.
Choose A Language​
In Extism, your plug-in code is compiled to a binary Wasm module. We offer a variety of libraries, which we call PDKs (Plug-in Development Kits), to help you compile your code to a Wasm module that can be embedded in any Host SDK.
First choose a language for your plug-in:
- Rust
- JavaScript/TypeScript
- Go
- C#
- F#
- C
- Haskell
- Zig
- AssemblyScript
Install the Dependency​
Generate a new plugin using Extism CLI:
extism gen plugin -l Rust -o plugin
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world.
Let's create a simple greeting plug-in. The plugin_fn
macro wires this function to Extism and exports it
using the name greet
:
use extism_pdk::*;
#[plugin_fn]
pub fn greet(name: String) -> FnResult<String> {
Ok(format!("Hello, {}!", name))
}
Compile the Plug-in​
We can compile to the wasm32-unknown-unknown
since we don't need to make any syscalls (not using WASI):
cargo build --target wasm32-unknown-unknown
If this fails, make sure you have added this target to rust:
rustup target add wasm32-unknown-unknown
Running the Plug-In​
This will put your compiled wasm in target/wasm32-unknown-unknown/debug
.
We can now test it using the Extism CLI's run
command:
extism call target/wasm32-unknown-unknown/debug/rust_pdk_template.wasm greet --input "Benjamin"
# => Hello, Benjamin!
You will get better performance and smaller .wasm
binaries if you build your code using --release
.
cargo build --target wasm32-unknown-unknown --release
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this rust library can do, see the rust-pdk README and reference docs.
Install the Dependency​
First install the Extism JS compiler with this install script:
curl -O https://raw.githubusercontent.com/extism/js-pdk/main/install.sh
sh install.sh
Then run command with no args to see the help:
extism-js
error: The following required arguments were not provided:
<input-js>
USAGE:
extism-js <input-js> -i <interface-file> -o <output>
For more information try --help
If you are using mac, you may need to tell your security system this unsigned binary is fine.
Then, generate a JavaScript plugin using Extism CLI:
extism gen plugin -l JavaScript -o plugin
cd plugin
npm install
Or, for a TypeScript plugin:
extism gen plugin -l TypeScript -o plugin
cd plugin
npm install
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world. Let's create a simple greeting plug-in. Just like a normal JS module, any function we export will be accessible to the outside world:
function greet() {
const name = Host.inputString()
Host.outputString(`Hello, ${name}`)
}
module.exports = {greet}
We must also describe the Wasm interface for our plug-in. We do this with a typescript module DTS file. Here is our plugin.d.ts file:
declare module 'main' {
// Extism exports take no params and return an I32
export function greet(): I32;
}
Compile the Plug-in​
Now we must compile this plug-in to wasm:
npm run build
Running the Plug-In​
We can now test it using the Extism CLI's run
command:
extism call ./dist/plugin.wasm greet --input "Benjamin" --wasi
# => Hello, Benjamin
At this time, all js plug-ins need WASI to run
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this js library can do, see the js-pdk README.
Install the Dependency​
Generate a Go plugin using Extism CLI:
extism gen plugin -l Go -o plugin
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world. Let's create a simple greeting plug-in.
package main
import (
"github.com/extism/go-pdk"
)
//export greet
func greet() int32 {
input := pdk.Input()
greeting := `Hello, ` + string(input) + `!`
pdk.OutputString(greeting)
return 0
}
func main() {}
The magic comment //export
is what exports the function to the outside world:
Compile the Plug-in​
Now we must compile this plug-in to wasm. Currently the best way to do this is with tinygo:
make
Running the Plug-In​
We can now test it using the Extism CLI's run
command:
extism call plugin.wasm greet --input "Benjamin" --wasi
# => Hello, Benjamin
At this time, all Go plug-ins need WASI to run
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this go library can do, see the go-pdk README.
Prerequisites​
- .NET SDK 8
- WASI Workload:
dotnet workload install wasi-experimental
Install the Dependency​
Generate a C# plugin using Extism CLI:
extism gen plugin -l C# -o plugin
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world. Let's create a simple greeting plug-in.
using System;
using System.Runtime.InteropServices;
using System.Text.Json;
using Extism;
namespace Plugin;
public class Program
{
[UnmanagedCallersOnly(EntryPoint = "greet")]
public static int Greet()
{
var name = Pdk.GetInputString();
var greeting = $"Hello, {name}!";
Pdk.SetOutput(greeting);
return 0;
}
// Note: a `Main` method is required for the app to compile
public static void Main() {}
}
Compile the Plug-in​
Compile as normal with dotnet:
dotnet build
Running the Plug-In​
This will create a Plugin.wasm
file in bin/Debug/net8.0/wasi-wasm/AppBundle
. Now, you can try out your plugin by using any of the Extism SDKs or by using Extism CLI's run
command:
extism call .\bin\Debug\net8.0\wasi-wasm\AppBundle\Plugin.wasm greet --input "Benjamin" --wasi
# => Hello, Benjamin!
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this dotnet library can do, see the dotnet-pdk README and reference docs.
Prerequisites​
- .NET SDK 8
- WASI Workload:
dotnet workload install wasi-experimental
Install the Dependency​
Generate a new plugin using the Extism CLI:
extism gen plugin -l F# -o plugin
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world. Let's create a simple greeting plug-in.
module Plugin
open System
open System.Runtime.InteropServices
open Extism
[<UnmanagedCallersOnly(EntryPoint = "greet")>]
let Greet () : int32 =
let name = Pdk.GetInputString()
let greeting = $"Hello, {name}!"
Pdk.SetOutput(greeting)
0
[<EntryPoint>]
let Main args =
// Note: an `EntryPoint` function is required for the app to compile
0
Compile the Plug-in​
Compile as normal with dotnet:
dotnet build
Running the Plug-In​
This will create a Plugin.wasm
file in bin/Debug/net8.0/wasi-wasm/AppBundle
. Now, you can try out your plugin by using any of the Extism SDKs or by using Extism CLI's run
command:
extism call .\bin\Debug\net8.0\wasi-wasm\AppBundle\Plugin.wasm greet --input "Benjamin" --wasi
# => Hello, Benjamin!
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this dotnet library can do, see the dotnet-pdk README and reference docs.
Install the Dependency​
The quickest way to getting started is generate a C plugin via the Extism CLI:
extism gen plugin -l C -o plugin
cd ./plugin
git submodule update --init --recursive
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world. Let's create a simple greeting plug-in.
#define EXTISM_ENABLE_LOW_LEVEL_API
#define EXTISM_IMPLEMENTATION
#include "../extism/extism-pdk.h"
const char *greeting = "Hello, ";
uint64_t greetingLen = 7;
int32_t greet() {
uint64_t inputLen = extism_input_length();
// Load input
uint8_t inputData[inputLen];
extism_load_input(0, inputData, inputLen);
// Allocate a new offset used to store greeting and name
uint64_t outputLen = greetingLen + inputLen;
ExtismPointer offs = extism_alloc(outputLen);
extism_store(offs, (const uint8_t *)greeting, greetingLen);
extism_store(offs + greetingLen, inputData, inputLen);
// Set output
extism_output_set(offs, outputLen);
return 0;
}
Compile the Plug-in​
Compile with clang and target wasm32-unknown-unknown
:
clang -o plugin.wasm --target=wasm32-unknown-unknown -nostdlib -Wl,--no-entry -mexec-model=reactor -Wl,--export=greet ./src/plugin.c
Note that we must explicitly export the greet
function at compile time.
You can also use the Makefile in the generated plugin. But you'll have to edit it so that the greet
functions is exported.
Running the Plug-In​
This will create a plugin.wasm
file. Now, you can try out your plugin by using any of the Extism SDKs or by using Extism CLI's run
command:
extism call plugin.wasm greet --input "Benjamin"
# => Hello, Benjamin
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this C library can do, see the c-pdk README.
Install the Dependency​
This library can be used to write Extism Plug-ins in Haskell.
Docs are available on Hackage: https://hackage.haskell.org/package/extism-pdk
Install​
Make sure you have wasm32-wasi-ghc installed, then generate a Haskell plugin using the Extism CLI:
extism gen plugin -l Haskell -o plugin
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world. Let's create a simple greeting plug-in.
module Greet where
import Data.Int
import Data.Maybe
import Extism.PDK
mkGreeting :: String -> String -> IO ()
mkGreeting g n =
output $ g ++ ", " ++ n
greet :: IO Int32
greet = do
-- Get a name from the Extism runtime
name <- inputString
-- Get configured greeting
greeting <- getConfig "greeting"
-- Greet the user, if no greeting is configured then "Hello" is used
mkGreeting (fromMaybe "Hello" greeting) name
-- Return 0 to signal success
pure 0
foreign export ccall "greet" greet :: IO Int32
module Plugin (mkGreeting) where
import Extism.PDK
mkGreeting :: String -> String -> IO ()
mkGreeting g n =
output $ g ++ ", " ++ n
Compile the Plug-in​
Compile with wasm32-wasi-cabal
:
make
Note that we must explicitly export the greet
function at compile time.
Running the Plug-In​
This will create a plugin.wasm
file. Now, you can try out your plugin by using any of the Extism SDKs or by using Extism CLI's run
command:
extism call plugin.wasm greet --input "Benjamin" --wasi
# => Hello, Benjamin!
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this Haskell library can do, see the haskell-pdk README.
Install the Dependency​
Create a new Zig project:
extism gen plugin -l Zig -o plugin
Create an Export​
The goal of writing an Extism plug-in is to compile your Zig code to a Wasm module with exported functions that the host application can invoke. The first thing you should understand is creating an export. Let's write a simple program that exports a greet
function which will take a name as a string and return a greeting string. Zig has excellent support for this through the export
keyword:
const std = @import("std");
const extism_pdk = @import("extism-pdk");
const Plugin = extism_pdk.Plugin;
const allocator = std.heap.wasm_allocator;
export fn greet() i32 {
const plugin = Plugin.init(allocator);
const name = plugin.getInput() catch unreachable;
defer allocator.free(name);
const output = std.fmt.allocPrint(allocator, "Hello, {s}!", .{name}) catch unreachable;
plugin.output(output);
return 0;
}
Compile the Plug-in​
Note: if you started with the generated project files from
zig init
, you should deletesrc/root.zig
and any references to it if they are in yourbuild.zig
file.
Then run:
zig build
This will put your compiled wasm in zig-out/bin
.
Running the Plug-in​
We can now test it using the Extism CLI's run
command:
extism call ./zig-out/bin/zig-pdk-template.wasm greet --input "Benjamin"
# => Hello, Benjamin!
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this Zig library can do, see the zig-pdk README.
Install the Dependency​
Generate a new plugin using Extism CLI:
extism gen plugin -l AssemblyScript -o plugin
cd plugin
npm install
Create an Export​
The primary means of interacting with this plug-in is an export function that can be called by the outside world. Let's create a simple greeting plug-in.
import { Config, Host, Var } from "@extism/as-pdk";
function myAbort(
message: string | null,
fileName: string | null,
lineNumber: u32,
columnNumber: u32,
): void {}
export function greet(): i32 {
const name = Host.inputString();
Host.outputString("Hello, " + name);
return 0;
}
Compile the Plug-in​
Then run:
npm run build
Running the Plug-in​
We can now test it using the Extism CLI's run
command:
extism call ./index.wasm greet --input "Benjamin"
# => Hello, Benjamin
Documentation​
Congrats! You just wrote your first Extism plug-in! To learn more about what this AssemblyScript library can do, see the assemblyscript-pdk README.
Need help?​
If you've encountered a bug or think something is missing, please open an issue on the Extism GitHub repository.
There is an active community on Discord where the project maintainers and users can help you. Come hang out!