· 8 min read 🍿

Three Hours, No Cloud

Three Hours, No Cloud

I named our robot Mycroft, after Sherlock’s smarter brother. The speech recogniser that serves as its ears has never met that word. So when I asked, “Hey Mycroft, what’s the capital of France?”, it wrote down “In Minecraft, what’s the capital of France?” and the robot politely explained that it doesn’t know much about Minecraft geography.

Most of what I now believe about home robotics is inside that one failure. The components are astonishingly good. The gaps between them are subtle. And nothing raises an error when the system is confidently wrong.

Attaching Mycroft's head at the desk: the robot upright, eyes level, mid-assembly

Why I bought one at all

I had been sceptical of consumer robots for years because the interesting part always turned out to be someone else’s server. The robot was a shell, the intelligence was a subscription. A reasonable business model, a bad deal for the buyer, and a non-starter with children in the house.

Two things changed my mind about Reachy Mini, and neither was the robot. Hugging Face published a guide for running the entire voice pipeline locally, and Google published benchmarks for Gemma on hardware I already owned. Two organisations with no reason to coordinate, both saying the same thing: this runs on a desk now.

Build time ~3 hrs · Reply latency 1–2 s · Cloud calls 0

The build is the easy part

Be clear about what arrives in the box: this is a kit, not a product you unwrap. Bare circuit boards you handle by the edges, motors, unattached wiring harnesses, a bag of screws, and shell halves. You plug every connector, route every cable, and torque every joint yourself. Three hours, no soldering, not quite IKEA-simple. The fiddly bits are the two the documentation warns about: cable routing and torque. The motor wiring daisy-chains up through the neck, so a cable with too little slack becomes a problem you discover much later, when the head stops moving. There are spare screws in the box, on purpose.

What the spec sheet cannot convey is the personality. It whistles on waking. It has eighty-one animated expressions and two antennae that serve no function and carry most of the emotional weight. When it mishears something it says “oops, quick system hiccup.” None of that is scripted; it is a small model with a personality prompt, and the effect on visiting children is total.

The Reachy Mini kit mid-build: parts, manual, shell halves and toolkit laid out in a circle on the carpet

Small models got good while I wasn’t looking

The robot itself is a Raspberry Pi. Plenty for motors, camera and microphones, nowhere near enough for a language model. It streams audio to a Mac mini on a shelf, which does the thinking and streams speech back. The plumbing is unremarkable and the details are at the end.

Here is the part worth sitting with: every model in this robot is open source. The wake word, the speech recogniser, the language model, the voice — open weights from four different labs, downloaded free, no API key anywhere in the house. A complete conversational machine assembled from parts anyone can have.

The language model is what surprised me most. I assumed a four-billion-parameter model would be a toy: passable at chat, hopeless at anything structured. That assumption was about a year out of date. Gemma holds a conversation at thirty tokens per second, comfortably faster than speech, and it does reliable tool calling. It has fourteen tools and picks correctly without coaching. When I asked what it could see, it worked out that it needed to look, called the camera with a well-formed question, took one frame, and reasoned about the image. Two years ago that was a frontier-model demo with a bill attached. It now runs on a desk, for nothing.

It is not uniformly good, and the failures are instructive. It can be trusted to choose the right tool. It cannot be trusted to obey a hard behavioural rule that conflicts with being helpful. My wake-word gate works because it sits in code, before the model is ever consulted. Every attempt to achieve the same thing with instructions failed.

Everything is swappable, and that is the trap

The pipeline is modular, which sounds like a feature and turns out to be a responsibility. I started with Whisper for speech recognition because I knew the name. The documentation recommended Parakeet. The swap took one flag and made transcription about fifteen times faster. It also taught the sharpest lesson of the build: Whisper transcribes a whole buffer at once, Parakeet streams, and a live-transcription setting that defaults to on (because the default recogniser streams) quietly produced garbled text with Whisper underneath it. The component was fine. The default around it assumed a system I had already replaced.

The voice output told the same story. I tried a different speech engine and the app validated my voice choice against nine hard-coded names, found no match, and silently fell back to its stock voice. No error, no warning. I spent a while convinced the swap had worked and the engine simply sounded like that.

Defaults encode assumptions about a system you may have already replaced. Nothing errors. It just gets subtly, expensively wrong.

Then it broke after five minutes

The demo was flawless. Real family use was not: fine at first, glitchy after five minutes, eventually unresponsive. It felt random, which is exactly why it took an evening to find. The cause was accumulation. Past a threshold, the robot summarises old conversation in the background to keep its memory bounded, and that background job had a timeout tuned for faster hardware. Each failure left the history a little longer, which made the next attempt slower and more certain to fail. Every failure guaranteed the next one.

Nothing in a ten-minute demo can surface a bug like that. The demo ends at turn twelve. Family life starts there, and the fix was only provable by measurement. Over an evening of chat the robot’s working memory climbed from 3,460 tokens to 3,878 across twelve turns, the summariser folded it back to 3,637, and the cycle repeated. A healthy conversational memory looks like a sawtooth. Ours used to look like a staircase.

Working memory per conversational turn · tokens, from the logs
after the fix   before
3,500 3,750 4,000 conversation turns → 3,460 3,878 3,637 kept climbing to 6,067 →

What I learned

  • Whatever you believe about small open-source models, it is probably stale. Mine was wrong by a year. Reliable tool calling from free, open weights changes what is worth building at home and at work.
  • The gap between demo and daily use is where all the time goes. Every component worked first time in isolation. The evenings went on integration, defaults, and failures that only appear after turn twelve.
  • Privacy flipped from constraint to enabler. My children talk to this thing because nothing they say leaves the building. That was not a compliance decision. It is the reason it is allowed in the house.
  • Do the arithmetic before believing the viral demo. A clip of this robot running its brain fully onboard did the rounds recently. Impressive, and the demo’s own numbers show it generating at a quarter of the speed of the machine already sitting on my shelf. Cool is not a reason to move a workload.

The roadmap is being set by the household. My eldest son has already asked it to turn off the lights, and it told him it checks with me first. Home control is next, as a tool the model can call rather than a mode that takes it over. After that, we’ll see what the family asks it for. That is a strange and pleasing way to run a product backlog.


The stack, for anyone building one: Reachy Mini Wireless streaming audio to a Mac mini over the LAN. On the Mac: openWakeWord (“Hey Mycroft”), Silero VAD, Parakeet-TDT for speech recognition, Gemma 4 E4B on llama.cpp, Qwen3-TTS for the voice. Fully local, no cloud calls at runtime. Reply latency runs 1–2 seconds once warm. Where a 1.9-second reply actually goes: 0.09s deciding you have finished speaking, 0.24s transcription, 0.95s thinking, 0.74s to the first spoken word.

Comments