Repository navigation
Releases
Kaho 2.4.6
Download Kaho-2.4.6.dmg, open it, and drag Kaho to Applications. Requires macOS 14 or later on Apple Silicon. With Homebrew: brew upgrade --cask kaho (or brew install --cask utsavanand/kaho/kaho).
- A stray tap no longer pastes your dictionary. Your dictionary and the
words Kaho reads off the screen reach the speech model as one list of
hints, and on a short recording with no speech in it (a quick tap, a
breath) the model sometimes wrote that list out instead, so a run of
names like "Kaho, Sotto, Duckterm, ui-dev, main-dev…" was pasted. Kaho
now recognises the list and pastes nothing. Sentences that mention
those words, and lists of them you say yourself, still paste.
Kaho 2.4.5
Download Kaho-2.4.5.dmg, open it, and drag Kaho to Applications. Requires macOS 14 or later on Apple Silicon. With Homebrew: brew upgrade --cask kaho (or brew install --cask utsavanand/kaho/kaho).
- See your words while a long dictation is still going. Once Kaho starts
transcribing a long dictation as you talk (past about 15 seconds), the
pill widens and shows the last few words so far, updated every stretch.
It clears the moment you stop, cancel or speak an instruction, and the
words are never written to the log.
Kaho 2.4.4
Download Kaho-2.4.4.dmg, open it, and drag Kaho to Applications. Requires macOS 14 or later on Apple Silicon. With Homebrew: brew upgrade --cask kaho (or brew install --cask utsavanand/kaho/kaho).
- Long dictations paste in about a second instead of up to half a minute.
Once a dictation passes 15 seconds, Kaho transcribes and cleans it up in
stretches while you are still talking, so stopping leaves only the last
few seconds to process. A two-minute dictation that waited 15-30 s now
pastes in about 1-2 s. Stretches are cut at sentence pauses, and the
punctuation where they meet is checked, so a sentence isn't split by a
stray full stop. Dictations under 15 seconds work exactly as before. - The recording pill shows on the screen you're typing on. With several
displays it used to appear on whichever one macOS considered main; it
now follows the text field, or the mouse pointer when an app doesn't
say where its field is. - Shift pressed a moment before the hotkey now counts. Only a Shift
pressed after recording had started was noticed, so an instruction
begun with Shift first was typed into the message. That's the usual
order when editing selected text.
Kaho 2.4.3
Download Kaho-2.4.3.dmg, open it, and drag Kaho to Applications. Requires macOS 14 or later on Apple Silicon. With Homebrew: brew upgrade --cask kaho (or brew install --cask utsavanand/kaho/kaho).
- Clean up keeps only the fix when you correct yourself. "Let's meet
Thursday, no wait, Friday" now comes out as "Let's meet Friday." Before,
both days were kept almost every time. A real "no", "not" contrasting
two things, and "or" between options are left alone. - A cleanup that would drop a "not" or "never" pastes what you said
instead. Removing a correction means deleting words, and in testing the
model once deleted a "not" and reversed the sentence.
Kaho 2.4.2
Download Kaho-2.4.2.dmg, open it, and drag Kaho to Applications. Requires macOS 14 or later on Apple Silicon. With Homebrew: brew upgrade --cask kaho (or brew install --cask utsavanand/kaho/kaho).
- Kaho now says when a newer version is out. At launch and once a day it
asks GitHub for the latest version number, sending nothing about you or
your dictation. A newer one shows as "Kaho x.y.z is available…" at the
top of the menu and in About in Settings, with a button to its release
page. "Check for new versions" in Settings turns it off. - Cloud rewrite works again in the downloaded app. 2.4.0 and 2.4.1 bundle a
Python with no certificates of its own, so every request to OpenAI,
Anthropic or a custom endpoint failed to verify, and Kaho quietly used
the on-device model instead. Requests now use the certificate bundle
that ships inside the app.
Kaho 2.4.1
Download Kaho-2.4.1.dmg, open it, and drag Kaho to Applications. Requires macOS 14 or later on Apple Silicon. With Homebrew: brew install --cask utsavanand/kaho/kaho.
Dictation that keeps working, a first run that needs no help, and two
ways to change text by saying how.
- A frozen microphone no longer stops dictation until Kaho is restarted.
macOS's audio system sometimes never returns from opening or closing
the microphone, and Kaho's only audio thread then stayed stuck: every
later dictation was refused. The microphone now runs in a separate
process. One that freezes is stopped after 350 ms, and the next
dictation gets a fresh one without reloading the models. Speech already
captured is kept. The next recording's process is started ahead of
time, with the microphone closed, so the key press still reaches an open
microphone in about 100 ms, as before. - Edit text you've already written. Select it in any app, hold the
hotkey and Shift, and say what to change: "make this more formal",
"the date is Friday, not Thursday". Kaho rewrites the selection and
pastes over it. - Spoken instructions work with either Shift key. Only the right one
counted, so an instruction spoken while holding the left one was typed
into the message. Instructions can now change what the message says as
well as how it reads: "drop the part about shipping", "the PR is number
six". - Names on screen are spelled right. At the start of a dictation, Kaho
reads the window you're dictating into and passes unusual names and
terms to the speech model as hints. In testing, "Siobhan" and
"Debezium" stopped coming out as "Shavon" and "debesium". The words are
never logged, and
"Use Words on Screen" turns it off. - A first run that works without help:
- Opening Kaho a second time brings up the running copy instead of
starting another that processes every dictation twice. - Opened from the download, Kaho offers to move itself to Applications
before asking for any permission, so the permission isn't granted to
a temporary copy. - After Accessibility is granted, Kaho restarts by itself. While it's
missing, the menu bar shows⚠️ and the first menu item opens the right
settings page. - The speech model download shows its progress in the menu.
- A paste that can't happen says why and how to fix it.
- Opening Kaho a second time brings up the running copy instead of
- Settings shows which Kaho is installed: an About section with the
version, the release notes and the website. - Back to a DMG: open it and drag Kaho to Applications. Apple had been
holding, then dropping, Kaho's 45 MB launcher; it is now 124 KB, with
the rest of the code beside it, and the DMG is notarized in minutes. - The 2.4.0 zip failed Gatekeeper ("Apple could not verify Kaho is free
of malware") when unzipped by double-clicking: Archive Utility turned
stored file attributes into stray files inside the bundled Python, which
broke its signature. Release zips no longer carry those attributes.
Kaho 2.4.0
Runs on macOS 14 (Sonoma) again. 2.2.0 bundled a Python and speech library built for macOS 15, so on macOS 14 it quit at launch without showing anything. 2.4.0 is built against macOS 14, and the release script now refuses to ship any file that needs a newer macOS than Kaho claims. Tested on a macOS 14.3 MacBook Air.
Download Kaho-2.4.0.zip, unzip it, and drag Kaho into Applications. This release ships as a zip, not a DMG: the app is notarized by Apple and stapled, but Apple's notary service is still holding the DMG wrapper. A DMG will be added here once it clears. With Homebrew: brew install --cask utsavanand/kaho/kaho.
A reliability release. An independent audit of the whole application
found eighteen reproducible defects; this fixes all of them. The worst
could cost a dictation the user had already finished speaking.
- A stuck microphone no longer loses your words. macOS's audio stack
can block forever while releasing a device, and Kaho waited for that
release before handing the recording to the model — so a hang
discarded speech that had already been captured. The transcript is
now submitted first and the device released afterwards. (Swapping
stop for abort would not have helped: both route through the same
blocking call.) - A dictation that takes too long says so instead of vanishing. The
watchdog used to hide the pill, which erased the only sign that
anything was still running — and because cancellability was read off
whether the pill was visible, it also silently stopped Escape from
working on that job. - Cancelling one dictation can no longer discard another. Cancellation
and spoken-instruction ranges were shared between recordings, so
stopping one dictation and cancelling the next threw away the first,
and starting a new one erased the previous one's instruction
boundaries. - A failed rewrite never costs you the transcript. Three paths could
throw away recognised speech: a tokenizer without a chat template, a
malformed custom endpoint, and a provider returning a null response.
All three now fall back to pasting what you said. - The reported time is the time you actually waited. It used to start
after the worker picked the job up, so microphone shutdown and queue
waiting were invisible — a four-second stall logged as 0.00s. - Audio that is too quiet, silent, or missing now says so on the pill
rather than only in a log file. A microphone turned down read as the
app being broken. - A slow device release is no longer reported as a wedged one. The old
five-second threshold fired on healthy recordings and sent people to
Restart Kaho for something that recovered on its own. - An instruction too short to use is no longer transcribed into your
message. - A dictation already finished can no longer be stopped by a leftover
timer from an abandoned one, and starting a new one can no longer
hide the pill of a recording still in progress. - A microphone that fails to open is no longer left claimed. The stream
was not closed when it failed to start, so one bad open made every
later open fail too — and any error other than a PortAudio one left
the app unable to record at all until it was restarted. - Changing the hotkey while holding it no longer strands the recording.
Releasing the old key stopped matching, so the microphone stayed open
with nothing to end it. - A damaged settings file or history entry no longer stops the app
starting. Both checks accepted valid JSON of the wrong shape and then
crashed on it later. - Warmups no longer pile up behind each other when several dictations
follow in quick succession.
2.3.0 was built but never published: Apple's notary service stalled on
it for hours, and by the time that was clear the build was eight fixes
behind. Its contents are included here.
Kaho 2.2.0
Say how you want it written, in the same breath.
Hold the hotkey and dictate. While still holding, press right Shift and keep talking — everything said while it's down is an instruction, not part of the message. Let go of Shift and you're dictating again.
"tell Mark I can't make the offsite, suggest November" → ⇧ → "formal, two sentences"
"Mark, I am unable to attend the offsite; I recommend scheduling it in November."
Same words, different instruction:
→ ⇧ → "casual, like texting a friend"
"Hey Mark, I'm sorry but I can't make the offsite, gonna suggest November instead."
The same app needs a different voice for a leader, a junior, and family, so no per-app rule can guess it — only you know, and only at that moment. Other tools solve this with saved modes and prompt libraries you have to maintain. Here the instruction is just speech: said once, used once, never stored.
Four times faster on short dictations
Transcription moves from Whisper large-v3-turbo to Qwen3-ASR 1.7B. On an M4 Max, measured back to back:
| clip | before | after |
|---|---|---|
| 1.4 s | 0.51 s | 0.12 s |
| 10.3 s | 0.60 s | 0.42 s |
| 29.6 s | 0.78 s | 1.06 s |
Accuracy improves too (WER 1.5% → 1.3% clean, 4.4% → 3.4% on jargon). The two cross at roughly 15–20 seconds: across 677 logged dictations the median is 6.3 s and 84% are under 20 s, so most get faster and the longest ~15% get slower. Dropping torch also shrinks the download from 478 MB to 357 MB.
Bring your own key — optional, never required
The rewrite step can run on OpenAI, Anthropic, or any OpenAI-compatible endpoint (Groq, OpenRouter, a local Ollama). Worth it for "turn this ramble into a clear paragraph", where a 4B model has a real ceiling.
On-device stays the default and the fallback. No key, no network, bad endpoint — it falls back to the local model and tells you, so a cloud problem can never cost you your words. The key is stored in your Keychain, never in Kaho's settings file.
Speech-to-text always stays on this Mac. Only the transcript is ever sent, and only if you set a key.
Also
- Tap to start, tap to stop. Holding is still the default and is self-limiting, but holding a key through a long prompt is tiring — and if you can't hold a modifier down at all, this is the difference between usable and not.
- Pin your language. Left to detect, the model guesses per 30-second window and can get a short sentence wrong.
- Escape cancels. Mid-recording the audio is dropped; mid-transcription the result is discarded rather than pasted.
- ⌘C, ⌘V, ⌘X and ⌘A work. macOS routes these through the menu bar and Kaho never had an Edit menu, so copying from History needed a right-click.
- A stuck microphone says so. macOS's audio stack can wedge mid-recording; the pill now reports it and Restart Kaho recovers.
- The app can say its own name. The dictionary shipped with "Kaho" commented out, so it transcribed as "Kahoot".
- The app bundle now carries its own notarization ticket, so a first launch works offline.
Install
Download the DMG below and drag Kaho to Applications, or:
brew install --cask utsavanand/kaho/kaho
Apple Silicon, macOS 14+. First launch downloads about 2.3 GB of models.
Kaho 2.1.0
Escape cancels a dictation. Press it while recording and the audio is dropped without being transcribed. Press it while Kaho is transcribing or rewriting and the result is computed, then discarded — MLX inference is one blocking call that can't be interrupted, so what cancelling buys you is that the text never lands in your document.
⌘C, ⌘V, ⌘X and ⌘A work now. macOS routes those through the menu bar, and Kaho never installed an Edit menu — so none of them did anything. Copying a transcript out of History needed a right-click, and the dictionary editor couldn't be pasted into at all.
A stuck microphone says so, and can be fixed. macOS's audio stack can wedge mid-recording: PortAudio's stop blocks forever inside CoreAudio. Kaho already refused to record in that state, but only said so in the log, so the symptom was dictation quietly doing nothing. The recording pill now reports it, and a new Restart Kaho menu item quits and reopens the app — the only cure, since that thread can't be interrupted.
Pin your language. Left to detect, Whisper guesses per 30-second window, and on a short or noisy clip it guesses wrong — an English sentence comes back transliterated into another script. Menu bar and Settings both offer a language; detection stays the default.
Also: the app bundle now carries its own notarization ticket, so a first launch works offline instead of waiting on a check with Apple. And tools/benchmark.py measures each stage of a dictation against fixed clips, so "it feels slower" can be checked against numbers.
Install
Download the DMG below and drag Kaho to Applications, or:
brew install --cask utsavanand/kaho/kaho
Apple Silicon, macOS 14+. Everything runs on-device.
Kaho 2.0.0
Sotto is now Kaho — Hindi कहो, "say it".
A commercial product with a nearly identical name was already on the market, and anyone searching for one would have found the other. Renaming now, while the install base is small, costs less than renaming later.
Nothing about how the app works has changed.
Upgrading from Sotto
Your settings, transcript history and dictionary carry over automatically — the app moves them the first time it starts.
You will need to grant Microphone and Accessibility permission once more. macOS ties those to an app's bundle identifier, which changed with the name, so it treats Kaho as a new app. System Settings → Privacy & Security. The recording pill will tell you if a paste is blocked.
You can drag the old Sotto.app to the Trash once Kaho is running.
Also in this release
Clean up now skips the rewrite when there is nothing to clean. Before generating, a single forward pass asks the rewrite model whether the transcript is already clean and reads the letter probabilities — a decision, not generation, about 85 ms. Above 90% confidence the transcript is pasted as-is, saving the 0.35–1.4 s rewrite. On 24 test dictations it skipped all 15 clean ones and none of the 9 messy ones.
Install
Download the DMG below, drag Kaho to Applications, and grant the two permissions. Apple Silicon, macOS 14+. Everything runs on-device.