Claudius

v0.2.0 Open source, MIT licence. macOS and Linux, with Windows in preview.

A beatmaker that listens to its own songs.

claudius picks sounds, writes the parts with music theory, arranges them into a song, mixes and masters it, then listens to the result with a critic and revises it. Every sound is real audio, synthesized in code or recorded from sampled instruments. There is no neural audio generation and no General MIDI.

curl -fsSL https://github.com/devlato/claudius/releases/latest/download/install.sh | sh

Listen to four songs Try the studio in your browser

Score 90

Golden Pulse deep house · 120 BPM · A dorian

The drum lanes of the deep house song below, as the studio’s step sequencer shows them. Press play and they follow the music; lanes that sit out the build go dark.

01Listen

Four songs, made by claudius on a laptop

Each one is cut to about 40 seconds around its drop or groove. One came out of evolution and three from scripts. Next to each is what made it and what claudius printed, including the critic’s verdict.

Golden Pulse

deep house · 120 BPM · A dorian

Score 90

MP3 golden-pulse.rhai

How Golden Pulse was made

One command. It generated four deep house songs, then bred them for four generations of eight children each. Every child was auditioned on its build-up and first drop, and the four the critic liked best became the next parents. --no-library keeps Apple Loops and your own samples out; the sample packs still play.

Command

claudius evolve --genre deep_house --seed 5 --generations 4 --no-library

What it printed (… marks lines left out)

evolving deep_house (4 start, 4 generations x 8 children, 32-bar previews, with ears)
  g0-0  86.1  Hollow Harbor
  g0-1  80.0  Paper Haze
  g0-2  85.0  Glass Garden
  g0-3  85.9  Golden Pulse
+ g1-0  87.0  from g0-3: shaker: synth voice parameter 8 -> 0.079; mix: perc +2.4 dB (now +2.4)
+ g1-1  86.7  from g0-2: form: intro gets fills; drums: played on the tr808 kit
+ g1-2  86.3  from g0-3: harmony A: chord 2: IV7 -> IV (plain triad)
  g1-3  84.9  from g0-2: harmony A: swapped chords 3 and 4; mix: pad sidechain depth 0.49
  g1-4  85.3  from g0-0: drums: new clap pattern; mix: hat +1.9 dB (now +1.9)
  g1-5  79.2  from g0-0: crossover: drums and form of one parent, harmony and parts of the other; mix: pad +1.6 dB (now +1.6)
+ g1-6  86.7  from g0-3: swing 0.55 -> 0.53; chords (keys): drive 0.4 dB
+ g1-7  86.1  from g0-0: crossover: drums of one parent, everything else of the other; pad (warm_pad): release 2.59 s; form: drop now 24 bars
generation 1: best 87.0
…
generation 4: best 90.1
searched 36 candidates in 76 s; rendering the best 3 in full
#1 g4-1 (Golden Pulse): preview 90.1, full song 89.7
    swing 0.55 -> 0.53
    chords (keys): drive 0.4 dB
    pad: rewrote the part
    drums: played on the muldjord kit
    crossover: drums of one parent, everything else of the other
    kick: synth voice parameter 3 -> 0.447
    form: break now 24 bars
    crossover: drums and form of one parent, harmony and parts of the other
    mix: hat -3.0 dB (now -3.0)
Golden Pulse — deep_house at 120 BPM in A dorian, 112 bars (3:44)
  progression A: i9 IV7
  progression B: i IV7
  form: intro 16 | groove 16 | break 24 | build 8 | drop 32 | outro 16
  tracks: kick (synth kick), clap (sampled cp (tr808:cp)), hat (sampled hh (tr808:hh)), shaker (synth shaker), perc (sampled rim (tr808:rim)), bass (synth patch 'sub_bass'), chords (synth patch 'keys'), pad (sampled string_ensemble (vsco2:strings)), lead (sampled rhodes (jrhodes:rhodes)), crash (synth crash), riser (synth riser)
  master: -11.0 LUFS, true peak -1.0 dBTP (pre-master -10.3 LUFS)
  ears: 'house music' z +3.8 (closest confusion 'techno music' +3.1); production z +1.5 vs 'a low quality recording with hiss' +1.1; p_real 0.71
        sounds like: house music, tech house music, drum and bass music, techno music
  verdict: 90/100 (arc 0.92, genre 0.93, mix 0.95, production 0.59, theory 1.00). Fix first: dull 4-8 kHz: hats, claps and snare lack bite (presence -28.6 dB, healthy from -26); production reads close to 'a low quality recording with hiss' (z +1.1) vs professionally mixed (z +1.5)
  wrote out/evolve-deep_house-5/1-g4-1-golden-pulse/song.mp3

