A Siri-like voice assistant for the Linux desktop. Press a hotkey, speak, and a local LLM turns your words into actions — open apps, set the volume, lock the screen, control media, set timers. Fully offline: whisper.cpp and llama.cpp are embedded — no ollama, no server.
See PLAN.md for the design, model evaluation strategy, and the build gotchas discovered along the way.
scripts/install.sh # CPU build
scripts/install.sh cuda # GPU build (needs the CUDA toolkit / nvcc)This:
- builds and installs
verad,vera,vera-stt,vera-evalto~/.local/bin - registers D-Bus activation (the daemon auto-starts on first use)
- runs
vera setup, which binds Super+Space tovera toggleand adds a login autostart entry so the daemon (and models) preload at login (hotkey override:VERA_HOTKEY='<Ctrl><Alt>space' scripts/install.sh; skip autostart withvera setup --no-autostartafterwards)
The overlay is placed by the compositor — Wayland apps can't position their own windows.
scripts/package-deb.sh # or: scripts/package-deb.sh cuda
sudo apt install ./target/deb/vera_*.deb
vera setup # per-user: hotkey, autostartThen download the models once:
vera models download whisper-base.en
vera models download qwen3-1.7b
vera models list # see all candidates + download status- Voice: press
Super+Space, speak, stop talking.Esc(or the hotkey again) cancels. The first command after daemon start loads the models (a few seconds); after that it's warm. - Conversation: the overlay stays open — after every answer or action the
mic reopens for ~4 s, so you can chain commands ("open firefox" → "volume to
30" → "thanks, that's all"). It closes when you say goodbye ("that's all",
"never mind", "bye"), stay silent, or press Esc. Configure with
conversation_mode/followup_timeout_ms. - Text (also handy for testing):
vera run "set volume to 40 percent" - Stop the daemon:
vera quit(it auto-starts again on next use)
cargo build && cargo test
# terminal 1: daemon with logs
RUST_LOG=info ./target/debug/verad
# terminal 2:
./target/debug/vera run "open firefox" # text command
./target/debug/vera toggle # voice sessionThe daemon log prints each stage: capture device, transcript, chosen tool call.
~/.config/vera/config.toml (created with defaults on first run):
| Key | Default | Meaning |
|---|---|---|
stt_model |
whisper-base.en |
registry name or absolute path to a ggml whisper model |
llm_model |
qwen3-1.7b |
registry name or absolute path to a GGUF |
device |
auto |
auto / cpu / cuda (cuda needs the cuda build) |
endpoint_silence_ms |
800 | trailing silence that ends an utterance |
leading_silence_timeout_ms |
6000 | give up if you never speak |
max_utterance_ms |
15000 | hard cap per utterance |
result_linger_ms |
4000 | how long results stay on screen |
language |
en |
whisper language hint, auto to detect |
temperature |
0.2 | LLM sampling temperature |
Restart the daemon (vera quit) after editing.
Open apps and URLs, web search, set/change/mute volume, media play/pause/next/ previous (MPRIS), lock screen, screen brightness, do-not-disturb, screenshots, timers with notification, free-form Q&A fallback, and suspend / power off / reboot (each asks for on-screen confirmation first).
The default model was picked by measurement, not vibes — and you can rerun it:
vera models download gemma-4-e4b # + qwen3-4b-instruct, phi-4-mini…
vera-eval --models qwen3-1.7b,gemma-4-e4b --data data/eval.jsonl --verbosePrints a markdown table of tool-selection accuracy, argument accuracy, and
latency per model. Set the winner as llm_model in the config.
Bake-off results (81 cases, CPU-only, i7-10875H, models under load):
| model | tool acc | args acc | avg ms | parse fails |
|---|---|---|---|---|
| qwen3-1.7b | 91.4% | 91.4% | 2917 | 0 |
| qwen3-4b-instruct (default) | 98.8% | 97.5% | 3315 | 0 |
| gemma-4-e4b | 100% | 98.8% | 6223 | 0 |
| phi-4-mini | 97.5% | 93.8% | 2679 | 0 |
qwen3-4b-instruct is the CPU sweet spot and the shipped default;
gemma-4-e4b is the accuracy pick once you have the CUDA build.
- "I didn't catch anything" — check the default input device:
wpctl status(Sources section). Vera records from the default source. - "model missing" error in the window — run the
vera models downloadcommands above. - Slow first response — that's the one-time model load + system-prompt decode; subsequent commands reuse the KV cache and are much faster.
- GPU build fails — you need
nvcc(sudo apt install nvidia-cuda-toolkit) and a working driver (nvidia-smi).
| Crate | What it is |
|---|---|
vera-core |
config, model registry/downloader, audio capture, VAD endpointing, STT client, llama LLM with GBNF-constrained tool calls, tool executors |
verad |
the daemon: GTK4 floating window + GApplication D-Bus actions, pipeline thread |
vera |
CLI: toggle (bound to the hotkey), run <text>, models …, quit |
vera-stt |
whisper.cpp helper process (whisper and llama bundle incompatible ggml copies, so whisper runs out-of-process) |
vera-eval |
model bake-off: labeled utterances → accuracy/latency table |
MIT — see LICENSE.
whisper.cpp and llama.cpp are pulled in via the whisper-rs and llama-cpp-2
crates and carry their own MIT licenses.