2026-08-21 13:08:18 +09:00
# NIH-plug Template
2026-08-21 03:55:36 +00:00
2026-08-21 13:08:18 +09:00
Minimal scaffold for new [NIH-plug ](https://github.com/robbert-vdh/nih-plug ) audio plugins (Rust + CLAP/VST3 + egui).
Based on patterns from [`musiikki/codename-206` ](http://192.168.2.199:3005/musiikki/codename-206 ).
## Quick Start
``` bash
# Clone this repo as your starting point
git clone http://192.168.2.199:3005/musiikki/nih-plug-template my-plugin
cd my-plugin
# Edit: src/lib.rs, Cargo.toml, bundler.toml — replace placeholder values
# See musiikki/codename-206 for a real-world example of how to fill these in
2026-08-29 10:24:52 +09:00
# Then verify the rename landed everywhere
sh check-branding.sh
2026-08-21 13:08:18 +09:00
```
2026-08-29 10:24:52 +09:00
## Renaming
Branding is duplicated across `Cargo.toml` , `bundler.toml` , `src/lib.rs` and the docs,
and nothing makes those agree — so a half-finished rename builds a bundle under one name
while the docs and deploy script look for another.
`check-branding.sh` declares the identity once at the top and asserts every copy matches:
``` bash
sh check-branding.sh # exit 0 = consistent, 1 = drift found
```
2026-08-29 10:29:06 +09:00
It covers the identity a host actually sees (package and bundle names, `Plugin::NAME` ,
`VENDOR` , `EMAIL` , `CLAP_ID` , `VST3_CLASS_ID` , the descriptions) and the Rust type names
(`MyPlugin` , `PluginParams` ) at every site they appear. Renaming the types is cosmetic —
no host ever sees them — but leaving `MyPlugin` in a shipped plugin is the kind of residue
that says nobody read the file. Leave them as-is and those checks simply stay green.
2026-08-29 10:24:52 +09:00
To rename: edit the canonical block at the top of the script, run it, and fix everything
it reports. The placeholder spellings are pre-seeded into its `STALE` list, and each one
arms itself as soon as you change the matching canonical value — so leftovers surface
without you having to track them. It also asserts `VST3_CLASS_ID` is exactly 16 bytes and
that `CLAP_ID` is reverse-DNS safe, both of which are otherwise a compile error or a
silent identity change between machines.
Checks for files the template doesn't ship (e.g. a `deploy.ps1` ) report as `skip` and
start enforcing once you add them.
2026-08-21 13:08:18 +09:00
## Build
``` bash
# Install Rust via rustup: https://rustup.rs
# No VST3 SDK needed — NIH-plug bundles its own bindings.
2026-08-29 10:24:33 +09:00
# Build + bundle the CLAP (default)
2026-08-21 13:08:18 +09:00
cargo xtask bundle nih_plug_template --release
2026-08-29 10:24:33 +09:00
# Add the VST3 as well — see the licensing note below before you do this
cargo xtask bundle nih_plug_template --release --features vst3
2026-08-21 13:08:18 +09:00
```
2026-08-29 10:24:33 +09:00
**Output: ** `target/bundled/<name>.clap` (and `<name>.vst3` with `--features vst3` ), where
`<name>` is the `name` set in `bundler.toml` — **not ** the crate name. Out of the box that
means `target/bundled/Plugin Name.clap` .
2026-08-29 10:23:59 +09:00
On Linux the egui editor needs the GUI development headers:
``` bash
sudo apt install pkg-config libgl-dev libx11-dev libxcursor-dev libxcb1-dev \
libxcb-icccm4-dev libxcb-dri2-0-dev libx11-xcb-dev libxkbcommon-dev libxkbcommon-x11-dev
```
2026-08-21 13:08:18 +09:00
## Deploy
### FL Studio
2026-08-29 10:24:33 +09:00
Build with `--features vst3` first if you want the VST3 (see the licensing note below).
2026-08-21 13:08:18 +09:00
FL Studio scans `C:\Program Files\Common Files\VST3` by default, **ignores directory junctions **
(so a symlinked bundle is invisible to its scanner), and caches failed scans.
1. Copy the `.vst3` bundle to a folder FL scans (e.g. `C:\Program Files\Common Files\VST3` ).
2. Copy the `.clap` bundle to a folder FL scans (e.g. `C:\Program Files\Common Files\CLAP` ).
3. In FL Studio: **Options → Manage plugins → tick "Rescan previously failed plugins" → Find installed plugins ** , then search for your plugin name (set in `bundler.toml` ).
### Linux
``` bash
# CLAP
2026-08-29 10:23:59 +09:00
cp -r "target/bundled/Plugin Name.clap" ~/.clap/
2026-08-21 13:08:18 +09:00
2026-08-29 10:24:33 +09:00
# VST3 (only exists if you built with --features vst3)
cp -r "target/bundled/Plugin Name.vst3" ~/.vst3/
2026-08-21 13:08:18 +09:00
# Or globally:
2026-08-29 10:23:59 +09:00
# sudo cp -r "target/bundled/Plugin Name.clap" /usr/lib/clap/
2026-08-29 10:24:33 +09:00
# sudo cp -r "target/bundled/Plugin Name.vst3" /usr/lib/vst3/
2026-08-21 13:08:18 +09:00
```
## Project Structure
```
2026-08-29 10:24:33 +09:00
Cargo.toml # Package deps + the opt-in `vst3` feature — NIH-plug pinned to codename-206's rev
2026-08-21 13:08:18 +09:00
bundler.toml # Bundle name for `cargo xtask bundle`
2026-08-29 10:24:33 +09:00
src/lib.rs # Plugin skeleton — params, DSP, and egui editor, with one example gain param
2026-08-21 13:08:18 +09:00
xtask/ # Bundler xtask (cargo xtask bundle)
.cargo/config.toml # xtask alias
2026-08-29 10:24:52 +09:00
check-branding.sh # Asserts the plugin's identity strings agree everywhere (see Renaming)
.gitattributes # Pins *.sh to LF so Windows checkouts keep a valid shebang
2026-08-21 13:08:18 +09:00
```
## License
Apache-2.0
## VST3 Licensing Note
2026-08-29 10:24:33 +09:00
NIH-plug's VST3 bindings (`vst3-sys` ) are GPLv3. Linking them makes the resulting binary
GPLv3 regardless of what `Cargo.toml` declares, so **VST3 is behind an opt-in `vst3` feature
and this template builds CLAP only by default.** That keeps the default build consistent with
the Apache-2.0 licence in `Cargo.toml` /`LICENSE` .
If you want to ship a VST3:
1. Build with `--features vst3` .
2. Relicense your plugin as GPLv3 (or obtain a commercial Steinberg licence) and update
`Cargo.toml` , `LICENSE` , and the SPDX headers in `src/` .
3. Accept Steinberg's VST3 SDK licence.
CLAP has no such restriction.