The winner, printed as a script

// Golden Pulse — deep_house (seed 8)
// song("deep_house", 8);   // uncomment to start over from the generator
title("Golden Pulse"); tempo(120); key("A dorian"); swing(0.53493524);
humanize(0.35);
prog("A", "i9 IV7");
prog("B", "i IV7");

// drums: X accent, x hit, o ghost, . rest, | bar line; 16 steps per bar unless a number follows
drum("kick", "main", "X...X...X...X...");
drum("kick", "sparse", "X...X...X...X...");
drum("clap", "main", "....X.......X...");
drum("hat", "main", "x.xxx.x..xxxx.x.|x.xxx.x..xxxx.x.|x.xxx.x..xxxx.x.|..xx.xx...xxxxxx");
drum("hat", "sparse", "..x...x...x...xx");
drum("shaker", "main", "o.o.o.ooo.ooo.o.");
drum("perc", "main", "x.x..x.x.x..x.x.");
drum("perc", "sparse", "..x.....x....x..");

// parts written by the theory engine: change the style, preset, register, density or seed
part("bass", #{ style: "syncopated", preset: "sub_bass", register: [33, 50], density: 0.4658955, seed: 7593466037959292827 });
part("chords", #{ style: "stabs", preset: "keys", register: [53, 74], density: 0.43242535, seed: -1845194844081732826 });
part("pad", #{ style: "sustain", preset: "vsco2:strings", register: [50, 76], density: 0.403872, seed: 5506831138054929778 });
part("lead", #{ style: "motif", preset: "jrhodes:rhodes", register: [62, 84], density: 0.34817874, seed: -2367553514172308588 });

form([
  sec("intro", 16, "kick hat shaker perc top").filter_in(),
  sec("groove", 16, "kick clap hat shaker perc bass chords top"),
  sec("break", 24, "pad chords lead shaker"),
  sec("build", 8, "clap hat shaker chords lead pad").energy(0.55).prog("B"),
  sec("drop", 32, "kick clap hat shaker perc bass chords lead pad top").energy(0.9),
  sec("outro", 16, "kick hat shaker perc bass"),
]);

mix("clap", #{ reverb: 0.3 });
mix("hat", #{ level: -2.9886246, pan: 0.18 });
mix("shaker", #{ pan: -0.3 });
mix("perc", #{ level: 2.3582892, pan: 0.4, reverb: 0.1, delay: 0.2 });
mix("bass", #{ duck: 0.45 });
mix("chords", #{ reverb: 0.3, delay: 0.1, duck: 0.35 });
mix("pad", #{ reverb: 0.4, duck: 0.4 });
mix("lead", #{ reverb: 0.35, delay: 0.25, duck: 0.15 });
mix("fx", #{ level: -3, reverb: 0.3 });

Paper Lanterns

lofi · 82 BPM · D minor

Score 94

MP3 paper-lanterns.rhai

How Paper Lanterns was made

A script with real instruments: a Rhodes, an upright bass, a vibraphone and a string section over a recorded kit. This is its third version; the revision log shows what the critic asked for each time.

Command

claudius script paper-lanterns.rhai

The script

// lofi in D minor at 82 BPM: a Rhodes, an upright bass, a vibraphone and strings over a recorded kit
blank("lofi"); title("Paper Lanterns"); tempo(82); key("D minor"); swing(0.6); humanize(0.35);
prog("A", "i9 iv9 VImaj7 V7"); bars_per_chord(1);

track("kick",  s("bd ~ ~ ~ ~ ~ bd ~ ~ ~ bd ~ ~ ~ ~ ~").bank("uzu"));
track("snare", s("~ sd ~ sd").bank("acoustic").gain(0.8));
track("hats",  s("hh*8").bank("acoustic").gain("0.9 0.55").degradeBy(0.1));
track("tamb",  s("~ tambourine ~ tambourine").gain(0.5).pan(0.3));
track("keys",  chord("prog").struct("x ~ ~ ~ ~ ~ x ~").voicing(53, 74).s("rhodes").room(0.3));
track("pad",   chord("prog").voicing(57, 72).s("string_ensemble").level(-8));
track("bass",  note("<[d2 ~ ~ a1 ~ ~ d2 ~] [g1 ~ ~ d2 ~ ~ g1 ~] [bb1 ~ ~ f2 ~ ~ bb1 ~] [a1 ~ ~ e2 ~ ~ a1 ~]>")
                 .s("upright_bass"));

let tune = "<[3 ~ 4 3 1 ~ 0 ~] [~ ~ 4 5 2 ~ 1 ~] [5 ~ 6 5 3 ~ 2 ~] [3 ~ ~ ~ 2 ~ ~ ~] "
         + "[3 ~ 4 3 1 ~ 0 ~] [~ ~ 4 5 2 ~ 1 ~] [6 ~ 7 6 5 ~ 3 ~] [2 ~ 3 ~ ~ ~ ~ ~]>";
track("vibes", n(tune).scale("D:minor:pentatonic").octave(4).s("vibes").delay(0.25));

form([sec("intro", 4, "keys pad"), sec("groove", 8, "kick snare hats keys bass"), sec("groove", 16, "*"),
      sec("break", 8, "keys vibes pad").prog("A"), sec("groove", 16, "*"), sec("outro", 4, "keys pad")]);

What it printed

track kick: bd
track snare: sd
track hats: hh
track tamb: tambourine
track keys: rhodes
track pad: string_ensemble
track bass: upright_bass
track vibes: vibes
ears loaded in 12.9 s
Paper Lanterns — lofi at 82 BPM in D minor, 56 bars (2:44)
  progression A: i9 iv9 VImaj7 V7
  progression B: i9 IIsus4 VImaj9 v9
  form: intro 4 | groove 8 | groove2 16 | break 8 | groove3 16 | outro 4
  tracks: kick (sampled bd (uzu:bd)), snare (sampled sd (muldjord:sd)), hats (sampled hh (muldjord:hh)), tamb (sampled tambourine (vcsl:tambourine)), keys (sampled rhodes (jrhodes:rhodes)), pad (sampled string_ensemble (vsco2:strings)), bass (sampled upright_bass (doublebass:upright_bass)), vibes (sampled vibes (vcsl:vibraphone))
  master: -12.5 LUFS, true peak -1.6 dBTP (pre-master -9.8 LUFS); done in 32.1 s
  ears: 'lo-fi hip hop beat' z +3.8 (closest confusion 'hip hop beat with heavy bass' +3.0); production z +1.9 vs 'a low quality recording with hiss' +0.9; p_real 0.74
        sounds like: lo-fi hip hop beat, hip hop beat with heavy bass, inspirational corporate background music, warm and cozy music
  verdict: 94/100 (arc 0.91, genre 0.95, mix 1.00, production 0.76, theory 1.00)
  wrote out/lofi-paper-lanterns-1/song.mp3

Night Shift

techno · 130 BPM · F minor

Score 88

MP3 night-shift.rhai

How Night Shift was made

A script: a real TR-909, a bass rolling between the kicks, an acid line, a chord stab and recorded congas. The excerpt starts four bars before the second drop, so you hear the beat of silence that .gap() leaves in front of it. The critic still hears a mix close to mono; that note stayed in.

Command

claudius script night-shift.rhai

The script

// techno in F minor at 130 BPM: a TR-909, a rolling bass between the kicks, an acid line and a chord stab
blank("techno"); title("Night Shift"); tempo(130); key("F minor");
prog("A", "i7"); bars_per_chord(1);

track("kick",  s("bd*4").bank("tr909"));
track("clap",  s("~ cp ~ cp").bank("tr909").room(0.25));
track("ohat",  s("[~ oh]*4").bank("tr909").gain(0.7).pan(0.3));
track("hats",  s("hh*16").bank("tr909").gain("0.6 0.3 0.45 0.3").pan(-0.3));
track("rim",   s("~ ~ rim ~ ~ ~ rim ~ ~ rim ~ ~ ~ ~ rim ~").bank("tr909").gain(0.5).pan(0.5).delay(0.3));
track("congas", s("~ ~ conga ~ ~ conga ~ ~ ~ ~ conga ~ conga ~ ~ ~").gain(0.6).pan(-0.5).room(0.3));
track("bass",  note("f1").struct("~ x x x ~ x x x ~ x x x ~ x x x").s("saw_bass").lpf(500).legato(0.6));
track("acid",  note("<[f2 f2 f3 f2 ab2 f2 c3 f2 f2 eb3 f2 f2 c3 f2 bb2 eb3] [f2 f2 f3 f2 ab2 f2 c3 f2 f2 eb3 f2 ab2 c3 eb3 f3 c3]>")
                 .s("acid").role("lead").delay(0.15));
track("stab",  chord("prog").struct("~ ~ ~ x ~ ~ x ~").voicing(55, 70).s("stab").room(0.4).delay(0.3));
track("strings", chord("prog").voicing(53, 72).s("string_ensemble").level(-9).room(0.5));

form([sec("intro", 8, "kick hats"), sec("groove", 16, "kick hats ohat congas bass clap"),
      sec("build", 8, "kick hats ohat bass stab").build(), sec("drop", 16, "kick clap hats ohat rim congas bass stab"),
      sec("break", 8, "stab acid strings").prog("A").gap(), sec("drop", 16, "*").impact(), sec("outro", 8, "kick hats congas")]);

What it printed

track kick: bd
track clap: cp
track ohat: oh
track hats: hh
track rim: rim
track congas: conga
track bass: saw_bass
track acid: acid
track stab: stab
track strings: string_ensemble
ears loaded in 7.6 s
Night Shift — techno at 130 BPM in F minor, 80 bars (2:28)
  progression A: i7
  progression B: i
  form: intro 8 | groove 16 | build 8 | drop 16 | break 8 | drop2 16 | outro 8
  tracks: kick (sampled bd (tr909:bd)), clap (sampled cp (tr909:cp)), ohat (sampled oh (tr909:oh)), hats (sampled hh (tr909:hh)), rim (sampled rim (tr909:rim)), congas (sampled conga (vcsl:congas)), bass (synth patch 'saw_bass'), acid (synth patch 'acid'), stab (synth patch 'stab'), strings (sampled string_ensemble (vsco2:strings)), crash (synth crash), riser (synth riser), impact (synth impact), downlifter (synth downlifter)
  master: -8.9 LUFS, true peak -1.0 dBTP (pre-master -9.8 LUFS); done in 22.0 s
  ears: 'techno music' z +4.4 (closest confusion 'drum and bass music' +3.1); production z +1.1 vs 'a low quality recording with hiss' +1.4; p_real 0.68
        sounds like: techno music, a punchy kick drum pattern, drum and bass music, an uplifter sweep
  verdict: 88/100 (arc 0.92, genre 1.00, mix 0.92, production 0.45, theory 1.00). Fix first: production reads close to 'a low quality recording with hiss' (z +1.4) vs professionally mixed (z +1.1); nearly mono (correlation 0.97): widen pads, chords and effects; dull 4-8 kHz: hats, claps and snare lack bite (presence -26.1 dB, healthy from -26)
  wrote out/techno-night-shift-1/song.mp3

Low Light

drum and bass · 174 BPM · C minor

Score 93

MP3 low-light.rhai

How Low Light was made

A script for liquid drum and bass: the Yamaha grand and a string section on a slow progression, a flute on top, and a two-step beat with a recorded snare, hats and ride, and ghost snares between the backbeats. The excerpt runs from the last four bars of the build into the drop.

Command

claudius script low-light.rhai

The script

// liquid drum and bass in C minor at 174 BPM: a grand piano, strings and a flute over a recorded kit
blank("dnb"); title("Low Light"); tempo(174); key("C minor");
prog("A", "i9 VImaj7 IIImaj7 VII"); bars_per_chord(2);

track("kick",   s("bd ~ ~ ~ ~ ~ ~ ~ ~ ~ bd ~ ~ ~ ~ ~").bank("uzu"));
track("snare",  s("~ ~ ~ ~ sd ~ ~ ~ ~ ~ ~ ~ sd ~ ~ ~").bank("acoustic"));
track("ghosts", s("~ ~ ~ ~ ~ ~ ~ sd ~ sd ~ ~ ~ ~ ~ sd").bank("acoustic").gain(0.35));
track("hats",   s("hh*8").bank("acoustic").gain("0.8 0.5"));
track("ride",   s("~ rd ~ rd").bank("acoustic").gain(0.4).pan(0.25));
track("bass",   note("<c2 c2 ab1 ab1 eb2 eb2 bb1 bb1>").struct("x ~ ~ ~ ~ ~ x ~ ~ ~ x ~ ~ ~ ~ ~").s("sub_bass").legato(0.9));
track("piano",  chord("prog").struct("x ~ ~ ~ ~ ~ ~ ~ ~ ~ x ~ ~ ~ ~ ~").voicing(55, 76).s("piano").room(0.35));
track("strings", chord("prog").voicing(53, 72).s("string_ensemble").level(-7).room(0.5));

let tune = "<[4 ~ ~ 2 4 ~ 6 ~] [7 ~ ~ ~ ~ ~ ~ ~] [2 ~ ~ 0 2 ~ 4 ~] [4 ~ ~ ~ ~ ~ 3 2] "
         + "[4 ~ ~ 2 4 ~ 8 ~] [6 ~ ~ ~ ~ ~ ~ ~] [3 ~ ~ 1 3 ~ 5 ~] [6 ~ ~ ~ ~ ~ ~ ~]>";
track("flute",  n(tune).scale("C:minor").octave(5).s("flute").level(-4).room(0.4).delay(0.2));

form([sec("intro", 16, "piano strings").filter_in(), sec("build", 8, "piano strings hats ride kick").build(),
      sec("drop", 32, "*").impact(), sec("break", 16, "piano strings flute").prog("A").gap(),
      sec("drop", 32, "*").impact(), sec("outro", 8, "piano strings")]);

What it printed

track kick: bd
track snare: sd
track ghosts: sd
track hats: hh
track ride: rd
track bass: sub_bass
track piano: piano
track strings: string_ensemble
track flute: flute
ears loaded in 4.2 s
Low Light — dnb at 174 BPM in C minor, 112 bars (2:34)
  progression A: i9 VImaj7 IIImaj7 VII
  progression B: i7 IIIsus4 VII7 VImaj7
  form: intro 16 | build 8 | drop 32 | break 16 | drop2 32 | outro 8
  tracks: kick (sampled bd (uzu:bd)), snare (sampled sd (muldjord:sd)), ghosts (sampled sd (muldjord:sd)), hats (sampled hh (muldjord:hh)), ride (sampled rd (muldjord:rd)), bass (synth patch 'sub_bass'), piano (sampled piano (salamander:piano)), strings (sampled string_ensemble (vsco2:strings)), flute (sampled flute (vsco2:flute)), crash (synth crash), riser (synth riser), impact (synth impact), downlifter (synth downlifter), reverse_crash (synth reverse_crash)
  master: -8.5 LUFS, true peak -1.0 dBTP (pre-master -8.5 LUFS); done in 23.9 s
  ears: 'drum and bass music' z +3.1 (closest confusion 'house music' +2.3); production z +1.7 vs 'a low quality recording with hiss' +0.9; p_real 0.76
        sounds like: jazz music, funk music, drum and bass music, a snare roll
  verdict: 93/100 (arc 0.98, genre 0.85, mix 1.00, production 0.72, theory 1.00)
  wrote out/dnb-low-light-1/song.mp3

Credits for the sampled instruments in these songs

  • Salamander Grand Piano V3 by Alexander Holm, SFZ mapping by kinwie / sfzinstruments, CC BY 3.0. The piano in Low Light.
  • MuldjordKit by Lars Muldjord, FreePats stereo edition by Roberto (freepats.zenvoid.org), CC BY 4.0. The snare, hats and ride in Paper Lanterns and Low Light.
  • jRhodes3d by Jeff Learman, free for making music. The Rhodes in Golden Pulse and Paper Lanterns.
  • TR-909 Ultimate Sample Pack by Audio Realism. The drum machine in Night Shift.
  • Public domain, CC0 or the Unlicense, credited with thanks: VS Chamber Orchestra 2 and the Versilian Community Sample Library by Versilian Studios, the double bass by D. Smolken, TR-808 samples by Michael Fischer, and the uzu drumkit by Mot4i, Switch Angel and Ludens.

02How it works

Compose, render, listen, revise

A song goes round this loop until the critic runs out of complaints or you stop it. Under each stage is what claudius printed while it made Paper Lanterns.

  1. 1Compose

    Music theory writes a blueprint, the song’s genome: tempo, key, chord progressions as Roman numerals, the form, drum patterns, melodic parts with a writing style, every sound and the mix. Scripts, mutations and the studio all edit the same blueprint.

    Paper Lanterns — lofi at 82 BPM in D minor, 56 bars (2:44)
      progression A: i9 iv9 VImaj7 V7
      form: intro 4 | groove 8 | groove2 16 | break 8 | groove3 16 | outro 4
  2. 2Render

    The blueprint is arranged like a DAW session, with fills at phrase ends, builds with a riser and a highpass sweep, and a beat of silence before the drop. Each track is balanced to its role’s loudness, ducked under the kick and sent to reverb and delay; the master lands on the genre’s loudness target.

    master: -12.5 LUFS, true peak -1.6 dBTP (pre-master -9.8 LUFS); done in 32.1 s
  3. 3Listen

    The critic meters the master (loudness, tonal balance per band, stereo width, mono low end), checks the energy arc and the score (melody in key, chord tones on strong beats, bass on the roots), and listens with earshot, a CLAP audio model ported to Rust.

    ears: 'lo-fi hip hop beat' z +3.8 (closest confusion 'hip hop beat with heavy bass' +3.0)
    verdict: 94/100 (arc 0.91, genre 0.95, mix 1.00, production 0.76, theory 1.00)
  4. 4Revise

    Every issue names what to change. You change it in the studio or the script, an assistant changes it over MCP, or claudius evolve mutates the song and keeps the children the critic prefers.

    Fix first: no air above 8 kHz: hats and cymbals too quiet or too dark (air -35.4 dB, healthy from -30)

Three versions of Paper Lanterns

Judged with meters and theory only (--no-ears), which takes seconds. Each line is the verdict as printed.

  1. Version 186

    verdict: 86/100 (arc 0.88, mix 0.81, theory 0.92). Fix first: no air above 8 kHz: hats and cymbals too quiet or too dark (air -35.4 dB, healthy from -30); low end not mono (correlation 0.85 below 150 Hz); only 25% of the lead's strong-beat notes are chord tones

    Rewrote the vibraphone line so beats 1 and 3 land on chord tones, made it eight bars long, raised the hats, and moved the keys and strings up out of the low end.

  2. Version 289

    verdict: 89/100 (arc 0.89, mix 0.83, theory 1.00). Fix first: no air above 8 kHz: hats and cymbals too quiet or too dark (air -34.6 dB, healthy from -30); low end not mono (correlation 0.85 below 150 Hz); muddy 250 Hz-1 kHz: too much pad / chord body (lowmid -3.9 dB, healthy up to -4)

    Three quick renders, each with one track muted, showed that the stereo low end came from the recorded kit’s kick, so the kick moved to the uzu kit. A tambourine on beats 2 and 4 added the missing air, and the chords now follow the song’s progression with chord("prog").

  3. Version 397

    verdict: 97/100 (arc 0.91, mix 1.00, theory 1.00)

    No issues left. With the ears on, the same song scores 94: genre 0.95 for “lo-fi hip hop beat”, production 0.76.

The critic measures; it does not have taste. A high score means no measurable problems and a confident genre read, not a hit, so listen to finished songs yourself.

03Script

The song is a script

A claudius script is Rhai with mini-notation patterns borrowed from Strudel. One cycle of a pattern is one bar. This is all of Paper Lanterns:

// lofi in D minor at 82 BPM: a Rhodes, an upright bass, a vibraphone and strings over a recorded kit
blank("lofi"); title("Paper Lanterns"); tempo(82); key("D minor"); swing(0.6); humanize(0.35);
prog("A", "i9 iv9 VImaj7 V7"); bars_per_chord(1);

track("kick",  s("bd ~ ~ ~ ~ ~ bd ~ ~ ~ bd ~ ~ ~ ~ ~").bank("uzu"));
track("snare", s("~ sd ~ sd").bank("acoustic").gain(0.8));
track("hats",  s("hh*8").bank("acoustic").gain("0.9 0.55").degradeBy(0.1));
track("tamb",  s("~ tambourine ~ tambourine").gain(0.5).pan(0.3));
track("keys",  chord("prog").struct("x ~ ~ ~ ~ ~ x ~").voicing(53, 74).s("rhodes").room(0.3));
track("pad",   chord("prog").voicing(57, 72).s("string_ensemble").level(-8));
track("bass",  note("<[d2 ~ ~ a1 ~ ~ d2 ~] [g1 ~ ~ d2 ~ ~ g1 ~] [bb1 ~ ~ f2 ~ ~ bb1 ~] [a1 ~ ~ e2 ~ ~ a1 ~]>")
                 .s("upright_bass"));

let tune = "<[3 ~ 4 3 1 ~ 0 ~] [~ ~ 4 5 2 ~ 1 ~] [5 ~ 6 5 3 ~ 2 ~] [3 ~ ~ ~ 2 ~ ~ ~] "
         + "[3 ~ 4 3 1 ~ 0 ~] [~ ~ 4 5 2 ~ 1 ~] [6 ~ 7 6 5 ~ 3 ~] [2 ~ 3 ~ ~ ~ ~ ~]>";
track("vibes", n(tune).scale("D:minor:pentatonic").octave(4).s("vibes").delay(0.25));

form([sec("intro", 4, "keys pad"), sec("groove", 8, "kick snare hats keys bass"), sec("groove", 16, "*"),
      sec("break", 8, "keys vibes pad").prog("A"), sec("groove", 16, "*"), sec("outro", 4, "keys pad")]);
s("bd ~ ~ ~ ~ ~ bd ~ ~ ~ bd ~ ~ ~ ~ ~")
One bar cut into sixteen steps, with kicks on steps 1, 7 and 11. ~ is a rest, hh*8 is eight hats in a bar.
.bank("acoustic")
Plays the snare and hats from a recorded kit; .bank("uzu") takes the kick from another one.
prog("A", "i9 iv9 VImaj7 V7")
The progression as Roman numerals, so key() can move it. chord("prog") plays whichever chord the song is on, voice-led between MIDI notes 53 and 74.
n(tune).scale("D:minor:pentatonic")
The vibraphone line as scale degrees. < > plays one group per bar, so the tune is eight bars long.
form([sec("intro", 4, "keys pad"), …])
The sections, their lengths in bars, and which tracks play in each. "*" is every track.
The first four tracks as a step sequencer: the same bar, drawn the way the studio draws it.

Run it, or read any song

# render it, judge it and write the song folder
claudius script paper-lanterns.rhai
# run a script on a saved song: it changes only what the script names
claudius script tweak.rhai --on out/lofi-paper-lanterns-1
# the whole language
claudius reference

Every song prints as a script: the studio’s script tab shows it, GET /api/script returns it, claudius script writes it to song.rhai beside the render, and --print prints it for a saved song. Running that script on the song changes nothing, so a script is also how you read a song. Golden Pulse came out of evolution, and its script was printed this way.

04Studio

A studio, native and in the browser

claudius studio opens the native window. claudius serve serves the same app, compiled to WebAssembly, at http://127.0.0.1:7878. Both are clients of one session, so the window, a browser tab and an assistant can work on the same song at once. Every change renders and is judged in the background, a few seconds for a full song.

The Claudius studio with Golden Bloom, a deep house song in G# minor at 123 BPM, rendered and open. At the top, the transport and its cyan readout; below, the arrangement with six coloured sections (intro, groove, break, build, drop, outro) and one row per track, the master waveform coloured by section, and the step sequencer for kick, clap, hat, shaker and perc. On the right, the selected section’s settings and the verdict: 98 out of 100, one issue, and the measures.
The arrangement, the step sequencer and the verdict. Sections are blocks you drag to reorder and right-click to duplicate, insert or remove; each track has a cell per section that switches it on or off there.
The mixer with the lead soloed: channel strips with pan, reverb, delay and duck knobs and a fader, every other track marked silent while the lead plays, and the master strip with its meters at −11.0 LUFS and −1.0 dBTP.
Mixer. Level, pan, sends and sidechain per track, mute and solo, loudness meters and the master.
The verdict panel: a ring showing 98 out of 100, bars for arc, mix and theory, the issue to fix first (a fizzy top end), and the measures: tonal balance per band, loudness, true peak, loudness range and stereo correlation.
Verdict. The score, the issue to fix first, and the measures behind it.
The harmony tab of a song in G# minor: which progression each section plays (A in the intro, groove and drop, B in the break and build), and progression A as four chords, i7 iv7 v7 i7, with the chord names under the Roman numerals.
Harmony. Progressions as chords and Roman numerals, and which sections play which.

Open the studio demo

The demo runs the studio in your browser with a built-in mock in place of the engine. Every panel works; the audio is a rough preview synthesized in the page. For real renders, run claudius studio or claudius serve.

05Assistants

Make songs with Claude, Cursor or ChatGPT

claudius is an MCP server. An assistant connected to it sees the song you have open, edits it with scripts, mutations, evolution or raw edits, renders and judges it, and you hear every change in the studio as it happens.

Claude Code

claude mcp add --scope user claudius -- claudius mcp

Codex

codex mcp add claudius -- claudius mcp

Claude Desktop

In Claude's settings, Developer, Edit Config opens claude_desktop_config.json. Add this and restart Claude, with the full path that which claudius prints.

{
  "mcpServers": {
    "claudius": {
      "command": "/Users/you/.local/bin/claudius",
      "args": ["mcp"]
    }
  }
}

Cursor

Add to Cursor

Cursor asks before it adds it. Or put the same command and arguments in ~/.cursor/mcp.json:

{
  "mcpServers": {
    "claudius": { "command": "claudius", "args": ["mcp"] }
  }
}

claudius connect claude-code (or claude-desktop, cursor, codex) does the same with the full path, and adds the skills that teach the assistant claudius; so does Connect an assistant, in the studio.

claudius mcp drives the studio when one is running on the port, so you and the assistant share the song. When none is running, it starts a session of its own and serves the web studio on the port, so you can still open it.

Clients that speak Streamable HTTP can use http://127.0.0.1:7878/mcp while the studio or claudius serve runs.

ChatGPT

Assistants in the cloud need a public HTTPS address. Run claudius with a token behind a tunnel:

TOKEN=$(openssl rand -hex 16)
echo "$TOKEN"
claudius serve --public --token "$TOKEN"
cloudflared tunnel --url http://127.0.0.1:7878

Then add a custom connector in ChatGPT’s developer mode with the URL https://<tunnel>/mcp?token=<token>. The studio is at https://<tunnel>/?token=<token>.

The tools an assistant gets

  • new_song
  • get_song
  • run_script
  • script_reference
  • listen
  • mutate
  • evolve
  • status
  • undo
  • redo
  • stop
  • catalog
  • save
  • open
  • analyze
  • remake
  • command

Make a deep house track at 122 BPM, listen to it, and fix the critic’s top two issues.

A good first message

06Sounds

Real sounds, with their licences

Notes exist only as the score that plays the sounds, like a piano roll. The sounds themselves are synthesized in code or recorded.

Synthesized

13 drum voices; a polyphonic and monophonic synth engine with polyBLEP oscillators, unison with analog drift, SVF and ladder filters, FM and glide, and 20 presets; risers, downlifters, impacts and reverse cymbals. claudius sounds renders every one of them to WAV.

Recorded

14 sample packs with 162 instruments, multi-sampled with velocity layers and round robins, all under licences that allow making and publishing music with them. claudius-packs install --defaults downloads them, about 1.1 GB. Songs that use CC BY packs get a credits.txt.

The default packs
PackWhat it isLicence
salamanderYamaha C5 grand piano, five velocity layersCC BY 3.0
epianosWurlitzer EP200, Yamaha CP80, Hohner Pianet TCC BY 3.0
jrhodes1977 Rhodes Mark I Stage 73free for making music
vsco2Chamber orchestra: strings, brass, woodwinds, harp, timpaniCC0
vcslMallets, pipe organ, tenor sax, harmonica, world and orchestral percussionCC0
tr808Roland TR-808, sampled by Michael Fischer in 1994CC0
tr909Roland TR-909, with every accent levelfree use, no redistribution
tr707Roland TR-707public domain
uzuA small processed electronic kit made for StrudelUnlicense
muldjordAcoustic rock kit with velocity layersCC BY 4.0
freepatsUpright piano, FM piano, organ, bass guitars, classical and electric guitars, synths and padsCC0
doublebass1958 double bass, pizzicatoCC0
growlybassFingered electric bass recorded directCC0
voiceA sung “a” vowel, and a five-voice choir built from itCC0

Apple Loops

When GarageBand or Logic content is installed, claudius uses it too, about 14,000 loops on a full install. Apple licenses these loops for your own music; claudius reads them where GarageBand put them and copies nothing except one-shot cuts in its cache. The songs on this page use none.

Your own sounds

claudius chop cuts any recording into bar loops and drum one-shots for your library, make --sample flips a chop into a song, and scripts play any file with .s("/path/to/sound.wav").

07Install

Install

The install scripts download the latest release, check it against the release’s SHA256SUMS, and put claudius, claudius-packs and the web studio in your user folder. Then they offer to fetch the sample library and the listening models.

macOS and Linux

curl -fsSL https://github.com/devlato/claudius/releases/latest/download/install.sh | sh

Apple silicon and Intel Macs (Intel builds have no ears: their verdicts come from the meters and the theory checks); x86_64 and ARM64 Linux with glibc 2.38 or newer (Ubuntu 24.04, Debian 13, Fedora 39 and later). Without ALSA you get the headless build, which serves the studio to your browser. The commands go to ~/.local/bin.

Windows preview

irm https://github.com/devlato/claudius/releases/latest/download/install.ps1 | iex

In PowerShell. An x64 build, which also runs on ARM64 Windows; it is newer and less tested than the others, so please report what breaks. The commands go to %LOCALAPPDATA%\Programs\claudius\bin, which the script adds to your PATH.

From source

With a Rust toolchain, in a clone of the repository:

cargo install --path crates/claudius-cli       # the claudius command
cargo install --path crates/claudius-packs     # the claudius-packs command
(cd crates/claudius-ui && NO_COLOR=true trunk build --release)   # the web studio (optional; needs trunk)

Then

claudius setup                  # the sample packs (about 1.1 GB) and the listening models (about 0.8 GB)
claudius doctor                 # checks the installation: studio, packs, models, ffmpeg, the port
claudius make --genre house     # a full song in out/house-<title>-<seed>/
claudius studio                 # the studio window, with the engine inside

Without the models, --no-ears judges with meters and theory only. Once they are downloaded, they load in about 4 seconds.