Plug-ins in Nebula: CLAP hosting, the bridge, and why VST3 is not supported

2026-11-03

Third-party plug-ins arrived in 0.3.0-alpha.278 — and with them a decision that surprises people: VST3 is not supported, and cannot be.

Settings, Plugin bridge: the bridge command and the 32-bit preference

Why not VST3

It is a licensing question, not a technical one. The VST3 SDK is dual-licensed GPLv3-or-Steinberg-proprietary, and a GPL dependency cannot go into a binary shipped under the Functional Source License. The project's own dependency ledger had a row claiming "VST3 SDK 3.8.0 — MIT"; that row was simply wrong, and it has been corrected and superseded in the decision records. Nothing in the repository links or ships the VST3 SDK.

Why CLAP

CLAP was the licence-clean answer: its headers are MIT, it is a C ABI with no runtime to link, its search paths and host/plug-in contracts are public, and it ships an open validator. The headers are the entire dependency — a host speaks an interface, it does not compile a library.

The headers are vendored like every other dependency: pinned by version, URL and SHA-256, and fetched without pulling in the validator and example plug-ins the project does not use.

How a plug-in appears in the app

The rule the engine lives by is that the audio thread may not allocate, lock, block, log or do I/O — and a plug-in is foreign code you cannot police. So a hosted plug-in is presented as an ordinary device:

  • its parameters become ordinary knobs, so they draw, save, automate and MIDI-learn with no special case;
  • its own saved state is carried opaquely, so a project re-opens the sound it was saved with;
  • its reported latency feeds delay compensation;
  • every buffer it is handed is sized before the audio thread ever runs it;
  • the calls into it are wrapped so a crash in a plug-in's setup is contained instead of taking the app down (proven with two deliberate access violations).

Discovery scans CLAP's documented locations plus a clap folder in the app's data directory, and everything unusable is reported with a plain reason rather than silently skipped.

The bridge: plug-ins the app must not load

Two kinds of plug-in can never be loaded into Nebula's own process. A 32-bit one cannot be mapped into a 64-bit program at all — there is no flag that makes that work. And a plug-in under a licence the app cannot take on can only be hosted across a process boundary.

There is a third reason to want it: a plug-in crash should not be the app's crash, and a separate process is the only structure in which a memory fault is survivable.

The hard part is not starting a process — it is that the audio thread may not wait for it. So it does not. The pipeline is filled ahead and read behind: the audio thread hands over block N and plays block N-1's answer. A slow or dead bridge therefore costs one block of silence, never a glitch. The app starts the bridge (a setting chooses which program, because a 32-bit bridge and a 64-bit bridge are two different files), they agree a protocol version — a mismatch is refused with a sentence rather than guessed at — and a legitimate in-process loopback mode keeps the lowest-latency option available.

A real 32-bit bridge program was built and driven by the 64-bit app with exact audio, so this half is proven rather than assumed.

What is deliberately missing

  • A plug-in's own editor window is never shown. The plug-in's GUI is not offered at all; the only controls are the mapped knobs in Nebula's interface.
  • There is no plug-in manager screen yet. Discovery and hosting are built and tested, but nothing in the app can currently list a scanned plug-in or add one to a track.
  • The app's audio path and its interface do not call the bridge yet. The protocol, the host side, the bridge process and the 32-bit case are all built and tested; wiring them to a track is the remaining step.
  • Fault containment is Windows-only — it uses structured exception handling.
  • The POSIX bridge transport is written but has not been run.
  • VST2, LV2 and AU are not implemented. Hosted plug-ins are refused by name on group, return and master buses, and only stereo, single-port plug-ins are accepted — this engine is stereo, and refusing by name beats pretending.

Devices and FX: Nebula's own effects, with a sidechain key wired up

Everything above applies to third-party plug-ins. Nebula's own 33 effects — delay, reverb, EQ, filters, dynamics, drive, modulation and pitch — still ship with the app, with factory presets and per-device preset save, and sidechain keys work on any keyable device.

An unhandled error has occurred. Reload 🗙

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.