Build audio plugins in Rust.
CLAP, VST3, LV2, AU v2, AU v3, AAX, and standalone — from a single Rust crate. Install and load your plugin in a DAW in five minutes.
# Install the CLI (one-time)
cargo install cargo-truce
# Scaffold a new plugin
cargo truce new my-plugin
cd my-plugin
# Run the plugin standalone — no DAW needed
cargo truce run
# Build and install
cargo truce install --clap
cargo truce install --vst3
# Open your DAW, scan for plugins, load "MyPlugin"Overview
Capabilities
One Rust codebase compiles to seven plugin formats. Hot reload, declarative params, cross-platform installers, automated validation.
7 plugin formats
CLAP and VST3 by default; VST2, LV2, AU v2, AU v3, and AAX are opt-in per crate. One Rust codebase, every host.
Hot reload
Edit DSP or layout, rebuild, hear changes without restarting your DAW.
Declarative params
#[derive(Params)] with ranges, units, and smoothing. Atomic storage, lock-free access from any thread.
Pick your GUI
Built-in widgets, egui, iced, Slint, or raw window handle. The same plugin, your choice of toolkit.
Cross-platform
macOS, Windows, and Linux. The CLI handles signing, notarization, installers, and validation.
Validation built in
cargo truce validate runs auval, pluginval, and clap-validator in one command on installed plugins.
Compatibility
Format support
CLAP and VST3 ship as defaults. VST2, LV2, AU, and AAX are opt-in per plugin via Cargo features.
| Format | macOS | Windows | Linux |
|---|---|---|---|
| CLAP | Yes | Yes | Yes |
| VST3 | Yes | Yes | Yes |
| VST2 | Yes | Yes | Yes |
| LV2 | Yes | Yes | Yes |
| AU v2 | Yes | — | — |
| AU v3 | Yes | — | — |
| AAX | Yes | Yes | — |
Example
A complete plugin
Smoothed parameter, GPU-rendered knob, CLAP + VST3 + standalone. The truce::plugin! macro generates every format export, GUI, and state serialization.
use truce::prelude::*;
use truce_gui_types::layout::{knob, widgets, GridLayout};
#[derive(Params)]
pub struct GainParams {
#[param(name = "Gain", range = "linear(-60, 6)",
unit = "dB", smooth = "exp(5)")]
pub gain: FloatParam,
}
use GainParamsParamId as P;
pub struct Gain { params: Arc<GainParams> }
impl Gain {
pub fn new(params: Arc<GainParams>) -> Self { Self { params } }
}
impl PluginLogic for Gain {
fn reset(&mut self, sr: f64, _bs: usize) {
self.params.set_sample_rate(sr);
}
fn process(&mut self, buffer: &mut AudioBuffer, _events: &EventList,
_ctx: &mut ProcessContext) -> ProcessStatus {
for i in 0..buffer.num_samples() {
let gain = db_to_linear(self.params.gain.read());
for ch in 0..buffer.channels() {
let (inp, out) = buffer.io(ch);
out[i] = inp[i] * gain;
}
}
ProcessStatus::Normal
}
fn layout(&self) -> GridLayout {
GridLayout::build(vec![widgets(vec![knob(P::Gain, "Gain")])])
}
}
truce::plugin! { logic: Gain, params: GainParams }Plugins
Built with truce
Open-source plugins built on the framework.
