Introducing Kaleidoscope-MacrosOnTheFly

Plugin name: Kaleidoscope-MacrosOnTheFly
Author: Craig Disselkoen
Source URL:


It’s been discussed briefly in this thread already, but I wanted to start an “official” thread to introduce Kaleidoscope-MacrosOnTheFly, a dynamic-macros plugin for Kaleidoscope. This is the first thread in the new suggested format for the “Plugins” category on this forum; hopefully we eventually see many, many more threads in this category introducing community plugins!

Kaleidoscope-MacrosOnTheFly allows you to record and playback macros on-the-fly. Do any sequence of keystrokes once, then repeat it with the tap of a button. Some possible uses including typing some text over and over; invoking a complicated shortcut several times; or (for programmers like me) making the same modification to several different lines of code. Furthermore, you can have as many different macros stored at once as you have keys on your keyboard, and play back any of them at any time. The possibilities are limited only by your imagination.

The organization and control scheme for MacrosOnTheFly is inspired by the similar feature in Vim - Vim users should feel right at home. This plugin simply takes that functionality and bakes it into your keyboard, so that it works in any application and context wherever you go. That said, using this plugin does not require any Vim knowledge at all - it is fully explained in the README.

MacrosOnTheFly is a third-party plugin, so it is not (at this time) included with a default install of Kaleidoscope. Fortunately, installing additional third-party plugins is pretty easy, regardless of your level of programming experience. Full installation and usage instructions can also be found in the README linked above.

As with all my plugins: suggestions, bug reports, feature requests, and PRs are all very welcome, either on this thread or on the plugin’s GitHub repo. If there’s something that would make MacrosOnTheFly more useful to you, let us know!


This sounds absolutely excellent. I fully expect to use this plugin. (Vim user, use macro recording in vim all the time!)

A couple of suggestions for edits to the readme:

  • It isn’t entirely clear whether there are separate slots for different layers, such as q vs Q. I would assume not, since you said that every key but the play key is its own slot, which would mean shift is a slot too. But then your example of <rec>Qhello<rec> is confusing, since you used an uppercase Q.
  • (Bear in mind I don’t have my Model 01s yet and so this might be obvious once actually installing the plugin…) The readme doesn’t mention any defaults (or suggestions) for Key_MacroRec and Key_MacroPlay.
1 Like

You are absolutely right that that is confusing. I’ll update the docs to use a lowercase q.

At the moment there are not, precisely because (as you guessed) keys like shift and even fn are also slots. One enhancement I’m considering is to change to the other behavior - ShiftToLayer() keys like fn, and maybe even modifiers like shift, would not be slots, in exchange for having q and Q (or even -, _, and |) be all different slots. It’d even be pretty easy to have this be a configurable setting, if some users actually wanted fn, shift, etc to be slots - much like the colors are configurable settings currently.

I’m not entirely sure where the best placements are for those keys. Even if I was sure where I wanted them on my layout, individual users’ layouts are probably different enough that they’ll want different placements of those keys.

I currently have both keys on my Fn layer, despite the known bug indicated in the README. (I use ActiveModColor, and if following a MacroRec or MacroPlay keypress the Fn layer is locked ‘on’, I just tap the key to reset. I hope to actually support MacroRec/MacroPlay on the Fn layer properly in the future.)

That said, we could certainly provide a few suggestions for placing MacroRec and MacroPlay. Candidates I could imagine, that don’t require a layer switch, would be: pgup / pgdn (as in the example .ino sketch); enter (if like me you use Fn-Space for Enter); tab (if like me you’ve remapped it somewhere else); or any of prog, any, or the butterfly key.

1 Like

I’ve updated the README with some of the suggested changes.

I’m even more excited now to get my keyboard, if that is possible, so I can try out this plugin. I agree programmers should find this very useful!

Personally I’d find it more useful to have multiple macros assignable to one letter via modifiers than being able to assign a macro to a key like shift. I know inevitably at some point I’ll have 2, 3, or 4 active macros that all seem best to be mnemonically assigned to the same letter.

1 Like

One enhancement I’m considering is to change to the other behavior - ShiftToLayer() keys like fn, and maybe even modifiers like shift, would not be slots, in exchange for having q and Q (or even -, _, and |) be all different slots.

