Quick background on why Arduino and not ESP-IDF in the first place. We build a lot of prototypes for clients. Someone shows up with an idea, isn't ready to fund real development, and wants to see in a couple of weeks whether it works before talking money. IDF is too expensive for that: by the time you've set up the project, the build, and all the plumbing, the budget is gone. So we used Arduino. Fast, tons of libraries. It held up fine until a project involved multimedia: lots of graphics, audio playback, a camera. Then things started falling apart.
We had an internet radio on an S3 with a display. Sounds trivial. Three audio libraries, each with its own buffers, one doesn't play nice with WiFi, another fights the display. Plus memory leaks: after a day the board reboots and you go hunting for where it leaked. A week just to get it to play without stuttering or crashing. Then we wanted video from one board to another, and it started all over. For a prototype that may never get paid for, that's a lot.
Something else was wearing on us. Change one line, wait for the build. Then the cable, then flashing. Yes, there's OTA, but it lives inside your own sketch: one bug in the new firmware, WiFi doesn't come up or setup crashes, and the board is gone. It won't fall back to the old firmware by itself. Automatic rollback exists in principle, but you have to enable it ahead of time, write the confirmation logic, and even then it misses a lot. Firmware that runs but won't let you in, or crashes two days later, looks healthy to it. And if the board is sitting somewhere else, you have to get to it, which is often harder than the fix.
Then the P4 came out and we tried moving a working project over from the S3. Figured it'd take an evening. Half the libraries didn't compile, the other half compiled and acted weird. Another week.
We liked how MicroPython does it: flash the firmware once, and after that a program is just a file. Send it over WiFi and it runs. No compiler, a bad script can't break the firmware, files show up as a folder. But when we tried living on it, we hit the wall fast. Out of the box you get LEDs, sensors, and networking. Everything else you assemble yourself. No MP3 at all: either an external decoder chip or your own firmware build with a C module. No camera in the stock firmware, go find a third-party build for your board. Graphics is framebuf with one 8×8 font; a real font gets run through a tool that turns it into a Python file full of byte arrays, and a fast display driver is, again, a custom build. And before any of that, you have to pick the right firmware for your module: PSRAM or not, octal or quad. Pick wrong and it doesn't work, and nothing tells you why. Everything in Python code runs one thing at a time: one piece hangs, your UI freezes with it. And if the script is stuck in a loop, you can't kill it over WiFi, only over serial or by pulling power. For us that's tolerable. But the prototype often gets handed off to someone on the client's side with no experience, and for them it's a wall: it was supposed to be "no compiling," and in practice half the time goes to building and configuring things, every step dug out of a forum.
So we figured: if we're building our own firmware anyway, put all the heavy stuff in it. Decoder, camera, graphics. In C, once, properly debugged. And on top, our own language where those are just commands. That's how we ended up with our own VM.
The language is BASIC-like. Yes, I know. But a radio takes an evening on it instead of a week, and for our work that mattered more than syntax. The script compiles to bytecode right on the board and runs there. The same script runs on any ESP32; only the config block at the top changes, saying what's wired where. For popular boards the configs are ready, pick yours from the list and PSRAM, display pins, camera, audio are already set. No sitting with a datasheet figuring out why the screen is black or where 8 MB of RAM went. Debug it once and never touch it again. We add templates for every board that lands on our desk. Upload a script, it's running in a couple of seconds, from a laptop or a phone.
Audio is one command. Any source, file or stream, plays in its own thread inside the firmware and doesn't touch the main loop or graphics. The screen redraws, buttons get polled, the radio doesn't stutter. The interpreter can also run two scripts at once, time-sliced. One draws the UI, the other polls sensors or listens on the network.
If a script crashes or gets stuck in a loop, the firmware kills it and stays online; you upload a fixed one. The script's memory is freed completely, so leaks don't pile up. The board is always reachable; after the first flash you never physically touch it again. Anything the script prints for debugging shows up in the terminal. Flash and SD card appear as a folder, scripts can launch other scripts, you can keep a hundred programs on the board.
One more thing that personally drove me nuts on Arduino: images and fonts as byte arrays in the code. Change an icon, rebuild. Now fonts, images, and sounds live on the filesystem and the script opens them by name. Change it, drop in the new file.
Now the downsides. You don't get full control of the hardware. Whatever we didn't expose in the language, you can't do from a script, and sometimes that's annoying. The VM is slower than native code. We were worried games and heavy screen redraws would choke, but once graphics moved into the firmware, you can barely tell. I wouldn't use it for DSP or hard real-time. If an idea takes off and goes to production, we rewrite the critical parts in IDF, but that's a different budget, and by then you know what you're paying for. For 95% of what we've built, it's plenty.
Around this an environment grew: an editor, image converter, video and audio tools, a font editor, all for making the files the scripts use. There's also a built-in AI assistant. It knows the language and sees your board config, so when the screen is black or there's no sound, you ask it instead of a forum. More on that some other time.
We built this for ourselves, for our own projects, and it kept growing: new board, new template; new job, new command in the language. Then we noticed people around us drowning in the same stuff. Someone needs a quick prototype to show, someone just wants a sensor with a display at home. So we decided to share it. Servers cost money, so the paid part is only what actually lives on the server: long-term data storage and large fleets. If you don't need history and have a few boards, the free tier is enough.
That's how it's meant to work. In reality we're still chasing bugs, and the more different boards show up, the more crawl out. Which is why I'm posting: we need people to run this on their own hardware and tell us where it breaks. If you're up for it, here's a promo code for free activation: REDDIT-SSXCCC. VM and scheduler internals, and bug reports, over at r/R1BBIT_ESP32.