YazSes on macOS — install & first-run guide¶
Version: Applies to the current YazSes release (v2.x). Install the latest with Homebrew (
brew tap MSKazemi/yazses && brew trust MSKazemi/yazses && brew install --cask yazses) or the.dmg.Developer preview. macOS builds are unsigned and not notarized. macOS will warn you on first launch; the steps below show how to bypass Gatekeeper safely. Signing and notarization land before public beta. Preview also means dictation on a current build has not yet been verified on hardware by a person: the validation matrix shows what Mac testers have confirmed, and the label comes off when it records a Verified (HW) dictation on a current release.
Requirements¶
- macOS 14 (Sonoma) or later for the
.dmgand the Homebrew app; the Settings window and the on-screen overlay need macOS 15 (Sequoia). On an older Mac,pipx install yazsesmay still work, because pip falls back to older builds of those libraries, but that route has not been tested there. - Either architecture — releases carry an Apple Silicon
.dmgand an Intel one; only the Homebrew cask is Apple Silicon only (see the note below) - ~500 MB free disk: a 101 MB
.dmg(2.43.2, Apple Silicon), the installed app, and the 147 MB default Whisper model on first use - A microphone
Which Mac do I have?¶
Apple menu → About This Mac. If Chip says Apple M1/M2/M3/M4, take the …-macos-arm64.dmg. If Processor says Intel, take the …-macos-x86_64.dmg (or use pipx — see below).
Or from a terminal:
Install¶
Apple Silicon — Homebrew (recommended)¶
Upgrades then come with brew upgrade --cask yazses.
The
brew trustline is not optional. Homebrew now refuses to load a cask from a third-party tap until you trust it, so without it the install stops withThis is Homebrew's own anti-supply-chain hardening, not a fault in the tap — it applies to every third-party tap. Reported and verified end to end on an Apple M4 by @slegarraga (#182); the install completes cleanly once the tap is trusted.
Apple Silicon — direct download¶
- Download
YazSes-<version>-macos-arm64.dmgfrom the Releases page. - Open the
.dmg. Drag YazSes.app into the Applications folder shown in the Finder window. - Eject the
.dmg.
Intel Macs — take the x86_64 .dmg, or install from PyPI¶
Since v2.22.0 there is an Intel build. The .dmg is produced as a per-architecture matrix, so every release carries both YazSes-<version>-macos-arm64.dmg and YazSes-<version>-macos-x86_64.dmg. Take the x86_64 one.
The Homebrew cask is still Apple Silicon only: it declares depends_on arch: :arm64, so brew install --cask yazses refuses cleanly on Intel rather than installing something that cannot start.
⚠ The Intel leg is continue-on-error in CI, so a release can ship without it. If you do not see an x86_64 asset on a given release, install from PyPI instead — but check your Python version first:
python3 --version # must be 3.11, 3.12 or 3.13 on an Intel Mac
pipx install yazses
yazses quickstart
You get the same daemon and CLI; what you do not get is the .app bundle and its tray icon. Everything below about Accessibility and Microphone permissions still applies — grant them to your terminal app instead of to YazSes.app.
The Intel Python ceiling — upstream's, not ours¶
This page used to say PyPI "is architecture independent and always works". That is no longer true, and the way it fails is misleading, so it is worth the paragraph.
| What you install | Python versions that work on Intel macOS |
|---|---|
pipx install yazses (base) | 3.11 – 3.13 |
yazses[all] | 3.11 – 3.12 |
| Anything, on Apple Silicon | 3.11 and up — unaffected |
The cause is upstream wheel publishing, not YazSes packaging:
onnxruntimepublished nox86_64macOS wheel after 1.23.2, and 1.23.2 was built for CPython 3.10–3.13 only.faster-whisperrequiresonnxruntimeand is not optional here, so on Python 3.14 the base install cannot resolve.torchpublished no Intel macOS wheel after 2.4.1 (CPython 3.12), so thevoiceprintextra — and therefore[all]— already cannot resolve on 3.13.
On Python 3.14 you will see a long resolver backtrace ending in something like "onnxruntime>=1.14.0,<=1.23.2 has no wheels with a matching Python ABI tag (cp314)". It names onnxruntime and reads like a YazSes bug. It is not: pin your interpreter to 3.13 (pipx install --python python3.13 yazses) and it installs.
Already installed and working? Nothing breaks today — but a Python upgrade will break your next install rather than your current one, which is the worst possible time to find out. yazses doctor prints an Intel macOS row showing where you sit against this ceiling, so you can see it while things still work.
This page previously said an Intel
.dmg"would need a second CI job" that had not been paid for. That job exists now (macos-15-intelin the build matrix) and has shipped Intel bundles since v2.22.0. Note thatmacos-15-intelis the last x86_64 image GitHub Actions will offer, available until August 2027; when it goes, pipx becomes the only Intel path.
First launch — Gatekeeper bypass¶
Because the app is unsigned, macOS shows "YazSes can’t be opened because Apple cannot check it for malicious software" the first time you double-click the app. To get past this:
macOS 15 (Sequoia) and later — including macOS 26 — no longer offer Open on a right-click for an unsigned app. Use the Settings route instead (this is the flow reported on #562):
- Double-click YazSes.app once. macOS says it was Not Opened; click Done.
- Open System Settings → Privacy & Security and scroll to the bottom.
- Next to "YazSes" was blocked to protect your Mac, click Open Anyway, then Open Anyway again in the dialog, and enter your login password if asked.
macOS 14 and earlier:
- Open Finder → Applications.
- Right-click (or Control-click) YazSes.app → Open.
- In the dialog that appears, click Open again.
You only need to do this once. After that, double-clicking works normally.
Opening the app does not by itself grant any permission. YazSes then asks macOS for Accessibility, Input Monitoring and the microphone; if no prompt appears, the sections below say where to switch each one on.
If you prefer, do the same from a terminal:
Grant Accessibility access¶
YazSes listens for the dictation key (Right Option by default) using the macOS Accessibility API. The OS gates this with a privacy prompt:
- On first launch, YazSes triggers macOS to show an Accessibility prompt. Click Open System Settings.
- In System Settings → Privacy & Security → Accessibility, find YazSes and enable the toggle.
- Quit and reopen YazSes (the daemon picks up the new permission on next launch).
If the prompt didn't appear, open the pane directly:
Grant Input Monitoring access — the second switch¶
Accessibility on its own is not enough. Since macOS 10.15 an app that watches for a key without consuming it needs Input Monitoring as well, and it is a separate service granted in a separate pane. YazSes needs both: without Input Monitoring the dictation key does nothing at all, in every application, while the Accessibility toggle sits there enabled.
- Launch YazSes and hold the dictation key once. macOS shows an Input Monitoring prompt the first time.
- In System Settings → Privacy & Security → Input Monitoring, enable YazSes.
- Quit and relaunch YazSes. The grant is read when the event tap is created, so a running daemon will not pick it up.
Or open the pane directly:
YazSes is not in the list? An app only appears in Input Monitoring once it has asked for it. Launch YazSes, hold the key once, then look again — you cannot add it with the
+button before it has asked.
yazses doctor reports Accessibility and Input monitoring as two rows, because they are two switches and either one being off produces the same dead key.
Grant Microphone access¶
Hold the dictation key once. The first time, macOS prompts: "YazSes would like to access the microphone." Click OK.
No microphone prompt ever appeared, and YazSes is not in the Microphone list? That is almost always this same problem one step upstream. macOS shows the microphone prompt at the moment an app first records, and YazSes only records while the dictation key is held — so if the key is dead for want of Input Monitoring, nothing ever records, no prompt is ever shown, and the app never appears in the Microphone pane. Fix Input Monitoring first, then hold the key again.
If you accidentally clicked Don't Allow, re-enable in System Settings → Privacy & Security → Microphone → YazSes.
Use it¶
By default, hold Right Option anywhere on the desktop, speak, then release. The transcribed text appears in whatever app is focused.
The default hotkey is configurable in ~/Library/Application Support/yazses/config.toml:
[hotkey]
# "auto" → Right Option on macOS. Other options: "right_ctrl", "left_option",
# "space", "right_shift", ...
key = "auto"
hold_threshold_ms = 500
[stt]
model = "base.en" # the default; "tiny.en" is faster and less accurate, "small.en" more accurate
The first transcription downloads the default Whisper model (base.en, ~147 MB) into ~/.cache/huggingface/hub/ (the shared Hugging Face cache). Subsequent dictations are fully offline.
The menu-bar menu¶
The menu-bar icon is a glyph for the current state (🎤 ready, 🔴 recording, ⚠️ a problem). Click it and the top of the menu shows up to three greyed-out status lines. They are information only, so clicking them does nothing:
YazSes — idle · base.en (faster-whisper)
Speech model: loaded, idle 45 s of 300 s
⚠ 2 silent clips in a row
- The first line is always there. It shows the state and the speech engine that is actually running, in the same words as
yazses status. If the engine you configured failed to load and another one took over, this line names the one that took over. - The second line appears only if you set
[stt] idle_unload_s(see Release the model when idle). It says whether the speech model is in memory. If you also set[residency] latency_keep_alive_s(off by default, and it only matters when[latency]is on), the menu bar appends the governor's extra model to this same line, with·, while that model is loaded. Not yet tested on a real Mac. - The third line shows only the most important warning: why the daemon is in error, then a fallback engine, then a run of silent recordings.
The memory line and the silent-recordings warning use the same words as the Linux tray menu and the Windows tooltip. The engine and the fallback warning use the same words as yazses status. Below the status lines are Settings, Meeting Mode, Pause hotkey, Help, About and Check for updates, in that order. This menu has not been tested on a real Mac yet.
Verify with the CLI¶
The .app ships a CLI alongside the tray:
/Applications/YazSes.app/Contents/MacOS/YazSes --cli doctor
/Applications/YazSes.app/Contents/MacOS/YazSes --cli status
Installed with Homebrew? Since v2.44.0 the cask links a yazses command onto your PATH that runs this CLI, so yazses doctor works directly. With the .dmg, or on 2.43.2 or earlier, make the same shortcut yourself:
printf '#!/bin/sh\nexec /Applications/YazSes.app/Contents/MacOS/YazSes --cli "$@"\n' | sudo tee /usr/local/bin/yazses >/dev/null
sudo chmod +x /usr/local/bin/yazses
A bare symlink named yazses would open the menu-bar app instead, because the executable picks its mode from its own name; the script passes --cli explicitly.
Troubleshooting¶
"Accessibility is on and the hotkey does nothing." Check Input Monitoring, not Accessibility. A keyboard event tap needs both since macOS 10.15, they are granted in different panes, and Accessibility being enabled says nothing about the other one. See Grant Input Monitoring access above, and run yazses doctor — it reports the two separately.
"YazSes keeps asking for Accessibility." macOS treats unsigned apps as new identities each time their hash changes. After every YazSes update you may need to re-enable the toggle. Signing (planned) will fix this.
"Accessibility is enabled and YazSes still says it is denied." Same cause, worse symptom: the grant is bound to an identity the binary no longer has, so the old entry keeps rendering as an enabled toggle while the check answers denied. Turning it off and on again does not always clear it, because the stale row is not the one the toggle edits. Remove YazSes from the list, add it back, and relaunch — or reset the decision for this app only:
Keep the bundle id. Without it, tccutil clears the Accessibility grant for every application on the Mac, not just this one.
"doctor says denied, but YazSes is switched on in Settings." If you ran doctor in Terminal (or iTerm, or the VS Code terminal), macOS may judge the permission of that terminal app rather than YazSes.app. One report showed exactly this: Terminal switched off, YazSes switched on, and doctor answering denied for both Accessibility and Input Monitoring. This is a hypothesis from that one report, not a confirmed mechanism. The answer that cannot be mixed up is what the running app logged about itself:
"doctor says the daemon is not running, but the menu-bar icon is there." Releases up to 2.42.0 compared the process name case-sensitively, so a daemon started from the .app (.../MacOS/YazSes) was reported as not running. Fixed in 2.43.0 — update. On an older release, look for it yourself:
A permission was fixed, but the hotkey still does nothing. The grant is read when the keyboard tap is created at daemon start. If an older daemon is still running (opening the app again exits with "Another YazSes daemon is already running" in the log), it keeps the old answer. Run yazses restart (from the app: /Applications/YazSes.app/Contents/MacOS/YazSes --cli restart), check that ps aux | grep -i yazses shows one daemon with a recent start time, and try the hotkey again. yazses doctor also says so in the Daemon row when it can tell: "started before Input Monitoring was granted".
To be sure nothing old is left, look before you relaunch:
ps aux | grep -i [y]azses # every YazSes process; the daemon ends in --daemon
launchctl list | grep yazses # the login item, if you enabled it (com.yazses.daemon)
Releases up to 2.43.0 have a second way into this state: Quit in the menu bar did not stop the daemon. The menu's Quit ends the tray process from inside its event loop, so the tray never got to ask the daemon to shut down, and the daemon carried on, holding whatever permission it had read at its start, for days (#578). Fixed in 2.43.1: Quit now stops the daemon. On 2.43.0 or older, do not rely on Quit plus reopening to pick up a permission you have just fixed; use yazses restart as above. This was found by reading the library and the log, not by reproducing it on a Mac.
Since 2.43.1, a newer YazSes daemon that starts while an older one is still running asks the old one to stop and takes its place, instead of exiting as a duplicate. The old daemon has to be a release that reports its version over status; if the log says "Another YazSes daemon is already running" anyway, use yazses restart once. Double-clicking the app does not start a daemon, though: it starts the menu-bar icon, and the icon uses a daemon it finds running rather than starting another, so that takeover alone never replaced the daemon you reopened the app to fix.
The release that carries the changelog entry for #578 adds a second route: the menu-bar icon restarts the daemon (it runs yazses restart) when the daemon itself reports either of two things: it is an older version than the icon, or it started before Input Monitoring was granted (the same fact doctor shows). Both routes into it work:
- The icon is already running (it is at least that release): it checks every poll, and restarts the daemon with the notice "Restarting YazSes so the updated version takes over." or "Restarting YazSes so it uses the permission you granted."
- An older icon is still in the menu bar (the daemon's own icon, as in #578): the icon you just opened finds it, exits as a duplicate as before, and on its way out asks the daemon once and restarts it if needed. No notice is shown in this case; the restart is in the log.
Either way it happens only while the daemon is idle (never during a dictation or a meeting), and not again for the same reason within an hour. If the reason survives a restart — for example a login item (launchctl) that still starts an older install — the icon restarts the daemon again about once an hour while it is idle; yazses doctor names the version that is running. After a restart the older icon may stay in the menu bar talking to the new daemon; Quit it and open the app again if you want the new one. If the hotkey is still dead, yazses restart is still the manual route. Unverified on a Mac: this is tested with simulated daemons only.
Which YazSes is being asked about? The Accessibility answer is about the program that is running, not about every copy on the disk — so a grant given to /Applications/YazSes.app is not automatically the thing being checked when you run a yazses binary from somewhere else. doctor now prints the executable it asked about; if that path is not the one you granted access to, that mismatch is the thing to fix first.
"The hotkey doesn't fire." Check Accessibility is granted. Also check that no other tool is intercepting Right Option (e.g., Karabiner-Elements, some IME apps). Try a different hotkey by editing config.toml.
"Microphone is silent." Confirm in System Settings → Privacy & Security → Microphone that YazSes is enabled. Run --cli doctor to see what YazSes is detecting — the Microphone row now carries the fix, not just the word denied.
"Microphone says denied and I never saw a prompt." macOS only asks the first time an app actually records, so before your first dictation there is nothing in the Microphone list to enable. Hold the hotkey once and answer the prompt.
"Microphone is enabled in Settings and YazSes still says denied." Same trap as Accessibility above: these builds are unsigned, so macOS treats a changed binary as a new identity and the old approval stops applying while the entry still looks on. Reset this app's microphone decision and relaunch:
Keep the bundle id. Without it, tccutil reset Microphone clears the microphone grant for every app on the Mac. Microphone and Accessibility are separate services — one being granted says nothing about the other.
"Antivirus flags YazSes." These builds are unsigned, which trips conservative AV heuristics. Build from source (scripts/build-macos.sh) if you prefer.
Uninstall¶
If you installed with Homebrew, that route also removes the app, stops the launchd agent, and (with --zap) clears the support files:
Installed from PyPI? pipx uninstall yazses.
For a manual .dmg install:
launchctl bootout gui/$(id -u)/com.yazses.daemon 2>/dev/null || true
rm -rf /Applications/YazSes.app
rm -rf ~/Library/Application\ Support/yazses
rm -rf ~/Library/Caches/yazses
rm -rf ~/Library/Logs/yazses
rm -f ~/Library/LaunchAgents/com.yazses.daemon.plist
Also remove the toggle entry in System Settings → Privacy & Security → Accessibility.