For what it’s worth, in vim, only registers 0-9, a-z, A-Z, and " can be used for recording macros. (They can be replayed from more registers than that, such as * and +.) 0-9 and " are dangerous because they are overwritten a lot by yanks and deletes and changes. I can’t see them being useful for macros at all (though if you know clever uses for them I’d love to hear!) a-z are useful, and A-Z are the same as a-z except the uppercase versions append the macro to the (lowercase) register rather than replacing it.

I think mimicking the append functionality vim gives with the uppercase registers would be much more valuable than having double the number of registers – I’ve never used more than three or four macros at the same time in my ten years or so heavily using vim.

I’m not entirely sure where the best placements are for those keys. Even if I was sure where I wanted them on my layout, individual users’ layouts are probably different enough that they’ll want different placements of those keys.

I would have thought the “prog” key would be a good default for recording.

I guess I’d probably want record on either “prog” or fn-q, and play on fn-@ (since q and @ are the vim record and play, as I’m sure you know).


I know inevitably at some point I’ll have 2, 3, or 4 active macros that all seem best to be mnemonically assigned to the same letter.

But then how will you remember which modifiers go on each one? I would have thought it’s safer to think up more mnemonics. (I do this anyway since I can only have one macro per alphabetic letter in vim.) Bad things can happen if you run the wrong macro!

It’s just the way my brain works… I can easily remember which ‘R’, “refactor”, “rearrange”, or “replace” is just ‘R’, which is ‘Shift+R’ and which is ‘Alt+R’. But I can’t remember which one(s) is mapped to an alternate letter and why.

I run into this with my IDE shortcuts where I often remap things. Even to the point that I use two shortcut sequences, where the first basically opens up a whole new ‘layer’ of shortcuts, if I run short of modifier comminations for a letter. I have a number of shortcuts on my “second shortcut layer” that I get to via Ctrl+comma. So as strange as it sounds, it’s easier for me to remember “Foo” is Ctrl+comma, then Ctrl+Alt+F then to remember it’s “just” Ctrl+O or some other contrived mnemonic… or that I had to “rename” an action from what I’d normally think of it as in order to find an available mnemonic.

I’m thinking about how this would interact with other plugins — specifically, something that enables the de-coupling of the shifted symbols from unshifted ones. I’m determined to make this happen somehow, even if I have to write my own plugin to do it.

It would be nice if shift could be used to access a different set of macros, just like the other modifiers. While the appending behaviour could be useful, I think it would be better to use shift to increase the size of the space and not introduce artificial restrictions for the sake of vi mimicry.

+1 for the shifted version being append

Seems like we have multiple votes for both shift-is-append, and for shift-gives-a-different-set-of-slots. The one that doesn’t seem to be getting any votes is shift-is-a-slot-itself (the current behavior).

Going forward, I might try to make all three of these options available, configurable with a setting just like the colors are. We’ll see if that seems possible and easy.

1 Like

On the subject of knowing what’s stored in a macro, what do you think about a gesture that “previews” the macro by lighting the keys in macro order?

1 Like

That’s probably a lot trickier to do than you might think. There might not be keys in the current active layer(s) that correspond to the macro, so you’d have to search all the layers to find keys that match, but some of those keys might do context-dependent things, and so on…

1 Like

Thanks for the good point. All the more reason I can’t wait to get my actual hardware :slight_smile:

I can imagine it possibly flashing in one colour any unmodified keys, and in another colour keys which need mods, or something like that. It’s a nice idea but you’re right that it’d be more complex than at first glance. It’d be a great feature, even if it only worked on a subset of macros!

1 Like

For those interested in the shift-gives-a-different-set-of-slots behavior, I’ve added that feature now - please go try it out and give me feedback! It’s available as an option along with the old shift-is-a-slot-itself behavior, but I’ve made shift-gives-a-different-set-of-slots the default as it seems more people will want that.

In fact, not only does Shift give you a second set of slots, but Control gives you a third set, Alt gives you a fourth set, Cmd gives you a fifth set, Shift+Control a sixth set, Control+Alt a seventh set… you get the picture. Layer keys also unlock additional sets of slots.

