Sep 5, 2026 · vibe-coding · ai-assisted-development · robotics-beginners · prototyping
Vibe Coding a Robot: What Works and What Quietly Breaks
Vibe coding gets a robot moving and holds for behaviour and glue code. What breaks quietly is timing, start-up order and the seams between programs.
Vibe coding gets a robot moving, then quietly breaks at timing and the seams between programs — the parts ROS 2 and HORUS exist to carry. A model is good at behaviour you can describe and poor at what happens between programs when the machine gets busy, because those faults never appear in the chat. That flips if your robot is a single program on one board, where there are no seams. The rest of this post is for somebody with a robot half-working from prompts, who wants to know which half will hold.
The first evening was the best evening. You described what you wanted, and something moved. By the weekend there was a camera, a web page with buttons, and a robot that drove down the hallway and stopped before the wall. It felt like the hard part was over.
Then it got strange in a way that is hard to describe to anybody. The robot is fine for ten minutes and then jerks, once, for no reason you can see. It happens more when the camera window is open. You paste the file into the chat, the assistant apologises and rewrites it, and now there is a different problem, or the same one less often, which is worse. Nobody can tell you why, because there is nobody: it is you, a laptop and a robot that behaves differently on Tuesday than it did on Sunday.
You start noticing you cannot answer simple questions about your own project. Which part runs first when it boots? What happens if the camera is unplugged? The code all looks reasonable. It reads well. And you have no idea what it does when nobody is watching.
Does vibe coding actually work for building a robot?
Yes, for more of a robot than sceptics admit, and it fails in one specific place. Generated code is strong wherever the problem can be described in words and checked by running it once: read this sensor, turn the reading into a distance, drive until the distance is small, put a slider on a web page, save a log. That is a real robot, and people are finishing projects this way who would have given up three years ago. The failure is not in any single file. It appears at the joints — between programs, between the fast thing and the slow thing, between what runs when the machine is quiet and what runs when it is loaded. Those failures never show up in the conversation, because the assistant never sees the machine. It sees your description of the machine, which is the version where the camera never lags and nothing starts in the wrong order. So the split is not smart code versus dumb code. It is code whose correctness you can see versus code whose correctness only appears under load.
What is vibe coding when the code has to move a motor?
Vibe coding is describing what you want in ordinary language and accepting the code that comes back without reading every line of it. On a website, the worst case is an ugly page or a broken button, and you find out immediately because you are looking at it. On a robot, the worst case has mass. A motor command that arrives late is not a cosmetic bug; the arm keeps going for a moment longer than intended, and the thing it was going to stop before is now a thing it has hit. That difference changes which mistakes matter. Sloppy naming and repeated code are almost free on a robot, and nobody should spend a weekend fixing them. Anything to do with time is expensive: what happens first, what waits for what, what happens when a message does not arrive, what happens when the computer is busy elsewhere. A model writes both kinds with the same confidence, and the second kind looks exactly as convincing on the screen as the first.
What are you actually choosing between when you generate robot code?
You are choosing what your generated code sits on, and there are six realistic answers. You can put it on top of ROS 2 and inherit drivers, maps, navigation and a decade of packages, which models have read a great deal of. You can put it on a narrow real-time layer such as HORUS, an open-source real-time robotics middleware for Rust, Python and C++ where the three languages share the same shared-memory ring buffers, so messages between processes on one computer are not serialised; it is Apache-2.0, validated in simulation rather than fielded at scale, and not a full ROS replacement, so it suits a robot that is a few programs on one box rather than one that needs a map. You can write straight to a vendor's kit library and stay inside what the kit anticipated, generate everything as one program with no framework at all, put the parts that must never be late on a microcontroller and let generated code live above them, or buy a whole platform and write only the application.
How do the approaches compare once the robot runs unattended?
Read the last column first and eliminate every row that describes your situation. Two rows usually remain, and the tiebreaker is which you could still debug on a bad evening when the robot does something you did not expect.
| Option | Who it is for | What it assumes you know | When to pick it | When not to |
|---|---|---|---|---|
| Generated code above ROS 2 | Builders needing parts that already exist | How to read a launch file and a topic list | The robot needs maps and drivers | Your whole problem is a loop on one computer |
| Generated code above HORUS | Robots that are a few programs on one computer | Which programs you have and what each sends | Motion stutters when the machine is busy | You need navigation and a map today |
| Generated code on a kit library | Classroom hardware and hobby kits | The kit's own vocabulary | The robot is the kit and stays so | You are adding a camera and a second computer |
| One generated program, no framework | Small robots with one job | Basic Python or C++ and your hardware | The whole robot fits in one loop | Two things run at different rates |
| Microcontroller below, generated code above | Anything with motors that must not lurch | Where the dangerous part must live | Limits and stops matter | There is no microcontroller in the design |
| Generated prototype, rewritten by hand later | Founders proving a concept before hiring | What in the prototype was a guess | The demo decides whether the project exists | The prototype is already at a customer site |
The rows are not ranked. A hobby kit robot picking the top row is doing needless work; a delivery robot picking the fourth is postponing a rewrite it already earned.
Are you a hobbyist, a founder with a demo date, or an engineer inside a company?
The same generated code is a good idea for one of these and a poor idea for another. A hobbyist should vibe code freely, because the cost of a mistake is a robot that drives into a table leg and a story to tell about it, and because finishing things is how anybody learns this. A founder with a demo date should vibe code the demo and stay honest that the demo is a sketch; the danger is not the code, it is telling an investor the hard part is done because the video looked convincing. An engineer inside a company has a different constraint: somebody will maintain this after you, and "the assistant produced it" is not an answer that survives a safety review. That does not mean generating nothing. It means marking which parts were generated, keeping the prompt history, and making sure one human can explain every part that moves something heavy. The rule across all three: the more the robot can hurt, the more you must be able to explain.
What hardware are you doing this on, and does it change the answer?
It changes the answer more than the software choice does. On a hobby microcontroller board, one program runs one loop, there are no seams, and vibe coding survives nearly anything — the model's code is the whole system, and if the loop keeps up the robot behaves. On a single-board Linux computer, where most projects go next, several programs share one machine and everything in this post about seams starts applying. That is the transition where projects get confusing, and almost nobody notices crossing it. On a laptop plus a separate controller board, the parts that must not be late already live elsewhere, so generated code on the laptop can be as leisurely as it likes. And on the cheap board chosen to save money, code that only fitted comfortably on a generous machine starts missing its moments. If you are about to move from a microcontroller to Linux, expect the character of your bugs to change from wrong to intermittent, and plan for that rather than being surprised by it.
What if the demo is in three weeks?
Generate everything, ship the demo, and write down what you are pretending. Three weeks is not enough to learn a framework, restructure a program and rehearse a demo, and choosing a foundation for reasons you cannot yet explain is how people spend two of the three weeks reading documentation. So: keep it in one program if it is already one program, run the demo on the machine you tested on, and rehearse end to end at least twice, because the failures that ruin demos are start-up failures rather than logic failures. Then write the honest list — the parts you do not understand, the parts that only work when the log window is closed, the thing you fixed by adding a pause — and keep it where you will find it after the demo. That list is worth more than the code, because it is the specification for whatever comes next. Teams who lose it rebuild the same robot twice, and the second version fails the same way for reasons nobody wrote down. This is also the fork where projects stall after the prototype.
How much do you need to understand of what the model wrote?
Enough to answer three questions about any part that can move the robot: what runs it, what it waits for, and what it does when the thing it waits for never arrives. You do not need every line, and pretending otherwise is why people give up. You do need to draw your robot on paper as boxes and arrows — this program reads the camera, that one drives the wheels, this arrow is the command between them — and say which arrow must never be late. Most people cannot do this for their own robot, and it is the most useful hour they could spend. Once the drawing exists, the assistant becomes more useful rather than less, because you can ask precise questions: what happens to this arrow if the camera program is slow, or if it dies. Vague prompts get confident answers. Prompts containing your actual structure get answers you can check. The drawing is what turns generated code from a black box into something you are directing.
What do you give up by letting a model write the robot?
You give up knowing where the weak points are, which is different from having weak points. Every codebase has them; normally the person who wrote it has a feeling about which parts are held together with tape. Generated code arrives with the tape invisible, uniformly confident in tone, so a piece that was written carefully and a piece that was guessed at look identical. You also give up the search that teaches you the field. Someone who spent a frustrating weekend learning why sensor readings jump around knows something permanent about sensors; someone who got a working filter in one prompt has a filter and no intuition, until the day it stops working. And you give up an easy conversation with collaborators, because the honest answer to "why is it done this way" is sometimes that nobody chose. None of this is an argument against generating code. It is an argument for spending the time you saved on understanding the shape of your robot rather than on adding more features to it.
When is ROS 2 the better choice?
ROS 2 is the better choice as soon as your robot needs things other people have already built, and that is most robots that leave a desk. If you want it to map a room and find its way back across it, that problem has consumed careers, and no amount of prompting produces a substitute in an evening. If your sensor has exactly one maintained driver and that driver is a package, the decision is made. If you want to record everything the robot did and replay it later, that tooling exists and is hard to reproduce. If you want to ask other people for help, the vocabulary is shared, and an assistant has read a great deal of code written in it, which makes generated code better rather than worse. HORUS is not the answer in those cases, and choosing it there trades a large ecosystem for plumbing you would then own alone. The narrow case where a smaller layer wins is a robot that is a handful of programs on one computer, where the problem is timing rather than missing parts.
Is vibe-coded robot code simply bad code?
No, and here is why: the quality distribution overlaps heavily with what humans write under deadline, and the failures are not the ones people expect. Generated code is often tidier than a rushed human's, with more error handling and better comments than most weekend projects ever get. What it lacks is not craft but context. The model has never seen your robot lurch, never watched a queue fill while a laptop compiled something in the background, never had a motor controller drop off the bus at the worst moment. So it writes the version of your program that works in the world it was described in, and that version is genuinely correct there. The gap is between that world and yours, which contains a warm computer, a loose connector and a camera that occasionally takes longer than usual. Judge generated code by whether anyone can explain what it does when things go wrong, and apply the same test to hand-written code. Plenty of that fails too. The problem was never authorship.
Will a better model fix the parts that break?
Partly, but not the way you think. Models keep getting better at exactly the things they were already good at: more correct code per prompt, longer programs held together, fewer invented functions, better guesses about what you meant. None of that touches the actual gap, which is that the model cannot observe your machine. It does not know that your camera driver occasionally takes longer than everything else, that your log writing lands on a slow memory card, or that your robot boots with the network absent. Those facts live in your building. A model can only receive them if you notice them and type them out, which returns the problem to you understanding your own robot. What genuinely improves is the middle ground, where an assistant reads your logs, spots a pattern you missed and asks a better question than you would have. That is worth a lot, and it is assistance rather than replacement — a difference that matters most where the robot can hurt something.
What does it look like when a vibe-coded robot breaks quietly?
It looks like four specific afternoons, and none of them look like a crash. The first is the stutter under load: the robot is fine until the camera window is open or a file is copying, and then motion arrives in jerks — the classic symptom of everything sharing one program and taking turns. The second is the start-up race: it works when you launch things by hand in your usual order, and fails after a power cut when the camera enumerates late and something waits forever for a message that never comes. The third is the growing lag: the robot responds a little later as the minutes pass, because something is queueing faster than it is read, and the only cure anyone finds is a restart. The fourth is the fix that hides the fault: somebody adds a pause, the symptom goes, and the race waits for a colder morning. All four are ordinary, all four are fixable, and none are visible in the code on the screen. Why the same robot behaves differently every run covers the mechanics.
How do you decide what to generate and what to choose deliberately?
Split your robot into things that must happen on rhythm and things that can take as long as they take, then generate freely on the second list and think hard about the first. Driving the wheels, holding the arm, reacting to a limit switch: rhythm. Recognising an object, planning a route, drawing a dashboard: as long as they take. Most confusion in a vibe-coded robot comes from those two lists living in one program, where the slow thing delays the fast one and nobody sees it happen. Once they are separate programs, what carries data between them becomes a real decision with a small number of answers, and this whole post turns into a choice rather than a mystery. Do the split on paper, before changing any code. And if you intend to sell the thing, what open source is safe to ship commercially is the next question waiting, and it is easier to answer when somebody can explain what is on the machine.
Decide by where you actually are:
- If you are learning and the robot is a toy -> generate everything, because finishing projects is how the intuition arrives.
- If the demo is close and the robot only has to work once -> generate everything, then write down what you are pretending, because that list is the real specification.
- If the robot needs maps, drivers or navigation -> the large ecosystem, because those parts took other people years.
- If motion stutters whenever the machine is busy -> split the fast part from the slow part first, because no framework rescues one program doing both.
- If something heavy moves near a person -> put that part on a microcontroller and understand it yourself, because somebody must be able to explain what stops the machine.
When two of those lines describe you, weigh the options on the five axes of the HORUS Fit Framework — ecosystem size, setup effort, team size fit, deployment target, licence — and keep whichever loses on fewer. No scores: they are questions about your project rather than about software. And if your robot keeps turning into several programs on one computer, in more than one language, with a loop you can see stutter, star HORUS on GitHub so it is in your list when you start building.