0002 Rust end to end
Status: accepted
Context
claudius has to do several different jobs well:
- render a four-minute song of a dozen tracks, with convolution reverb and a mastering search, in seconds, many times over during evolution;
- parse audio files, scripts and blueprints that come from other people and from assistants;
- serve a studio natively and in a browser, an HTTP API and MCP, from one session;
- listen: run CLAP and the AudioSet tagger, which earshot, the library that calibrates them, does in Python with PyTorch.
It also has to install as a program a musician downloads and runs, not as a development environment.
Decision
claudius is written in Rust throughout, as one Cargo workspace:
- the engine (DSP, theory, rendering, the critic) uses rayon for parallel rendering and evolution;
- the server uses tokio and axum, and the MCP tools rmcp;
- the studio is egui, compiled natively and to WebAssembly (0008);
- the scripting language is Rhai, which is itself written in Rust (0004);
- audio decoding is symphonia, with ffmpeg only as an optional fallback;
- earshot is ported to Rust (
crates/earshot): its DSP reimplemented, the two models run as ONNX exports on ONNX Runtime through theortcrate, linked statically. Nothing needs Python at runtime.
Rejected: keeping earshot in Python and calling it as a subprocess, which would make every user install a Python environment with PyTorch, add seconds of startup to every verdict, and split the program in two. A C++ engine (a JUCE or similar stack) would be as fast but give up memory safety where claudius parses untrusted input, and make the build harder to keep portable. A JavaScript engine sharing code with Strudel would have made the web studio simpler and offline rendering of long, dense songs much slower.
Consequences
- One language, one toolchain (
rust-toolchain.toml), one dependency audit (cargo deny), and binaries that run without an interpreter. Theclaudiusprogram carries the whole engine, the server and the studio. - The wire types (
claudius-api) are shared by the server and the WebAssembly studio, so they cannot drift. - Parsing audio, scripts and JSON happens in memory-safe code; the remaining C is ONNX Runtime (running pinned, hash-checked models) and ffmpeg when it is installed.
- The port of earshot is a maintenance cost: it has to match the Python original, which
crates/earshot/tests/parity.rschecks against fixtures the Python version wrote. Regenerating those fixtures is the one task that still needs a Python environment, and only for developers. - ONNX Runtime arrives as a prebuilt static library downloaded at build time by
ort. There is no build for Intel Macs, so that release target is marked experimental and fails for now. - Compile times are long (the dev profile optimises everything, because tests render audio), and contributors need to know Rust, which is a higher bar than Python for people who come from music.