See the README for more details on usage and how to enable/disable this new option. As always, bugs / feature requests / suggestions are always welcome here or on GitHub.

For those wanting shift-as-append, I plan to implement that as well, I just did this one first. I’ll post another update when there’s news on that front.


Hello there,

I might be 1-4 years late to the party, but I would really like to make use of this plugin with my Atreus. I’ve seen the latest interaction on the repo was in August 2020, so there is hope=)

What do I need to do to make this plugin work with the latest Kaleidoscope bundle (v 1.99.3) on Arduino?

I see these problems:

  • I see that the newer HID facade of Kaleidoscope is implemented in the plugin as part of the latest pull request. (So Kaleidoscope.hid().keyboard().wasModifierKeyActive() in place of kaleidoscope::hid::wasModifierKeyActive())
    Still, there is a faulty import #include <kaleidoscope/hid.h> // wasModifierKeyActive() on line 22 in Kaleidoscope-MacrosOnTheFly\src\Kaleidoscope\MacrosOnTheFly.cpp that makes the sketch compilation fail.
    Removing this import solves this error (although I don’t really know from where the Kaleidoscope.hid().keyboard().wasModifierKeyActive() will be known to the code).

  • Then the next issue is with Kaleidoscope.device().maskKey(key_addr) on line 407 in MacrosOnTheFly.cpp, causing an error with message
    'kaleidoscope::Device {aka class kaleidoscope::device::keyboardio::Atreus}' has no member named 'maskKey'
    What would I need to import/change to make this work?

  • And finally, the last error is with one of the LED functionalities of the plugin, giving error
    C:\Users\bence\AppData\Local\Arduino15\packages\keyboardio\hardware\avr\1.99.3\libraries\Kaleidoscope-MacrosOnTheFly\src\Kaleidoscope\FlashOverride.cpp: In member function 'kaleidoscope::EventHandlerResult kaleidoscope::FlashOverride::afterEachCycle()':
    C:\Users\bence\AppData\Local\Arduino15\packages\keyboardio\hardware\avr\1.99.3\libraries\Kaleidoscope-MacrosOnTheFly\src\Kaleidoscope\FlashOverride.cpp:51:70: error: no matching function for call to 'kaleidoscope::plugin::LEDControl::setCrgbAt(uint8_t&, uint8_t&, cRGB&)::LEDControl.setCrgbAt(flashedLEDRow, flashedLEDCol, flashColor);
    As I don’t have LEDs in the Atreus, I don’t need any related functionalities of the plugin, I just want this part to compile.

Has anyone come across these issues, better yet, solved them somehow? I am not an experienced cpp programmer, nor have knowledge with this level of depth regarding the inner workings of the firmware Kaleidoscope and (3rd party) plugins, so I can only hope someone has some advice for me. Any input is appreciated! =)

Cheers, Bence

Hmm… I’m finally trying to switch full-time to my Keyboardio Atreus, and already have one plugin mostly-working (basically, MagicCombos but eating the original keystrokes with a timeout, so I can, e.g. map A+S to tab.)

I’d also like to have some kind of dynamic macro system; this plugin doesn’t look like exactly what I want, but may be close enough to at least be a useful start.

No promises, but I may take a look in the next week or two at trying to get this plugin working on the current firmware.

That sounds great @edanaher! Let me know if you got anywhere with this. Or if you wrote your own version=)

Also, would it be possible to share your MagicCombo plugin? I also looked around how the original keypresses could be suppressed, but only saw the recommendation on the forum of a workaround involving cross referencing layer shifts with Qukeys and timeouts. I just haven’t started playing with that (plus it would increase the number of necessary layers for me quite a bit).

I haven’t done much more work on this, but it’s working pretty well for me.

I just took the path of least resistance and added the chords to my local plugins directory; my Kaleidoscope config is now on github, with the chord plugin in particular here.

It’s very much in the developer phase; the configuration is right in the plugin, and I’m not sure how exactly it should be set up (e.g., should combos persist across layers). So it’s certainly not ready for general use yet, but if you’re desperate, you might be able to get it working now, and the interest makes it marginally more likely that I’ll polish it up in the near future.

1 Like