Inspiration
Dictation got good. It also got expensive in a way nobody prices: every sentence you speak goes to a server. Your half-formed ideas, your client names, your passwords read aloud by accident. All of it becomes someone else's log line.
We wanted to know whether a dictation tool could be fully local and still be good enough to use every day. Not a demo. The thing you actually reach for when you have an email to write.
What it does
Swar is a macOS dictation app that never sends your voice anywhere.
Hold a key. Speak. Release. The text appears at your cursor in whatever app you were already in: a native text field, a browser, an Electron editor. There is no account, no upload, no network call. Turn on airplane mode and nothing changes.
Everything else is local too. Your history lives in a SQLite file on your own disk. Insights are computed on device. The cleanup that fixes your punctuation runs in Rust on your machine, not in a datacentre.
How we built it
Three layers, with hard boundaries between them.
Flutter owns the interface and nothing else. Rust owns the pipeline: capture, speech detection, recognition, cleanup, storage. Swift owns what only the operating system can do: the global keyboard hook, a non-activating overlay, and text insertion through the Accessibility API. Raw audio never crosses into Dart. A build script fails the CI if presentation code reaches for the bridge directly.
Recognition runs NVIDIA Parakeet TDT v3, quantised to int8 and served through ONNX Runtime in a separate helper process, with whisper.cpp as a fallback. Running it out of process means a model crash cannot take the window down with it.
Cleanup is deterministic Rust, not a language model. Capitalisation, punctuation, filler removal. Rules you can read and test.
Challenges we ran into
The overlay kept stealing focus. A normal window takes key focus when it appears, and the moment it does, the app you wanted to type into is no longer frontmost. It had to become a non activating panel that renders above everything and accepts nothing.
macOS revoked Accessibility permission on every rebuild. Ad hoc code signing derives the app's identity from its executable hash, so every build was a stranger to the system and every build asked for permission again. Fixing it meant pinning a stable designated requirement.
The cleanup model was making things worse. We had a 2 GB local LLM polishing transcripts and we assumed it helped. So we measured it. Of eight real dictations, five were rejected outright by our own validator, and one silently inverted the meaning of a sentence: "the design team, I mean the product team" came back as the opposite. Cold start was over ten seconds. We made it opt in. First run dropped from 2.8 GB to 819 MB.
Hindi and Hinglish did not survive contact with evidence. We built the pipeline, added a code switching model, ran the benchmarks, and the quality was not good enough to put in front of someone. We deleted it. That was the hardest decision in the project and it is the one we would defend hardest.
A genuinely fresh install downloaded nothing at all. We only found it by wiping every model, permission, and settings file off the machine and starting over as a new user. Two separate bugs were stacked: the Rust side loaded the fallback first and gave up when it was missing, and the Dart side returned early before ever asking the engine to prepare. Every test we had passed. Only a clean machine caught it.
Accomplishments that we're proud of
We removed a feature instead of shipping it broken. Hindi support was in the repo, working end to end, and demoable. It was not good enough, so it is gone.
We measured the language model instead of trusting it. Almost nobody does. It failed, and finding that out saved every user two gigabytes and ten seconds per dictation.
The protected token validator. Any text enhancement is checked before it reaches you. If a number changed, a name vanished, a URL moved, or a negation flipped, the result is thrown away and you get the original. Fluent output is not the same as correct output, and dictation is one place where a confident rewrite is worse than no rewrite.
It is genuinely offline. Not "privacy first" as a marketing line. No network code exists in the dictation path.
What we learned
Benchmarks published by a model's own authors are marketing. We only trusted numbers we generated ourselves on our own recordings.
Stale documentation is worse than none. Comments describing deleted code sat in our repo for a day, and a research pass read them, concluded the deleted feature was still live, and designed an entire architecture on top of a subsystem that no longer existed.
The only test that counts is a real machine in a real state. Ours was green while the app was unusable for anyone who was not us.
What's next for Swar
Hindi, done in the right order. Recognition quality first, measured against real speakers, before any translation feature is built on top of it. You cannot translate what you did not hear correctly.
An explicit translate mode, never an automatic one. Detecting Hindi is not consent to convert it to English.
Windows. It compiles today. Compiling is not evidence, so we make no claim until it has run on Windows 10 1809 and current Windows 11.
Categorised insights, so you can see whether you dictate mostly email, mostly code, or mostly messages, resolved on device from the app you were typing into.
Log in or sign up for Devpost to join the conversation.