At its core, it's a terminal designed for microcontrollers. But let me tell you how it all started…
Back in 2013, during technical high school, I wanted to upgrade one of my RC cars as a home hobby project. The goal was to make simple automations, like following a red ball, stopping before hitting a wall, or moving a set distance forward. This was the first time I got interested in remote control and diagnostics. Around this time, I also discovered the Arduino ecosystem.
After school, our math teacher held programming sessions, and over two years, I managed to put together something that actually worked! At the time, I was super proud of it. The system understood about 10 commands, was a bit buggy, but it really motivated me to dive deeper into the topic.
In 2015, during my final year in technical high school, I had a project to redesign the control system of a disco light. This thing had four stepper motors, a few relays, and an RS-232 interface. Unfortunately, its mainboard died, and my task was to build a new one and control it via RS-232.
I spent a few months designing the hardware, which was relatively straightforward. But when it came to software, I figured:
Hey, I’ll just write it in C, so I could easily add a command line interface to it. It’ll be a piece of cake!
(Since, before that, we had to do everything in assembly, C felt like a luxury.)
Like any good programmer, the first thing I did was search for an existing Arduino library.
But to my surprise, there were no proper solutions for adding a terminal to a microcontroller.
I checked forums and quickly realized:
💡 Nobody really puts a command-line interface on microcontrollers!
Instead, most people just reflash their firmware every time they need to make a change.
💡 I thought making this easier to use would also be easy to implement.
Spoiler alert: I couldn’t have been more wrong. 😅
Building a maintainable command processor turned out to be way harder than I expected.
At first, my command parser was just a giant else-if chain. But hey—it worked!
The project was completed, and while I was proud of the hardware, the software felt... clunky.
I decided to fix this by creating a portable terminal interface—one that was interactive, had command history, supported deletion, and could be formatted properly.
For two years, I studied how terminal interfaces worked. After many prototypes, I finally had a system that supported:
But… the command processor still sucked. It wasn’t flexible enough.
When I got to university, I finally learned about function pointers in C and C++. At first, they seemed exotic, but since I had assembly experience, I quickly realized they were actually pretty familiar.
This was also when I had a realization:
💡 I don’t just need a terminal—I need a proper command processor with a configurable command-database too!
But the command processor turned out to be a much bigger challenge than I expected. So, I had to split the project into two:
For about 1.5 years, I put Shellminator on hold and focused entirely on Commander. My goal?
⚡ Make it fast and resource-efficient ⚡
At one point, Commander even had recursion and dynamic memory allocation (yes, I know—that’s a crime on AVR and any other microcontrollers). But once initialized, it ran efficiently and could find commands in log₂N steps.
Eventually, I built a working interface between Commander and Shellminator, and I happily used them for all my university projects—including my thesis, where I designed a cocktail-making machine.
I was already working in a small prototype development offices alongside my studies in the second half of university. Since I didn’t had much work experience back then, getting into a larger company wasn’t really an option, so I started working at smaller companies instead. There was even one semester when I had two jobs at the same time, which gave me a pretty good overview of how local small businesses develop automated systems. I was shocked to see that nothing had changed in the world of microcontroller terminals.
Everywhere I went, I saw engineers avoiding interactive interfaces. In most cases, these systems weren’t even capable of any real-time diagnostics.
Occasionally, some solutions had logs generated via printf, which was at least somewhat useful. However, these logs had no structure whatsoever,
meaning you had to sift through an overwhelming amount of data to find the relevant information (if it was logged at all).
I don’t mean to offend anyone, but my personal experience was:
For example, one industrial machine I worked on had a motor speed command like this:
x1 10
where x
means motor (obviously), 1
means motor ID (obviously), 10
means speed (of course not in RPM...)
Now, what happens if the operator accidentally types a wrong key?
💀 Because no delete, backspace and cursor handling, the system executes the broken command anyway! And the only way to recover?
Restarting the microcontroller—which isn’t exactly an option if the device is in motion.
Let’s just say I’ve seen more than one motor burn out because of this... 😬
I even worked on a 5m-high machine with no built-in diagnostics. Every time something failed, we had to climb up with a laptop just to check what went wrong. One day, I spent more time on a ladder than writing code. That was my breaking point.
So I told my boss: I have a solution. It’s not perfect, but it’s way better than this.
Due to the project's state and the tight deadlines, we quickly came to an agreement:
The company, where I worked at the time, can use my libraries( they were on GitHub with MIT license anyway )
and I get some feedback about how it works, and more importantly, how it broke.
For legal reasons, I wasn’t allowed to develop either library during work hours—but I didn’t mind.
At that stage, I needed real-world tests, the kind you can only get out in the field.
And guess what? It worked great! 🚀 We used Shellminator + Commander to build tons of prototypes and mini-projects. I got the test results I needed, and my boss was able to sell the prototypes quickly— which was essential for the company’s business.
This was when my colleagues started contributing. At first, they just reported bugs, then they started requesting features.
Eventually, my hobbyist co-workers told me:
Dude, you need to publish these libraries! I want to use them at home too!
Then I told them:
Hey, I already done that years ago! Have you tried to search for it?
That’s when I realized:
💡 Maybe I actually found an open-source niche that matters!
Even though the project was already on GitHub, nobody really found it. (No surprise—I suck at marketing 😅).
So, I decided to make it Arduino-compatible to attract more developers. And guess what?
📢 The internet finally noticed!
People started using it, reporting bugs, and sending feedback.
And finally, here we are at the V3 release! 🎉
I just want to say a huge THANK YOU to everyone who has helped bring this project to where it is today.
To everyone who contributed bug fixes, feedback, ideas, and documentation—I truly appreciate it.
So… what’s next? Well, let’s keep pushing forward and see how far we can take this—together! 🚀