A Rust plugin framework for trait-to-dylib plugin systems
fidius lets you define a Rust trait, annotate it with a macro, and get a compiled dynamic library with a stable C ABI. Host applications load, validate, and call plugins through a type-safe proxy — no handwritten FFI.
- Trait-driven — define a plugin interface as a Rust trait; the macro generates the ABI shim.
- Stable C ABI — plugins compile to
.dylib/.so/.dllwith versioned, hash-checked entry points. - Type-safe host loading —
fidius-hostloads plugins behind a typed proxy that mirrors your trait. - Optional methods & interface evolution — add methods without breaking existing plugins.
- Signing & verification — Ed25519 signatures over plugin artifacts.
- Python plugins — write plugins in Python that satisfy a Rust trait via
fidius-python. - Sandboxed WASM plugins — compile a plugin to a WebAssembly component that runs in a deny-all wasmtime sandbox with a capability allow-list; polyglot (Rust and other languages implement the same interface). Outbound HTTP is host-brokered and policy-gated (
wasi:http+ a required egress hook). - Streaming, all three directions —
fidius::Stream<T>works in return position (server-streaming — the plugin produces), argument position (client-streaming — the host produces), or both (bidirectional — a plugin-owned transform). Pull-based, backpressured, drop-to-cancel, with bounded memory for unbounded inputs — on all three backends (Rust/Python/WASM), and server-streaming proven across Rust, JS, Python, and C guests. - Configured instances — bind config once and call many (
#[plugin_impl(Trait, config = C)]+configure): config crosses the boundary once, config-bound setup runs once, and N differently-configured instances coexist — on all three backends (cdylib/WASM/Python). - CLI tooling — scaffold interfaces and plugins, sign, inspect, and package.
| Crate | Purpose |
|---|---|
fidius |
Top-level facade re-exporting the public API |
fidius-core |
Descriptors, wire format, hashing, registry, metadata |
fidius-macro |
Proc macros (#[fidius::interface], #[fidius::plugin]) and IR |
fidius-host |
Loading, calling, signing, arch detection, arena pool |
fidius-cli |
fidius command-line tool |
fidius-test |
Test helpers (dylib fixtures, signing fixtures) |
fidius-python |
Python plugin support |
fidius-guest |
wasm-buildable guest types for plugins compiled to WASM components |
cargo install fidius-cliA fidius plugin system is three crates: an interface (the trait), a plugin (a cdylib that implements it), and a host (loads and calls it). The CLI scaffolds the first two:
fidius init-interface my-api --trait ImageFilter
fidius init-plugin my-plugin --interface my-api --trait ImageFilterYou then fill in two small pieces of code. In the interface crate, annotate the trait — the macro generates the vtable, ABI hash, and the host-side typed proxy:
use serde::{Deserialize, Serialize};
#[fidius::plugin_interface(version = 1, buffer = PluginAllocated)]
pub trait ImageFilter: Send + Sync {
fn apply(&self, input: ApplyInput) -> ApplyOutput;
}
#[derive(Serialize, Deserialize)]
pub struct ApplyInput { pub pixels: Vec<u8> }
#[derive(Serialize, Deserialize)]
pub struct ApplyOutput { pub pixels: Vec<u8> }In the plugin crate, annotate your impl and emit the registry — that's all the FFI you write:
use my_api::{plugin_impl, ImageFilter, ApplyInput, ApplyOutput};
pub struct Invert;
#[plugin_impl(ImageFilter)]
impl ImageFilter for Invert {
fn apply(&self, input: ApplyInput) -> ApplyOutput {
ApplyOutput { pixels: input.pixels.into_iter().map(|p| 255 - p).collect() }
}
}
fidius::fidius_plugin_registry!();Then build, optionally sign, and inspect:
cd my-plugin && cargo build
fidius keygen --out mykey
fidius sign --key mykey.secret target/debug/libmy_plugin.dylib
fidius inspect target/debug/libmy_plugin.dylibThe host loads the resulting dylib through fidius-host and calls apply() through a generated ImageFilterClient proxy. See Your First Plugin for the full walkthrough including the host crate.
This project uses angreal as its task runner. Common tasks:
angreal tree # list all tasks
angreal build # build the workspace
angreal test # run the test suite
angreal python-test # run the Python SDK tests
angreal check # cargo check + clippy
angreal lint # formatting and lint checks
angreal license-header # add/check license headersFull documentation lives in docs/ and covers tutorials, how-to guides, reference, and architecture explanation. Build it locally with mkdocs serve.
- Your First Plugin
- Your First Python Plugin
- Your First WASM Plugin
- Capabilities & the WASM Sandbox
- Architecture Overview
- ABI Specification
- CLI Reference
Apache-2.0. See LICENSE.
