"Off" isn't "broken": the small wording choices that make people trust a device
Picture the training desktop asleep in the next room. Until recently, Kestrel's dashboard would tell you it was installing software on it.
Nothing was being installed. The card was confident, specific and wrong, and it was my code. If a status line can mislead the person who wrote it, it can mislead anyone.
That moment changed how I think about the most overlooked part of a product: the one-line messages that tell you what's going on. On a device you can't see inside, they're the whole relationship. A status line is a promise, and every wrong one teaches people to stop reading them.
Kestrel is my nights-and-weekends project, built with Claude as my AI teammate: an open-source Raspberry Pi device for authorized Wi-Fi security research, with a dashboard on your phone and an optional e-ink face. It's unaffiliated with my employer, and the views here are my own.
The card that lied
Kestrel can train its learning agent on a desktop computer over the network. Until version 1.0.12, when the device couldn't reach that desktop, it assumed the desktop's training software wasn't installed yet, and said so:

The fix wasn't clever code. It was asking a better question: when the device can't reach the desktop, what does it actually know? It knows it couldn't connect. It knows when it last could. It knows the last model it received is still good. So that's what it says now, and it keeps that knowledge across restarts, so the card isn't blank after an update either.
Every message answers three questions
That fix turned into a rule for every status in the product:

- What's true right now. "Paused", not "error", when the device is simply waiting for something, and name what it's waiting for.
- Since when. "Last reached 3h ago" tells you whether to worry. A bare "unreachable" doesn't.
- What to do next. "Nothing was changed, safe to retry", or "check diagnostics before retrying". The next step, in words.
- Don't claim more than you know. If a number or a mood implies something, it had better be true.
- Say when a number is rough. Kestrel's anonymous census says "approximate and unverified" right above its totals.
- Never colour alone. Every status is spelled out in words, never just a red or green dot, so it reads the same to everyone.
Here's what that looks like on the phone:

Even the mascot tells the truth
Kestrel has an optional e-ink face, a nod to the little screens on earlier hobby devices like this. It's playful on purpose. It also follows the rule.

The face picks its mood from a fixed order of what matters most: a fault beats a battery problem, which beats a milestone or a fresh capture, which beats everything else. The confident "smart" face shows up only while a trained model is really choosing what the device scans, never while a simple scripted sweep is running. A face that looks smart when nothing smart is happening would be cute and dishonest. We decided it doesn't get to be both.
Honest labels, not just honest messages
Some of the most useful fixes were relabels:
- "Promotions" became "Model contests". The agent page used to count a model trained on the device replacing the old one as a "win", even when nothing had been compared. Version 1.0.11 made every new model win a fair contest first, and the page now shows those real results. The old numbers still appear, honestly labelled "Earlier adoptions".
- The version in the header. For a while the dashboard's header showed a stale internal package number. It now shows the release you're actually running.
- "Unknown" while busy. The environment card once said "Unknown" while the device was capturing perfectly well, because a database it read had fallen behind. The card now reads from a source that keeps up.
Honest about our own testing, too
The rule applies to the process, not just the product. Every beta is checked on a real device by a script that marks each item PASS, FAIL, SKIP or INFO, and only a PASS gets ticked on the public checklist. On the last beta the script passed a check that, it turned out, hadn't tested what the checklist item described, because only one of the two plugins it was about was turned on. It stayed unticked. A pass that didn't test the thing isn't a pass.
One we found while writing this
Writing the companion post on field updates, I found one more. After a power cut interrupts an update, the device correctly rolls back to the previous version at the next boot, and the dashboard correctly says the previous version was restored. But it then adds that "the new version did not come up", which isn't what happened: the power went out. A small thing, the kind that's easy to leave. It's exactly the kind of sentence this post is about, so it's already fixed for the next release: the card now says the update was cut short, the previous version was restored, and it's safe to retry.
For product and engineering leaders
- Treat status text as product, not plumbing. It's often the only interface a connected device has. Review it like you'd review a pricing page.
- Ask "what do we actually know?" Most misleading messages come from code that turns "I don't know" into a confident guess.
- Write the failure messages first. "What does the user see when this goes wrong?" is a design question, not a QA one.
Working with an AI teammate made this cheaper to do well. Checking each message against what the code actually knows, and rewording the ones that guess, is tedious work that usually loses to new features. With an AI teammate it takes minutes, so it gets done.
For investors
Trust in a connected product is built or lost in small moments: the card that says "paused" instead of "error", the update that explains what it restored. Teams that sweat those moments have lower support costs and stickier users, and it shows up long before it shows up in metrics. Ask a team to show you their error messages. You'll learn a lot about how they treat their users.
If posts like this are useful to you, subscribe and the next one lands in your inbox.
What's the most misleading status message you've ever trusted? 🪶
Kestrel is a personal, open-source project built on nights and weekends, unaffiliated with my employer, and for authorized testing only. The user guide and source are public.
Member discussion