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, Vizia, 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, built-in knob, CLAP + VST3 + standalone. The truce::plugin! macro generates every format export, GUI, and state serialization.
use truce::prelude::*;
use truce_gui::IntoLayoutEditor;
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 editor(&self) -> Box<dyn Editor> {
GridLayout::build(vec![widgets(vec![knob(P::Gain, "Gain")])])
.into_editor(&self.params)
}
}
truce::plugin! { logic: Gain, params: GainParams }Plugins
Built with truce
Open-source plugins built on the framework.

Truce Analyzer
Compare signals across your chain without extra tracks or sends. Insert one before processing, one after, and see exactly what your plugins do.

Truce EQ
3-band parametric EQ — low / mid / high, each with frequency, gain, and Q. Built-in GUI with section-based layout, f64 DSP path for precision-sensitive filter coefficients.

Truce Fundsp Reverb (worker)
Stereo plate reverb wired through a fundsp audio graph. The worker variant rebuilds the graph on a dedicated background thread and swaps it in via lock-free queues so `process()` stays allocation-free.

Truce Fundsp Reverb (simple)
Stereo plate reverb wired through a fundsp audio graph. The simple variant rebuilds the graph inline on the audio thread — easier to read end-to-end, but rt-unsafe.