Skip to content
Quill app icon

Local-first voice dictation

Talk to your computer.
Words appear.

Quill captures your mic, transcribes with Whisper on-device, polishes with embedded llama.cpp when you ask for it, and inserts text into whatever field you have focused. F8 is quick raw dictation. Add an enhanced binding when you want translate or polish. Everything runs on your machine unless you explicitly choose a remote endpoint.

Download for macOS All platforms → v1.0.0-beta.5 · open beta

Apple Silicon macOS 14+ .dmg (signed and notarized) and Linux x86_64 .AppImage / .deb. Windows is coming soon. Free, open download while in beta. Say hi on Discord.

Quill setup view showing microphone, accessibility, Whisper model, and embedded polish readiness checks

Local-first means local-first.

No audio or transcript leaves the machine by default. The polish pass runs against a SHA256-pinned model the app manages itself. Anonymous beta diagnostics contain no transcript or audio, and offline mode disables all network egress. Any remote provider is opt-in per-config and surfaces a startup warning.

Get Quill

Download the beta.

Free, open download. 1.0.0-beta.5 · published 2026-07-29. macOS is signed and notarized; every build ships a minisign-signed SHA256SUMS you can verify.

Trouble installing? See the install guide. The app auto-updates in place once installed, on the beta channel.

Record, transcribe, polish, insert

Four stages, all on-device.

Each stage is a separate Rust crate, so raw and enhanced dictation stay predictable. Hold the hotkey, talk, release. The daemon does the rest without a single byte leaving your machine on the default path.

1
Hotkey down

Daemon opens the mic via cpal. webrtc-vad waits through natural pauses and auto-stops.

2
Whisper

On-device transcription with whisper-rs. Metal on Apple Silicon, CPU elsewhere.

3
Translate / polish

Optional local LLM stages: translate-to-English, then embedded llama.cpp polish against the verified GGUF.

4
Type or paste

Type at cursor by default, with clipboard-preserving copy-and-paste as the fallback path.

First dictation, from a terminal

Drive it live over IPC

# Cheap liveness probe
$ quill ping
pong

# Live-switch a hotkey's insertion strategy
$ quill set-inject-mode enhanced clipboard

# Wayland: let the compositor own the keybind
$ quill press quick
$ quill release quick

Seven polish styles

Pick how the polish pass rewrites you.

On the enhanced path, the embedded model rewrites the raw transcript through one of seven prompt templates. casual is the default polish style. no-polish is a passthrough: Whisper text, untouched. Set it in Settings or via the polish_template field.

no-polish

Pass the raw Whisper transcript through unchanged.

Fast dictation, already-edited speech, debugging STT

casual

default

Light cleanup. Conversational tone, contractions kept.

Slack, quick notes, PR comments

formal

Proper grammar, no contractions, business voice.

Email bodies, reports, customer replies

technical

Preserve technical terms, code, and command names verbatim.

Code review, bug reports, eng chat

bullets

Restructure continuous speech into a bulleted list.

Meeting notes, action items, stand-ups

concise

Shorter, fewer words, filler and hedging removed.

Commit messages, status updates

email

Format as an email body. Greeting, body, and sign-off when context fits.

Dictating email replies

Key concepts

The vocabulary; the daemon composes everything else from these.

F8 (quick)
The fast path, on by default: capture, transcribe, inject. No polish pass, lowest latency.
enhanced hotkey
Optional second binding, commonly F9, that adds local translate and polish stages before injection.
polish style
One of seven prompt templates: casual, formal, technical, bullets, concise, email, no-polish.
custom vocabulary
User-managed domain terms, names, brands, and acronyms that bias Whisper through an initial prompt.
inject mode
Per-hotkey: Type at cursor by default, or Copy & paste with clipboard restore.
polish backend
embedded by default (bundled llama.cpp). remote is the opt-in escape hatch and warns on non-loopback hosts.
daemon
The long-running process that owns the global hotkey via rdev and drives the whole pipeline over IPC.

The privacy contract

Dictate without trusting a cloud.

Quill is built so the private content path is the default path. The embedded polish model is pinned and verified; remote transcript processing is the loud exception, not the rule. Here is exactly what that buys you.

  • Audio never leaves the machine. Whisper runs on-device. There is no transcript network round-trip on the default path.
  • Anonymous diagnostics are transcript-free. Beta telemetry and crash uploads default ON, contain no transcript or audio, and can be disabled in Settings.
  • No raw transcript logging. The daemon refuses to log raw transcripts at the default tracing level. That is enforced, not advised.
  • SHA256-pinned polish model. The embedded GGUF (Qwen3 4B Q4_K_M) is verified against a pinned SHA256 before first use.
  • Remote is explicit and loud. Pointing polish at a remote endpoint is per-config opt-in and fires a startup warning for non-loopback hosts.
  • Offline mode exists. A single Settings switch disables telemetry, crash uploads, and update checks for fully offline operation.
  • Signed, verifiable downloads. Every build ships a minisign-signed SHA256SUMS, and the in-app updater verifies downloads against a key baked into the app.

The pinned polish model

# quill-core model registry
model = "Qwen3 4B Q4_K_M"
repo  = "Qwen/Qwen3-4B-GGUF"
file  = "Qwen3-4B-Q4_K_M.gguf"
sha256 = 7485fe6f11af...

