Techniques

Rust Extensions

Build high-performance WASI component extensions in Rust with full type safety.

Rust is the recommended language for OXP extensions that need logic beyond declarative UI. The toolchain is mature, the output is tiny, and you get the full safety guarantees of the WASI Component Model sandbox.

Prerequisites

bash
rustup target add wasm32-wasip2

Scaffold a Rust Extension

bash
oxp create -t hello-rust my-rust-ext
cd my-rust-ext

This creates:

my-rust-ext/
├── Cargo.toml
├── build.rs
├── src/
│   └── lib.rs
├── wit/
│   ├── oxp-host.wit
│   └── oxp-extension.wit
└── oxp.json

Cargo Configuration

toml
[package]
name = "my-rust-ext"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wit-bindgen = "0.36"

[profile.release]
opt-level = "s"
lto = true
strip = true
codegen-units = 1

Key points:

  • **crate-type = ["cdylib"]** — produces a dynamic library, which is what wasm32-wasip2 needs
  • **wit-bindgen** — generates Rust bindings from the WIT contracts
  • Release profile — optimized for small binary size

Implementing the Extension

rust
wit_bindgen::generate!({
    world: "extension",
    path: "wit",
    generate_all,
});

use exports::oxp::extension::lifecycle::{ActivateCtx, Guest as LifecycleGuest};
use exports::oxp::extension::ui_handler::{EventError, Guest as UiHandlerGuest};
use exports::oxp::extension::command_handler::Guest as CommandHandlerGuest;
use oxp::host::log::{log, Level};

struct Component;

impl LifecycleGuest for Component {
    fn activate(ctx: ActivateCtx) -> Result<(), String> {
        log(Level::Info, &format!(
            "hello from {} v{} on {}",
            ctx.extension_id, ctx.version, ctx.host
        ));
        Ok(())
    }

    fn deactivate() -> Result<(), String> {
        log(Level::Info, "goodbye");
        Ok(())
    }
}

impl UiHandlerGuest for Component {
    fn on_event(_event: Vec<u8>) -> Result<(), EventError> {
        Ok(())
    }
}

impl CommandHandlerGuest for Component {
    fn on_command(id: String, _args_json: String) -> Result<String, String> {
        Ok(format!("\"unhandled:{}\"", id))
    }
}

export!(Component);

Your extension must implement three traits:

  • **LifecycleGuest** — activate() and deactivate()
  • **UiHandlerGuest** — on_event() for UI interactions
  • **CommandHandlerGuest** — on_command() for command palette actions

Available Host Imports

Inside your Rust extension, you can call host capabilities:

rust
use oxp::host::log::{log, Level};
use oxp::host::storage::{get, set, delete};
use oxp::host::ui::{render, notify, set_status};
use oxp::host::fs::{read_file, write_file};  // requires fs.read/fs.write permission
use oxp::host::net::fetch;                    // requires net.fetch permission

Build and Pack

bash
cargo build --release --target wasm32-wasip2
mkdir -p build
cp target/wasm32-wasip2/release/my_rust_ext.wasm build/
oxp pack

Manifest for Rust Extensions

json
{
  "specVersion": "1",
  "kind": "component-v1",
  "id": "@yourname/my-rust-ext",
  "publisher": "yourname",
  "version": "0.1.0",
  "displayName": "My Rust Extension",
  "license": "MIT",
  "engines": { "oxp": "^1.0.0" },
  "main": { "wasm": "build/my_rust_ext.wasm" },
  "wit": {
    "package": "oxp:extension",
    "version": "0.1.0",
    "sha256": "<computed-by-oxp-create>"
  },
  "permissions": []
}

The wit.sha256 is automatically set by oxp create — it's the SHA-256 of the canonical WIT world this CLI was built against.