Linux is great at a lot of things. Voice typing has not been one of them.
On Windows and macOS you get system dictation that works in basically any app. On Linux you get cloud services, research scripts, and CLI tools that only make sense if you already know how speech stacks fit together. I wanted something closer to: press a shortcut, talk, text appears. Prefer offline. Free. Not tied to one distro.
That is Vocalinux. GPLv3 tray app. System-wide speech-to-text on X11 and Wayland. Default engine is whisper.cpp running on your machine. You can also pick OpenAI Whisper, VOSK, or a Remote API engine that talks to your own HTTP STT server (OpenAI-compatible or whisper.cpp's server). Core path needs no account and does not send audio to a random SaaS.
This is the story and the technical path, not a feature dump.
The gap
I kept tripping over the same three constraints:
- Privacy. Mic audio is sensitive. Cloud STT is a non-starter for a lot of people (and a lot of workplaces).
- Daily use. A tool that only works as a terminal demo is not dictation.
- Linux realities. X11 and Wayland are different. GNOME and KDE are different. Text injection is harder than "call the API and print a string."
Pieces of the puzzle already existed. whisper.cpp made local Whisper models practical. VOSK was light enough for older boxes. Projects like nerd-dictation showed people wanted FOSS options. What I did not find was a multi-engine tray app that treated Wayland as a real problem, stayed offline by default, and still let power users point at a home-lab GPU when they wanted to.
So I started building one.
A short timeline
Numbers as of mid-2026. The project is still beta on purpose.
| When | What |
|---|---|
| Early 2025 | Design and early work around offline Linux dictation |
| April 2025 | Public GitHub repo: jatinkrmalik/vocalinux |
| Late 2025 | First tagged alphas (e.g. v0.2.0-alpha). Installer and engine choices start to harden |
| Early 2026 | Alpha into beta (v0.5.0-beta and friends). Site at vocalinux.com. Multi-language work |
| Through 2026 | Wayland/IBus reliability, settings UX, model selection, remote HTTP STT, nightlies |
| July 2026 |
v0.14.0-beta: custom modifier+key hotkeys, FunASR/SenseVoice over remote OpenAI-compatible APIs, more Wayland fixes, smarter whisper.cpp thread defaults on hybrid CPUs |
Still beta because desktop Linux dictation has a long tail of compositor and input-method bugs.
What Vocalinux actually is
In practice:
- Tray app with clear listening / processing state
- Toggle or push-to-talk
- Configurable shortcuts (presets, or any Ctrl/Alt/Shift/Super + key combo)
- Four engine paths: whisper.cpp (default, local), OpenAI Whisper (local PyTorch), VOSK (local, light), and Remote API (HTTP to a server you control)
- Vulkan GPU for whisper.cpp when available (AMD, Intel, NVIDIA)
- One interactive installer that peeks at hardware and suggests an engine
curl -fsSL raw.githubusercontent.com/jatinkrmalik/vocalinux/main/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh
First install is usually a couple of minutes with the default tiny whisper.cpp model. Bigger models cost RAM and latency for accuracy.
Stack: Python 3.9+, GTK 3 (PyGObject), the speech backends above, then a lot of stubborn work on audio capture and text injection.
Remote API (the fourth engine)
Local models are the default story. Remote is the escape hatch when your laptop is weak, you already run a Whisper box on the LAN, or you want one GPU server shared by a few machines.
How it works when Remote API is selected:
- Vocalinux still captures mic audio on the laptop (16 kHz mono PCM).
- Local VAD / end-of-utterance decides when a phrase is done.
- The buffer is packed as WAV in memory (not written to disk) and uploaded over HTTP.
- The server returns text; Vocalinux injects it into the focused window.
Two wire formats out of the box (docs: HTTP remote transcription):
| Format | Endpoint idea | Examples |
|---|---|---|
| OpenAI-compatible | POST /v1/audio/transcriptions |
Speaches, LocalAI, FunASR/SenseVoice servers, or a self-hosted stack that mimics OpenAI's audio API |
| whisper.cpp server | POST /inference |
The HTTP server binary from whisper.cpp |
You are not locked into OpenAI's cloud. Point the base URL at http://your-lab:8000 (or whatever you run). As of v0.14.0-beta, OpenAI-compatible remote mode also understands FunASR/SenseVoice-style model names (e.g. sensevoice) and cleans SenseVoice metadata labels before injection.
Same self-hosted server can back other clients on the network (phones, other desktops) if they speak the same API. Audio goes to your box, not a random vendor, unless you deliberately configure a public endpoint.
Remote does not replace offline mode. It is for people who want the tray UX on a thin client and the heavy ASR somewhere else they trust.
The hard parts
1. Recognition is only half the product
Getting a transcript string is easy. Users live in browsers, IDEs, chat, LibreOffice, terminals. The product is "text landed where the caret is," not "something printed on stdout."
That means:
- Clipboard and paste paths when injection fails
- IBus and input method restore on GNOME/KDE Wayland
- Modifier keys still held when injection starts (fires shortcuts, garbles input)
- Audio device indices that change between sessions
A lot of recent releases are those bugs, not new models. That is the right bias for desktop software.
2. Wayland is not "X11 but newer"
On X11 you could fake more with older tools. Wayland is stricter and more compositor-specific. Vocalinux spends time on injection paths for modern GNOME and Plasma, then spends more time fixing regressions when detection or engines move.
If you only test one DE, you ship "works on my machine" and break on the next Reddit thread.
3. Engine choice is a product feature
There is no single STT stack that wins for everyone:
| Engine | Role |
|---|---|
| whisper.cpp | Default local path. Good speed/quality tradeoff, Vulkan-friendly, avoids PyTorch for many users |
| OpenAI Whisper | Local PyTorch path; NVIDIA-oriented GPU story |
| VOSK | Lighter local footprint on older hardware |
| Remote API | Offload ASR to whisper.cpp server or any OpenAI-compatible STT (Speaches, LocalAI, FunASR/SenseVoice, etc.) while VAD stays local |
The installer recommends something sane from RAM, GPU, and Vulkan. Settings keep model selection per engine so switching does not wipe preferences. Remote is configured with server URL, endpoint style, and model name when the server needs one.
4. Offline-first is a constraint, not a slogan
Offline means:
- Models download once and run locally for the three local engines
- No account for core dictation
- Remote API is optional and explicit: you choose the host
Air-gapped and flaky-network laptops care about the first path. Homelab people care about the second. Both are valid; the default still does not require a network.
5. UX details show up before fancy models do
People notice tray icons, short audio cues, whether push-to-talk matches muscle memory, whether a pause between phrases inserts a space instead of gluing words, and whether hybrid CPUs cook because the STT library grabbed every core.
v0.14.0-beta is full of that kind of work: hotkeys, hybrid-CPU thread defaults, Wayland/IBus reliability, remote SenseVoice cleanup. Unsexy. Necessary.
Who it is for
Linux desktop users who want dictation without defaulting to cloud STT. People reducing keyboard load (RSI, accessibility, long writing sessions). Devs who live in terminals and editors but still want system-wide capture. Privacy-minded folks who want GPLv3 code they can read. Homelab users who already run Whisper (or FunASR) on a box and want a proper Linux client in front of it.
It is not a commercial Dragon replacement with a sales team. It is a community desktop app that should be good enough to leave running every morning.
What I would do differently (and what I would not)
I would not drop the offline default, the multi-engine design (including remote), or Wayland injection as core work.
I would start earlier on packaging (Flatpak, AUR, and friends) as a real channel, not only the install script. More automated DE matrix testing for injection. Clearer "what works where" docs from day one. Remote setup could use more opinionated presets for common servers so people do not have to read endpoint docs on a bad day.
Still open: broader packages, a better docs hub, and the endless DE/compositor bugs that only show up when real keyboards and layouts hit the wild.
Try it, break it, file issues
- Site: https://vocalinux.com/
- Source: https://github.com/jatinkrmalik/vocalinux
- Remote HTTP setup: docs/HTTP_REMOTE.md
- Changelog: https://vocalinux.com/changelog/
- Compare / alternatives: https://vocalinux.com/compare/
If you try it on a weird Wayland setup, open an issue with distro, DE, and whether injection or recognition failed. Same for remote: say which server software and endpoint style you used. Those reports are how the history above got written.
I am still shipping betas on purpose. Desktop dictation on Linux only gets good if people use it in the wild and we keep fixing what they hit.
Disclaimer: I am the maintainer of Vocalinux. Feedback welcome on GitHub issues/discussions.
Top comments (1)
"Recognition is only half the product" — I can confirm this law holds on Windows too, from the least likely demographic: I'm a physical therapist who builds internal tools for my hospital with AI, and I built a little push-to-talk dictation tool for our staff (hold a key, speak, local Whisper transcribes on a modest GPU).
The model took me an afternoon. Everything you listed took the rest: global key hooks, audio devices reshuffling between sessions, and above all injection. I eventually surrendered on true injection entirely — my tool writes to the clipboard and pastes, precisely because making text land correctly inside a browser field vs a terminal vs a legacy medical program was a compatibility swamp I couldn't drain alone. Reading your Wayland/IBus/compositor matrix, I feel simultaneously validated and grateful: you drained the swamp; I built a bridge over mine and called it a feature.
One observation from the deployment side that might interest you: for my users (hospital staff, mostly non-technical, dictating in Korean), the make-or-break wasn't accuracy — the local model was already good enough — it was trust in where the audio goes. "It never leaves the building" did more for adoption than any WER number. Offline-first isn't just an architecture choice; for some workplaces it's the entire permission to exist.
Shipping betas on purpose is the right call. Tools like this only meet their real edge cases in the wild.