You're sitting there quiet all day. Say Something.
Say Something lets you talk instead of type. Hold Right Ctrl (Windows) or Right Cmd (Mac) in any app, say your thing, let go, and the cleaned-up text drops in at your cursor about a second later. It runs 100% on your machine. Free, open-source, no account, no cloud, no subscription, no telemetry. None of that.
Catch your words in the floating pad, then drag it onto any field and let go. I haven't found another dictation tool that lets you aim.
The little pill while it's listening. Live waveform and a timer, so you know it's actually on.
Settings: rebind the hotkey, grab models, dictionary, history, formatting. All local.
The Rewrite tab: optional AI polish that runs locally through Ollama. Off by default, and if it flakes it just gives you your original words back.
Not sure which box has focus? Don't want it typing into the wrong window? Hold Right Alt (Windows) or Right Option (Mac) instead of the main key and your words land in a little floating pad, already copied. Then just grab the pad and drag it onto the field you want, let go, and the text drops right there. Or hit Ctrl+V anywhere, it's copied either way. You catch your words and carry them exactly where they go. Every other dictation tool just fires text at whatever window's focused and hopes. This is the only one I've found that lets you aim. Wispr Flow doesn't.
- Hold to talk. Hold the key (default Right Ctrl on Windows, Right Cmd on Mac, you can rebind it), a glowing pill pops up, talk, let go, text drops in at your cursor.
- Tap to go hands-free. Quick tap (under 250 ms) and it keeps listening so you don't have to hold anything. Tap again to finish. Esc bails, nothing gets inserted.
- Auto-stop when you stop. In hands-free mode it notices when you go quiet and finishes on its own (silence window is adjustable, 1 to 5 seconds). The pill dims as the pause builds so it never feels random. Hold-to-talk never auto-stops.
- Live preview. Words show up in the pill while you're still talking. It's just a preview though. The final accurate pass on release is what actually gets inserted.
- The drop pad. See above. It's the good part.
- Optional AI cleanup. Off by default. Flip it on and every dictation gets polished by a local Ollama model first (Clean up, Professional, Casual, or Bullets). Runs on your box, no cloud. If it's slow or dies, you just get your plain text, nothing lost.
- Warm mic. Keeps a tiny rolling buffer so if you start talking a beat before you hit the key, your first word still makes it.
- Smart formatting. Punctuation, filler removal (um, uh), spoken commands (say "new line" or "new paragraph"), auto-caps, and it strips the junk Whisper sometimes emits. All toggleable.
- Custom dictionary. Feed it names and jargon so it stops mangling them.
- Local history. Last 200 transcriptions, click to copy, stored as a local JSON file. Turn it off if you want.
- Private because of how it's built, not because of a checkbox. Audio stays in memory, Whisper runs on
127.0.0.1only, zero network calls at runtime.
Straight up: Wispr Flow is a polished paid product and it does some things Say Something doesn't chase. The whole point here is it runs entirely on your machine and you can read every line of it.
| Say Something | Wispr Flow | |
|---|---|---|
| Price | Free, open-source (MIT) | Subscription |
| Transcription | On your machine (whisper.cpp) | Their cloud |
| Account | None | Required |
| Privacy | You can read the source; audio never leaves | Trust their policy |
| Works offline | Yes | No, needs the cloud |
| Platforms | Windows 10/11 and macOS (Apple Silicon and Intel) | Windows and macOS |
| AI cleanup | Yes, local and free (optional, via Ollama) | Yes, cloud (part of the sub) |
| Live preview while talking | Yes, in the pill; inserted on release | Yes, streams into the field |
| Drop pad (catch text, place it with a click) | Yes | No |
| Custom dictionary | Yes | Yes |
If you want text streaming straight into the field as you talk, Wispr Flow is the more complete thing today. If you want dictation that never phones home and that you fully own, on Windows or Mac, that's this.
You can have it hand each finished dictation to a local model for one last polish before it lands. Fix grammar, tighten it up, or turn a rambling thought into bullets. Four styles: Clean up, Professional, Casual, Bullet points.
- Off by default. None of this happens until you turn it on in Settings → Rewrite.
- Runs on Ollama, a free local model runner you install once. Pull a model (
ollama pull llama3.2) and it shows up in the picker. - Stays on your machine. It talks to Ollama on
127.0.0.1:11434and nowhere else. That address is hard-coded, not a setting. Nothing hits any cloud, and no network call happens at all unless you turn rewrite on. - Never loses your words. Each rewrite gets 10 seconds. If the model is slow, down, or spits out garbage, you just get your original text.
Windows
- Windows 10/11 (x64)
- Node.js 24+
- The C# compiler that already ships with Windows (
csc.exe). Used once at setup to build the tiny helper. Nothing gets downloaded to build it.
macOS
- macOS 13+ on Apple Silicon or Intel
- Node.js 24+
- Xcode Command Line Tools (
xcode-select --install). Setup usesswiftcto build the tiny helper andcmake+clangto build the speech engine, all on your machine.
Windows:
npm install # installs Electron (the only devDependency)
node scripts/setup.js # unpacks whisper, compiles the helper, grabs the default model
npm start # launches, shows up in your system trayMac:
npm install # installs Electron (the only devDependency)
bash scripts/build-whisper-mac.sh # builds whisper.cpp (Metal) from source, once
node scripts/setup.js # compiles the helper, grabs the default model
npm start # launches, shows up in your menu barFirst launch on a Mac walks you through the three permissions it needs (Microphone, Input Monitoring, Accessibility). That's just how macOS gates global hotkeys and text insertion; the grants stay on your machine like everything else.
npm startruns the app.npm run smokeis a headless self-check (no windows, prints JSON, exits non-zero if something's off).npm run setupre-runs setup (add--model <name>for a specific model).npm testruns the unit tests.
Default model is small.en (466 MB). Smaller ones (tiny.en, base.en) and bigger ones (medium.en, large-v3-turbo), plus multilingual, are one click away in the Model tab.
Both of these bundle Whisper, the helper, and the default small.en model right into the package, so whoever runs it gets zero setup and no download.
npm run dist:dir # portable app -> dist\win-unpacked\ (also zipped)
npm run dist # installer -> dist\SaySomething-Setup-<version>.exeHeads up: npm run dist (the installer) needs Windows Developer Mode on (Settings → Privacy & security → For developers → Developer Mode). electron-builder unpacks a signing toolkit that has some macOS symlinks in it, and making symlinks on Windows needs that permission. The portable dist:dir build doesn't need it. Builds are unsigned, so first launch you'll get a SmartScreen "unknown publisher" nag (More info → Run anyway) until it's code-signed.
On a Mac the same two commands make a .dmg and a .zip for both Apple Silicon and Intel (four files, one of each per arch). Local builds are unsigned, so Gatekeeper shows the "unidentified developer" nag (right-click → Open) until they're signed and notarized; the signing steps live in docs/MAC-PORT.md.
An Electron shell (main is CommonJS, the windows are plain HTML/CSS/JS, no bundler, no framework) plus two small local native bits:
- The input helper. One tiny native program per platform, both talking the same JSON-over-stdio protocol. On Windows it's a C# helper compiled at setup by Windows' own
csc.exe(native/SaySomethingHelper.cs); on Mac it's a Swift helper built byswiftc(native/SaySomethingHelper.swift). It watches only your hotkey, does the clipboard-swap paste and unicode typing, and reports the frontmost app. You can read every line. It's never downloaded. - whisper-server. From whisper.cpp v1.9.1, kept warm on
127.0.0.1:8737. Transcription is a localPOSTto/inference. On Mac it's built from source as one universal binary; on Apple Silicon it uses Metal so transcription runs on the GPU, and on Intel it runs on the CPU (Accelerate).
Zero runtime npm dependencies. Downloads use Node's built-in fetch, unzipping uses Windows' own tar.exe.
Full spec is in docs/SPEC.md, module layout in docs/CONTRACTS.md. Those are the source of truth.
Privacy here isn't a setting, it's how the thing is built.
- The keyboard hook only ever reports your hotkey (and Esc while recording). It never buffers, logs, or sends any other keystroke, and it ignores injected input so it can't feed on its own typing.
- Audio only lives in memory and never hits disk. The WAV exists just long enough to POST to the local server.
- Whisper binds
127.0.0.1only. With AI rewrite off (the default), there are zero network calls at runtime, period. - The optional rewrite only talks to localhost. If (and only if) you turn it on, it POSTs to Ollama on
127.0.0.1:11434. That address is hard-coded. No cloud, ever. - The only time it uses the internet is grabbing models and binaries at setup (GitHub and Hugging Face), and it tells you on the console.
- The helper is compiled on your machine from source that's checked in (
csc.exeon Windows,swiftcon Mac). The binary is never downloaded.
Mic permission denied. Windows can block mic access per app. Open Settings → Privacy & security → Microphone (or paste ms-settings:privacy-microphone into Run) and make sure desktop apps can use the mic. Restart the app.
Mac: hotkey does nothing / nothing pastes. macOS gates global hotkeys behind Input Monitoring and text insertion behind Accessibility (System Settings → Privacy & Security). The first-run screen walks you through both, plus the mic. If you granted them and it still sits there, toggle the app off and on in those two panes (macOS caches grants per binary) and restart Say Something.
Port 8737 is busy. It binds the whisper server to 127.0.0.1:8737, and if that's taken it probes up through 8747 and grabs the first free one. Nothing for you to do unless all of them are busy, then free one up and restart.
My first word gets clipped. Turn on Warm mic (pre-roll) in Settings → General → Microphone (it's on by default). It keeps a short buffer so speech that starts right before the keypress still lands. Bump the slider up if you tend to jump the gun.
A model download got interrupted. Downloads go to a .part file and only get renamed once the full size checks out, so a half-download won't get mistaken for a real one. Just re-run it (Model tab, or node scripts/setup.js --model <name>).
My antivirus flagged SaySomethingHelper.exe. False positive. Some AVs freak out at any freshly compiled, unsigned exe that sets a keyboard hook. The full source is in native/SaySomethingHelper.cs and it's compiled on your machine by Windows' own csc.exe, nothing downloaded. Read it, then allow-list bin/helper/SaySomethingHelper.exe if your AV keeps eating it.
Hands-free stopped while I was still thinking. In tap-to-latch mode it auto-stops when you go quiet. If it's cutting you off, bump the silence window up in Settings → Hotkey (up to 5 s) or just turn auto-stop off there. Hold-to-talk never auto-stops, hold as long as you want.
It never stops in a loud room. Constant background noise can keep the level above the quiet threshold so it never hears the pause. Just tap the key again to finish it yourself (and there's a max-length backstop for really long ones).
Rewrite tab says "Ollama not detected." The optional AI cleanup needs Ollama running. Install it, start it, pull a model (ollama pull llama3.2), then hit Refresh. It's off by default so this only matters if you want it, and if Ollama's ever unreachable you just get your plain text.
Nothing happens when I hold the key. Check the tray menu isn't Paused, confirm your hotkey in Settings → Hotkey, and make sure the helper's running (Settings → About → Input helper). If it keeps crashing, restarting the app reinstalls the hook.
Contributions welcome. See CONTRIBUTING.md for how the code's laid out and the C# / no-dependency rules to keep.
Regenerating the screenshots:
npx electron scripts/capture-screens.jsrenders the pill and both settings tabs toassets/screenshots/.
Say Something is free forever, but you can buy me a coffee ☕. (It's not actually coffee. It's a secret second thing.)
MIT © Say Something contributors.