Spellbook: Plain text sequencing

Spellbook is a module to sequence pitch and control voltage (CV) patterns in a eurorack-style environment using a plain text syntax I call RhythML.

It has 16 outputs (and a polyphonic output which combines all of them), each of which outputs a voltage determined by the corresponding column in formatted text input. Spellbook is not yet in the VCV Rack Library version of this plugin; check Releases to install the preview build.

Sequencing with RhythML

Spellbook sequences are programmed using the RhythML format, a syntax to define pitch and CV patterns in plain text. Each line in the text input represents a sequence step, triggered sequentially by the clock input. Columns in the text represent the 16 outputs, allowing for complex configurations across multiple hardware modules.


  • Decimal Voltages: Directly specify voltage outputs by writing decimal numbers.
  • Gate and Trigger Commands: Use X/_ for gate-with-retrigger, T/^ for a 1ms trigger pulse, or W/| for a full-width gate; as shorthand for rhythmic sequences.
  • Scientific Pitch Names: Specify pitches using standard note names (e.g., C4, G#3, Fb4), and they are translated to 1V/oct standard.
  • MIDI numbers, prefixed with m (e.g. m60 for C4)
  • Percentages ending in % (e.g. 50% or 12.5%), which are scaled so that 100% = 10.0v.
  • Hertz in the format <Frequency>Hz (e.g. 440Hz)
  • Semitones (relative to C4) in the format s<Number> (e.g. s7)
  • Cents (relative to C4) in the format <Number>ct (e.g. 100ct)

Refer to RhythML Syntax for comprehensive guidelines on writing sequences for Spellbook.

Usage Example

Here’s a simple RhythML sequence to get started:

E4 ? Pitch, X ? Gate, 10 ? Velocity
C5        , X       , 8
D5        , X       , 6
B4        , X       , 5

In this example, each step sets a pitch in column 1, uses column 2 for gating, and controls a velocity CV in column 3. The sequence plays a C major arpeggio, holding the first note for a full beat, and gradually lowering the velocity on each note. The labels, like ? Pitch, are ignored because of the ?.

Here’s the same arpeggio, but with a little more rhythmic variation:

E4 ? Pitch, X ? Gate, 10 ? Velocity
          , |       , 
          , |       , 
C5        , X       , 8
D5        , X       , 6
          ,         , 
B4        , X       , 5
          ,         , 

Notice the way this pattern holds notes by using consecutive gates over several steps, using Retriggers to ensure a new rising edge after a prior gate.

You could also do things like treat each row as a sequence, played through a sequential switch like my Ouroboros module.

Would love to hear feedback from anyone that helps test it. There are a few more quality of life changes I want to make before I submit to the library, so this is a good time for other suggestions and fixes.


Watch a brief demonstration here:


Spellbook appears to be very interesting as a discrete event scheduler and processor.

I have installed the latest alpha for Windows and will do some testing.

What license will you release to the library under?

I’ve been putting it all under the MIT license.

1 Like

Thanks, I did not recognize you license text as MIT.

Release Spellbook Alpha 6 · Jadael/TMT (github.com)

Improvements in the newest build:

  • Index input, a new CV input that directly addresses steps such that 0v = first step, 10v = last step. This could let you drive Spellbook using a rising ramp like a Phasor, or by otherwise addressing rows by CV however you like. The clock is ignored if anything is connected to Index.
  • Scrolling - When in focus, mouse scrolling will work as before, and it will also scroll to keep the text cursor visible. When NOT in focus, Spellbook will auto-scroll to keep the active step centered.
  • Additional trigger symbols: _ for retrigger, | for full-width gate, and ^ for trigger pulse. The old letter codes still work, but some people may prefer these for a more visually distinct view of what a gate column is doing. I’m not totally sold on _ if anyone has a better idea for a good symbol that shows you where notes start:

Question for the community, how important is an internal clock to you?


I don’t use internal clocks on sequencers, I like to clock all my other stuff with divisions and maybe have swing and other features… so it’s just better to use a dedicated module for it. Although if you do have an internal clock on your tracker, then you would also need to add an extra clock output. I think it complicates things when there are lots of great clocks to choose from.

This module is turning out really nifty, I think it’s very innovative!! The demo patch was also very nice sounding! I do like the CV indexing, it’s something that I wish more sequencer would implement, I use it on my Mimetic Digitalis in eurorack. If you have 100 steps, then I guess .1V is a step? Do negative voltages wrap around?

I have a whole list of little suggestions (that you should just please feel free to ignore!!!):

Context menu control of the font size, mainly with a larger option. In cases where you only use a few outputs the text could be a lot larger to fill up the width of the module, and it would be much easier to use if I didn’t have to zoom in to make the spreadsheet fill the screen. Or in other words, it would be cooler if the spreadsheet were way more zoomed in.

Or… okay okay hear me out. Make the spreadsheet part a little bit smaller so that you can have a display window at the top. The top window displays just the current step much larger, and scaled to fill the width. Then when you go to edit the sequence, you would be able to edit it from the current step window, and have a larger interface. It would allow you have the rest of the sequence displayed smaller, and by clicking around to where you want the top box is larger. This is basically how Excel works, btw, but that’s a really proven way to interact with a spreadsheet.

A high-contrast or accessibility mode that puts text over solid dark grey background, maybe with a nice looking border or transition around the screen part. Bonus if you can make it look like slate or something that still matches the theme. (basically I find the colored text over varigated background to be difficult to read, but I really get the theme and look is important)

Column headers that make it more clear what the different columns are controlling. Allowing them to be use user named or taken from Row1 would be cool. I always do it in Excel, lock the top row when I scroll a big sheet.

Columns borders that are rendered by the module as lines, and maybe a tiny space between adjacent columns. This should be possible to do since you are using a fixed-width font.

Some kind of % display that shows where the tracker is in relation to the whole sequence, like a scroll bar indicator or something. For example, you could put a health bar looking thing at the bottom left, and have a marker on it that indicates the current position in the sequence.

The mouse pointer should turn into a quill pen when you mouse over the module :slight_smile: That would be really fun.

nice but not really necessary

1 Like

Well, that certainly looks interesting.

Cat Standing

Is it resizable?

No, but it really needs to be. At some point I’m going to sit down and figure out that and Undo support.

Today’s focus was aesthetic changes, it’s now got a backdrop for the text, zebra striped columns, and comment highlighting:


Going to consider this build a candidate for submitting to the Library, if no one finds any bugs:

Release Release v2.1.0 · Jadael/TMT (github.com)

Bonus new module: “Stats”! Get the mean, mode(s), median, geomean, sum, product, count, sorted list, and distinct list of a polyphonic cable.

Also a blank panel, for fun.

For examples of resizing and undo/redo, you might look at the source of my TTY and Fermata modules. Oh, and make sure that resizing is itself in the undo/redo queue.

And if you ever consider having your module send or receive text via cables, I hope you’ll consider the Tipsy protocol.

Fermata has been an invaluable resource for study during the entire project. I built it up from the core Notes module, but constantly referred to Fermata for an understanding of just, how to even think about what I was doing.

I can imagine an expander module that sends each cell’s content as Tipsy to another 16 outputs, but I don’t know what that might be useful for. Perhaps a way to accept Tipsy input and write that text into the cells :thinking:

I’m thrilled to hear that! And hope that any stupidity on my part hasn’t infected your module :wink:

Right now BASICally can output Tipsy, but it doesn’t yet have string variables, so it’s not as easy as you’d hope. It doesn’t accept Tipsy text yet. I guess I’m thinking that one might send generated text to Spellbook, for it to incorporate into it’s instructions…well, I should try Spellbook out before considering that a useful suggestion.

TTY accepts Tipsy, so if you had status or debug output that users might optionally want to see, that’s a way to display it. Again, not really sure that’s germane.

Mainly I saw a module relying on text and thought, oh, hey, this might be relevant.

Spellbook could be a justification for another module idea I’ve had: a way to perform with text. Like, imagine a document with bits of text in it, with the ability to edit it, or select some text and send it to another module to perform. Like live coding, but separating out the editor from the interpreter, to allow for multiple kind of interpreters.

1 Like

I also feel like an internal clock isn’t worth the bother. There are many wonderful clock modules out there with fantastic features. I’m particularly fond of Impromptu Clocked — I know how to make it do all kinds of tricks, and it’s in my muscle memory.

People can also use something like a gate sequencer as an intentionally irregular external clock. Or a square wave coming out of a frequency-modulated LFO. And so on…

I love this idea of a text-based sequencing language. There is so much potential here. I’m definitely keeping an eye on this module!

1 Like

I also agree that an internal clock is unimportant to me. For my own modules, I provide internal clock but I always use an external clock. I prefer to use an Impromptu CLOCKED as the master clock. I spent quite a bit of effort in the beginning getting my modules to also take the CLOCKED BPM out and set my module’s internal BPM accordingly. All of this becomes more important for time signature based sequencers.

1 Like

Congrats! Very nice module. It’s easier for me than working with Loud Numbers and I see myself replacing BASICally in many of my patches with Spellbook. :ok_hand:

I finally installed it, and am starting to play around. It’s super neat! I’ll share a patch once I make something interesting.

Couple questions/comments: -If I make a column header row, and reset the steps, why does it go to the header row? I think the header should be row 0, and reset should take it to row 1. Also, possible I am using it wrong…

-I don’t understand how the reformatting/updating works. It only reformats the text if I have a clock patched, or stop the clock. No way to have the module reformat the sheet, maybe you need a button for that?

-If the clock is running, it doesn’t update changes to the sequence. I have to stop the clock for the update to happen.

-A manual reset button and manual trigger advance button would be nice to have. A step-backwards, or reverse input would be handy too perhaps?

-Clicking on the step number should jump to that step.

-Hitting Initialize in the context menu or cmd-I should reset the module to the starter text I think.

Right now the rows have to be in row 1 (there is no “header” row), but I do want to make it so ?? starts a full-line comment, which lets that entire row be ignored when counting “steps”, especially for having a row 0 as column labels.

I originally imagined that optional row numbers might be part of the syntax, too, like:

1: C4, X
3: D4, X
4: D#, |
6: E4, X

The idea being you could write sequences in a “terse” style that omits empty steps if you wanted, to make long sequences easier to read, write and share. Feels complicated though lol.

It parses the text onDeselect(), the idea being that if it were constantly checking and re-formatting as you typed it would be difficult to type anything. I think I do want Ctrl+Enter to be a hotkey for “re-parse” though, along with Ctrl+Left/Right to jump cells.

Step Back is a great idea.

Release Release v2.1.1 · Jadael/TMT (github.com)


  • Comments in the first step (not “step 0”, unfortunately, coming soon maybe) become labels on the outputs
  • “G” replaced by “W” as a keyword for “Gate” so it doesn’t conflict with the note “G”
  • Created some manufacturer presets
  • Added a little tutorial sequence as the default text
  • Reset restores it to the tutorial sequence
  • Renamed “clock” to “step forward”
  • Added a “step back” input
  • Fixed some edge cases for indexing
  • Index input can be toggled between two modes: Relative, where 0v = Step 1 through 10v = Last Step, or Absolute Mode, where 1v = Step 1, 2v = Step 2, etc.
    • If you send a clean linear ramp to Relative Index, you could use Spellbook as a crude oscillator or shape generator (there’s no filtering or anti-aliasing of any kind, so you’re on your own with making it sound good). See the ‘Waveforms’ preset.
  • Two new outputs output the Relative and Absolute index of the current step, so you can sync or address Spellbooks with each other (e.g. you could address one Spellbook using a sequence from another using Absolute, or sync them like Phasors using Relative)
  • Added more note names to the parser, such as non-standard ones like E#, and double sharp ##/double flat bb
  • Added horizontal scrolling, and changed scroll behavior so it only updates if the cursor would be out of view, so it’s less jumpy
  • lots of little bugfixes and tweaks I’m forgetting


  • Added Stats module to the readme, and updated the screenshot for Spellbook
  • Made Stats update every 10ms by default to reduce CPU load, with a toggle for operating at sample rate. Again, no special attempts to anti-alias or anything, so probably don’t use it for audio signals.
  • Added a blank panel to learn how to make resizeable panels