# Verified before first use. No Ollama server.
backend = "embedded"

Polish backends: embedded (default), system, remote. Only remote sends transcripts off-machine, and only after you opt in.

What it looks like

Paper-like sheets instead of glowing panels. The setup view runs once. The live view is where you spend your time. Settings is one keystroke away.

Quill live view with a list of past transcripts
Idle. Hold the hotkey to dictate. Past transcripts stack below; nothing leaves the machine.
Quill recording state showing a live partial transcript and an audio meter
Recording. The live transcript gets the main canvas while you talk. The meter shows the mic is hearing you.
Quill settings panel showing capture, polish, and output configuration
Settings. Pick your hotkeys, polish style, model, insertion mode, privacy settings, and theme. Persists to TOML.

What you get

Local-first by default

Audio and transcripts never leave your machine by default. Whisper runs on-device; enhanced dictation uses embedded llama.cpp against a verified GGUF in Quill's model cache. No API keys, no transcript network round-trip. Beta diagnostics are anonymous, transcript-free, and opt-out; offline mode disables all network egress in one switch.

Whisper with Metal acceleration

Speech-to-text via whisper-rs (whisper.cpp under the hood). Metal on Apple Silicon, CPU fallback everywhere else. Curated picker covers base.en, base, small.en, small, medium.en, medium. Quill manages the downloads into ~/.cache/quill/models/.

Enhanced polish without Ollama

After Whisper transcribes, a local Qwen3 4B Q4_K_M GGUF cleans up filler words, fixes punctuation, and disambiguates homophones through embedded llama.cpp. Pick one of seven styles. No Ollama install, no local HTTP server. A custom Ollama-compatible endpoint stays an explicit opt-in escape hatch.

F8 raw, enhanced when you want it

F8 is the fast path: transcribe and inject. The optional enhanced binding adds translate and polish stages before insertion. Both use the same hold-talk-release loop, and both can run as hold-to-talk or tap-to-toggle.

Pastes into any focused field

Quill defaults to Type at cursor, using macOS Accessibility where available and falling back when a field is not AX-writable. Copy & paste uses the clipboard but restores what you had copied before. Works in your editor, your browser, your terminal, your chat app.

Click-to-capture hotkey picker

Open Settings, click the hotkey field, press the binding you want: function keys, right-hand modifiers, or full chords like Cmd+Shift+Space, with reserved-combo warnings. Quill applies changes without hand-editing TOML.

First-run model setup

First launch walks through mic and Accessibility permissions, downloads the Whisper model and embedded polish GGUF, then verifies the GGUF before use. If something breaks later, WHAT / WHY / DO error banners with stable IDs explain what happened, why, and what to do.

In-app updater

Background download, signed-checksum verification, restart-to-install, and beta/prerelease channel selection. A 'What's new' card surfaces release highlights from a TOML asset baked into the binary.

Custom vocabulary and voice commands

Add domain terms, names, brands, and acronyms so Whisper stops mangling them. Optional voice commands turn phrases like new line, period, and question mark into punctuation after transcription.

Paper-first app shell

Quill defaults to large Literata reading type, no-glow layered sheets, a live transcript-first recording layout, and the current Corvid Light/Dark theme system with accessible contrast.

Stack

Pure Rust workspace, one crate per pipeline stage, plus a thin iced GUI for the app shell.

Layer Crate Tool
Audio capture + VAD quill-audio cpal + webrtc-vad
Speech-to-text quill-stt whisper-rs (Metal on macOS)
LLM polish quill-polish Embedded llama.cpp + verified GGUF (BYO endpoint optional)
Text insertion quill-inject arboard clipboard · enigo keystroke · macOS Accessibility
Hotkey + pipeline quill-daemon rdev + tokio
CLI quill-cli clap
GUI app quill-app iced

Status

v1.0.0-beta.5 is shipping on macOS and Linux. What works today, what we are hardening, what is still planned. Listed honestly.

Working today
  • Apple Silicon macOS 14+ .dmg, signed, notarized, stapled
  • Linux x86_64 .AppImage and .deb packages
  • Whisper STT with Metal on macOS; curated model picker
  • Embedded llama.cpp polish with verified Qwen3 4B Q4_K_M GGUF
  • F8 quick raw dictation by default; optional enhanced hotkey for translate and polish
  • Seven polish styles: casual, formal, technical, bullets, concise, email, no-polish
  • Chord hotkeys, tap-to-toggle, stream-as-you-speak, custom vocabulary, and voice commands
  • Type at cursor by default, with clipboard-preserving copy-and-paste fallback
  • First-run tour, WHAT / WHY / DO error banners, and self-explanatory diagnostics logs
  • In-app updater with signed-checksum verification and beta/prerelease channels
  • Anonymous beta telemetry and redacted crash reports: transcript-free, default ON, opt-out
  • Offline mode master switch for telemetry, crash uploads, and update checks
In flight
  • Packaged smoke coverage on every PR, starting with macOS
  • More field diagnostics for GPU/CPU backend selection and dictation outcomes
  • Windows hardening from preview toward a packaged beta build
Planned
  • Published Windows installer
  • Published Linux aarch64 release artifacts
  • Wayland-aware injection on Linux beyond compositor-owned press/release bindings
  • Per-app custom polish prompts

Built on the CorvidLabs spine

The same lanes, specs, and agent contracts as every other CorvidLabs project.