Installing YazSes on Linux¶
This guide installs the Python daemon as a global command and starts it automatically at login. It targets the reliable batch (transcribe-on-release) configuration. Most reports from real machines are on X11 + PipeWire; the validation matrix lists them, and a dated, versioned hardware record for X11 is still to come (#642).
1. Install — one command¶
You do not need to clone the repository — the script fetches everything itself. Paste this. It installs YazSes and every system prerequisite (audio, keystroke injection, clipboard, the input group, and ydotoold on Wayland), then runs yazses doctor so anything missing surfaces during install rather than as silent failure later:
That is the whole install. Skip to §2. If you are unsure what is left to do, yazses quickstart looks at this machine and prints the next steps; it changes nothing.
Build prerequisites are handled for you. The script needs
git(it installs the latest code straight from the repo) and a C compiler with the Python headers (evdev, which reads the hotkey, publishes no wheels and is always compiled from source). It checks for all three up front and installs them viaaptif they are missing, instead of failing later inside the build. On a distro withoutaptit stops and names the packages — Fedoragit gcc python3-devel, Archgit base-devel. The Snap is the one channel that needs none of this: it bundles a prebuiltevdev. The APT package does not — itpipx-installs the Python package in its post-install step, so it compilesevdevtoo.
Other install channels (APT, Snap, pipx)
| Channel | Command | Notes | |---|---|---| | **Universal script** (recommended) | `bash <(curl -fsSL https://raw.githubusercontent.com/MSKazemi/yazses/main/install.sh)` | Latest code from git. Installs `uv` if absent. Provisions everything. | | **APT** (Debian/Ubuntu) | `bash <(curl -fsSL https://raw.githubusercontent.com/MSKazemi/yazses/main/install-apt.sh)` | Needs a distro whose `python3` is ≥ 3.11 (Debian 12+, Ubuntu 23.04+); on Ubuntu 22.04 use the universal script. Last tagged release. The script adds the YazSes apt repo, installs the runtime deps, joins you to the `input` group and sets up `ydotoold`; the `.deb`'s post-install step then `pipx`-installs the Python package and enables the user service. | | **Snap** | `sudo snap install yazses``sudo snap connect yazses:audio-record`
`sudo snap connect yazses:raw-input`
`yazses doctor`
`yazses start` | **Works on X11, and on GNOME/KDE Wayland via the desktop portal** (approve the one-time permission prompt at first dictation). All three privileged commands are required: a snap cannot connect its own interfaces, so without `audio-record` it has no microphone and without `raw-input` the hold-to-talk key does nothing ([#44](https://github.com/MSKazemi/yazses/issues/44)). `yazses setup` is not required: confinement blocks host package, group, and service changes, while the snap already bundles its X11 dependencies. See [what the snap can and cannot do](#3e-what-the-snap-can-and-cannot-do). | | **pipx** (any distro, Python ≥ 3.11) | `pipx install yazses` | Installs **only** the Python package — needs `build-essential python3-dev` to compile `evdev`, and you must then run `yazses setup` yourself ([§3](#3-installing-by-hand-what-the-installer-did-for-you)). | Already installed and want the newest release?
2. Finish setup¶
Three steps only you can do — the installer prints this same list when it finishes:
# 1. Log out and back in (once — so the `input` group takes effect)
yazses mic-level --set # 2. tune the silence gate to your voice (~4 s)
yazses start # 3. start dictating
The log-out/in is mandatory and one-time. Group membership only refreshes in a new login session — opening another terminal tab is not enough, because it inherits the old session's groups and the hotkey stays dead. To dictate immediately without logging out, bridge the group for one session:
Verify anytime — you want [OK] Keyboard capture, [OK] Microphone, [OK] Injection:
Then hold the hotkey (default right_alt), speak, release — the text types into whatever field has focus. That's it; the rest of this page is reference.
3. Installing by hand (what the installer did for you)¶
Skip this if §1 worked — it is for people installing with pipx, or who want to understand the pieces.
Order matters: the package first, provisioning second. yazses setup is a subcommand of YazSes, so it cannot run until YazSes is installed:
sudo apt install -y pipx build-essential python3-dev # pipx + the evdev build toolchain
pipx install yazses # 1. install the CLI
yazses setup # 2. now provision the system
# then log out and back in (the input-group change needs a fresh login)
yazses setup installs the audio + injection packages, joins you to the input group and sets up ydotoold on Wayland. It is idempotent (safe to re-run — it only fixes what's missing) and finishes by printing the §2 checklist, offering to run the mic calibration for you there and then.
The remaining sub-sections spell out what yazses setup does, for when you want to do each piece yourself.
3a. Runtime dependencies¶
Install every runtime dependency in one command (the APT .deb pulls these in automatically, so skip this if you used install-apt.sh):
What each is for:
| Package | Role | Needed when |
|---|---|---|
libportaudio2 | Audio capture — sounddevice loads it at import | Always (else the daemon crashes on start: OSError: PortAudio library not found) |
xdotool | Text injection (X11) | X11 sessions |
xclip | Clipboard fallback (X11) | X11 sessions |
wtype / ydotool | Text injection (Wayland) | Wayland sessions |
wl-clipboard | Clipboard fallback (Wayland) — provides wl-copy | Wayland sessions |
pipx | Installs the yazses CLI | If installing via pipx |
Installing all of them makes YazSes work whether you log into X11 or Wayland — at runtime YazSes auto-selects the right backend (inject/auto.py). You also need membership in the input group (§3b) and a working microphone (PipeWire/PulseAudio/ALSA).
3b. Add yourself to the input group (required)¶
The hold-to-talk hotkey is read directly from the kernel input devices (/dev/input/event*), which are owned by the input group. If your user is not in that group the daemon cannot detect the hotkey and dictation never starts (yazses doctor reports [FAIL] Keyboard capture: denied).
Then log out and back in (or reboot) — group membership only refreshes on a new login session. Opening another terminal tab is not enough: it inherits the old session's groups, so the hotkey stays dead and yazses doctor still reports [FAIL] Keyboard capture (that line reflects the shell running doctor, not a running daemon). Confirm it took effect:
id -nG | tr ' ' '\n' | grep -x input # should print: input
yazses doctor # should show [OK] Keyboard capture
Do this before starting the daemon (§2). yazses start/restart will warn you if this re-login is still pending. To dictate immediately without logging out, bridge the group for one session:
After a real re-login, a plain yazses start just works — no bridge needed.
3c. Wayland keystroke injection — ydotoold (GNOME/KDE Wayland)¶
How text gets typed depends on your session:
| Session | Injector | Notes |
|---|---|---|
| X11 | xdotool | works out of the box |
| Wayland — wlroots (Sway, Hyprland, …) | wtype | works out of the box |
| Wayland — GNOME / KDE | ydotool + ydotoold | wtype is blocked by Mutter/KWin; ydotool injects at the kernel /dev/uinput level and is the only reliable option |
On GNOME/KDE Wayland you must run the ydotoold daemon, or injection fails with failed to connect socket … .ydotool_socket. yazses setup configures this for you; to do it manually, install the user service:
mkdir -p ~/.config/systemd/user
cp /usr/lib/systemd/user/ydotoold.service ~/.config/systemd/user/ 2>/dev/null \
|| curl -fsSL https://raw.githubusercontent.com/MSKazemi/yazses/main/contrib/ydotoold.service \
-o ~/.config/systemd/user/ydotoold.service
systemctl --user daemon-reload
systemctl --user enable --now ydotoold.service
ls -l /run/user/$(id -u)/.ydotool_socket # socket should now exist
ydotoold runs as your user (no root) because /dev/uinput is owned by the input group (§3b). After this, yazses doctor shows [OK] Injection and [OK] ydotoold.
3d. What gets installed¶
The script, APT and pipx all install six commands into ~/.local/bin (make sure that's on your PATH): yazses, yazses-daemon, yazses-tray, yazses-settings, yazses-agent, yazses-overlay. The APT path also links yazses and yazses-daemon into /usr/bin. The Snap instead exposes yazses, yazses-daemon, yazses-tray and yazses-overlay on /snap/bin, which is already on your PATH.
If an old
alias yazses=...exists in your shell rc pointing at a previous build, remove it so the installed binary is used.
Working on YazSes itself? Clone the repo and run bash scripts/dev-install.sh — an editable install plus provisioning plus start, in one command.
3e. What the snap can and cannot do¶
A strictly confined snap cannot install packages on the host, change group membership, or configure the host's ydotoold service. Therefore:
- hold-to-talk dictation works on X11, and on GNOME/KDE Wayland through the
xdg-desktop-portalRemoteDesktop API — the one Wayland injection route that needs no/dev/uinput, no udev rule and no extra interface, because portal access rides on thedesktopplug the snap already has. The first dictation asks once for permission; approve it and the answer is remembered. Both cases still require manually connectingaudio-recordandraw-inputas shown in §1; wtypeis not a Wayland fallback here: it needsvirtual-keyboard-manager-v1, which GNOME's Mutter and KDE's KWin do not implement. The portal is what covers those two desktops;- the unconfined installers (universal, APT,
pipx) remain the most-tested Wayland path, and useydotool+ydotooldinstead of the portal; yazses setupcannot provision a Snap install; current builds only use it to print the manual interface checklist.
Only the three snap install/snap connect commands require sudo. Run yazses doctor, yazses start, and every other YazSes command as your normal desktop user; sudo yazses … loses the session environment and reports the wrong display type.
A snap ships a fixed set of Python libraries. Its files are read-only, so yazses features enable <name> cannot download anything into it the way the other channels can — whatever is bundled in a revision is all that revision will ever have.
Everything needed for dictation is bundled, plus the capabilities whose libraries fit inside a snap:
| Capability | In the snap? | Why |
|---|---|---|
| Dictation, commands, tray, overlay, mic guard, target guard | ✅ | Part of the base install |
stt-parakeet — higher-accuracy English engine | ❌ | onnx-asr is the optional parakeet extra and is not bundled in the snap |
meeting, recimport, diarize — Meeting Mode and diarized import | ✅ | sherpa-onnx is bundled |
read-back — spoken read-back of what you dictated | ✅ | kokoro-onnx + soundfile are bundled |
cocktail — Cocktail Filter | ❌ | speechbrain pulls PyTorch (~1 GB) |
llm-cleanup — offline LLM reformatting | ❌ | llama-cpp-python has no PyPI wheels; needs a compiler |
gaze — Glance-Type | ❌ | mediapipe + opencv cost ~110 MB, and it needs a webcam and X11 |
prosody — prosody-aware punctuation | ❌ | praat-parselmouth publishes no aarch64 wheel |
Enabling one of the ❌ rows inside the snap refuses with an explanation rather than failing halfway through — the config is left untouched, so nothing reads as "on" while being unable to work.
To use those five, install through any other channel:
Note that settings do not carry over: the snap keeps config and models under ~/snap/yazses/, an unconfined install under ~/.config/yazses.
3f. Arch Linux and derivatives (AUR)¶
Not on the AUR yet —
yay -S yazseswill not find it. The recipe below is written, current and verified, but the package has never been published:aur.archlinux.orgreturns noyazses(checked 2026-10-21), soyay -S yazsesandparu -S yazsesstop with target not found. That is the AUR missing the package, not a broken helper. Publication is blocked upstream — AUR account registration was paused on 2026-09-19 with no announced ETA. Until it lands, use the universal installer (§1) orpipx(§3), or build the package yourself from the recipe, which is what the rest of this section covers. Progress: #67.
Build it from the recipe in the repository:
Install the two AUR dependencies with a helper first. python-faster-whisper and python-sounddevice are AUR packages, and faster-whisper pulls a further chain of its own — python-ctranslate2 and python-tokenizers from the AUR, python-av and an onnxruntime provider from extra. makepkg never fetches AUR dependencies by design; only a helper resolves them recursively. So run yay -S python-faster-whisper python-sounddevice before makepkg -si, or the build stops with target not found — which looks like a broken PKGBUILD and is not one.
The PKGBUILD is built from the PyPI sdist — the artifact the release actually publishes, with a checksum that is stable and quotable — rather than a GitHub tag tarball.
Verify it yourself on a clean Arch container:
That script checks the PKGBUILD parses, that .SRCINFO matches it (the file the AUR refuses a push without), builds and installs the package, and runs yazses --version. It deliberately does not claim yazses doctor end to end, because the AUR chain above is the helper's job and is not present in a bare container.
3g. NixOS and Nix (flake)¶
nix run github:MSKazemi/yazses # run it without installing
nix profile install github:MSKazemi/yazses
The flake is at the repository root and exposes yazses (headless — dictation, commands, transcription) and yazses-desktop, which adds Qt for the tray icon and the voice-activity overlay. Splitting them is deliberate: Qt is about 648 MB, and a server transcribing files should not pull it in.
nix flake check passes for x86_64-linux. Verify it without installing Nix:
Not verified: aarch64 and Darwin —
nix flake checkomits systems it cannot evaluate on, so those rows are unproven rather than broken. Nobody has installed this from a real NixOS machine either; if you do, say what happened.
3h. Fedora and the RHEL family (COPR)¶
The repository is live at copr.fedorainfracloud.org/coprs/mskazemi/yazses, serving 2.36.0 for Fedora 43 and 44 (x86_64 and aarch64) and EPEL 10 (x86_64) (repository metadata checked 2026-09-25).
COPR trails the newest release. Each version is pushed to COPR by hand, so
dnf install yazsesgives you 2.36.0 rather than the current tag. Checkyazses --versionagainst the latest release; if you need the newest build, use the universal installer (§1) orpipx(§3).
EPEL 9 is not offered, and that is a limitation rather than an oversight: it ships Python 3.9, so python3-devel >= 3.11 cannot be satisfied there. RHEL 9 users need another route — pipx install yazses under a Python 3.11+ interpreter (RHEL 9 ships python3.11 as a separate package) is the practical one. The three commands above were run end to end in a clean fedora:43 container: dnf copr enable → dnf install → yazses --version printing yazses 2.36.0.
The spec lives at packaging/fedora/yazses.spec. packaging/fedora/build-and-test.sh builds and installs it locally, and is meant to be run in a container rather than on your machine:
That local test cannot catch everything
Docker and podman give a build network access by default; COPR does not. Because %install runs pip to populate the bundled virtualenv, the first COPR build failed where the container build had passed — and it failed as No matching distribution found for hatchling, which reads like a missing dependency rather than a missing network. The project now sets --enable-net on. Only a real COPR build could have found it.
Two honest notes about this package:
- It bundles its Python dependencies into a private virtualenv under
/usr/lib64/yazses, which makes the installed size about 380 MB. The idiomatic Fedora approach would declare each dependency as apython3dist(...)require, and that is not possible today: faster-whisper, ctranslate2 and onnx-asr are not in the Fedora repositories, and a spec that declared them would fail dependency generation on a clean build. Bundling is acceptable for a COPR and is not acceptable for the official Fedora repositories — getting there means packaging that dependency tree first. portaudiois a hard requirement; the injection tools are not.xdotoolandxclipare Recommends,ydotoolandwl-clipboardare Suggests, because transcribing files withyazses transcribeneeds none of them and a hard dependency would drag an X11 stack onto a headless machine.
After installing, yazses doctor will still ask you to join the input group (§3b) — that is a system-level change no package can make on your behalf, and it needs a full logout.
Status: live, but hand-published — it serves 2.36.0 while the current release is 2.51.0.
4. Start at login¶
Usually already done. yazses start sets this up once the daemon is up, whichever way you installed — so if you have started YazSes at least once, it will be running again after the next reboot. It says so the one time it does it, and does nothing on later starts.
To skip it, yazses start --no-autostart. To do it explicitly — or to redo it after disabling — it is one command:
That writes a systemd user service pointing at this install, enables it, and starts it. Check it any time:
yazses autostart status # will YazSes be running after the next reboot?
yazses doctor # includes a "Starts at login" check
yazses autostart disable turns it off again, and it stays off: a later yazses start does not turn it back on, and doctor shows it as your choice rather than a problem. yazses autostart enable reverses it.
The service restarts YazSes automatically if it ever crashes — verified by killing it outright, it is back within about five seconds — and gives up after five failures in a minute so a genuinely broken machine leaves a diagnosable state instead of a spin loop.
Display access. X11 injection needs
DISPLAYandXAUTHORITY, which the unit takes from the systemd user manager viaPassEnvironment. GNOME/GDM export them there automatically; confirm withsystemctl --user show-environment | grep DISPLAY. If they are missing, add them to the unit explicitly withsystemctl --user edit yazses.service, or runsystemctl --user import-environment DISPLAY XAUTHORITYfrom inside your session. Without them, dictation runs and the text goes nowhere.
Writing the unit by hand instead
`yazses autostart enable` is the supported path, and it keeps the unit correct across upgrades that move the binary. If you would rather manage it yourself, the unit it installs lives at `~/.config/systemd/user/yazses.service`; `contrib/yazses.service` in the repo is the same file.5. Use it¶
- Focus any text field.
- Hold the hotkey (default
right_alt), speak, release. - The transcript types in once.
The log holds timing and state, never what you dictated — unless you set [general] log_level = "DEBUG", which also records each transcript.
6. Tune the silence threshold¶
If dictation does nothing and yazses logs shows Silent audio -- discarding, your speech is below the VAD gate. Measure and set it:
yazses mic-level --set # records ~4s; writes a fitting vad_threshold
yazses restart # a running daemon ignores a changed threshold until restarted
yazses restart works with or without the systemd unit: it stops every daemon and starts exactly one, through the unit when one is installed.
Re-run whenever your speaking volume changes (e.g. quiet late-night dictation).
7. Manage the service¶
systemctl --user restart yazses.service # after a config change
systemctl --user stop yazses.service # stop
systemctl --user disable --now yazses.service # stop + remove autostart
journalctl --user -u yazses.service -f # live logs via journald
Config lives at ~/.config/yazses/config.toml. See the CLI reference for all commands.
8. Troubleshooting: the hotkey does nothing¶
If holding the key records nothing (no transcript, no overlay reaction), run the health check first — it now pinpoints every common cause in one shot:
Look for these lines and act on any that are not [OK]:
Hotkey device: bound to virtual device …— the daemon is listening on an injector's virtual device (e.g.ydotoold virtual device) instead of your real keyboard, so your keypresses are never seen. Make sure you are in theinputgroup (groups | grep input; if missing, §3b, then log out and back in) so the real keyboard is readable. Fixed in v1.3.3+, which skips virtual devices automatically; older builds need an upgrade.systemd unit: ExecStart=… does not exist— the service points at a binary that isn't there (a leftover from a different install method), so it crash-loops withstatus 203/EXECandyazses start/restartsilently start nothing. Point the unit'sExecStartat your real binary (which yazses-daemon) andsystemctl --user daemon-reload && systemctl --user restart yazses.Install: multiple yazses on PATH …— you have more than one copy installed (e.g. apt + pipx + uv tool). Keep one and uninstall the rest so an upgrade can't leave you running stale code:pipx uninstall yazses,sudo apt remove yazses, oruv tool uninstall yazsesas appropriate.Keyboard capture: FAIL— you are not in theinputgroup; see §3b.
If yazses logs shows Silent audio -- discarding, the key is working but your speech is below the VAD gate — see §6.
Tip: manage the daemon with
systemctl --user restart yazseswhen a systemd unit exists; mixingyazses start(detached) with a systemd unit can leave two daemons fighting over the hotkey, or none running at all.
9. Voice-activity overlay¶
The overlay draws neon "sonar" rings near the cursor that pulse with your voice while you dictate. It is optional and off by default: turn it on with yazses features enable overlay. The universal installer, the .deb and the snap already include Qt (PySide6); a plain pipx install yazses does not, and features enable overlay downloads it (~268 MB) on demand. On Ubuntu/GNOME Wayland an overlay can take keyboard focus and swallow the dictated text — see Troubleshooting. The PySide6 wheels need glibc ≥ 2.28 (Ubuntu 20.04+); on older distros the daemon logs a one-line hint and keeps dictating.
Once enabled, the daemon auto-launches yazses-overlay on start when a display is present and terminates it on shutdown. If PySide6 isn't installed the daemon logs a one-line hint and keeps dictating — nothing breaks. To turn the overlay off again, run yazses features disable overlay or set [overlay] enabled = false in ~/.config/yazses/config.toml. Run yazses overlay yourself to preview it.
Transparency note (X11): the see-through glow needs a compositing window manager. If you run a bare WM without one, install picom:
Without a compositor the rings still render, just on a small opaque panel.
To autostart it as its own user service instead of letting the daemon spawn it, create ~/.config/systemd/user/yazses-overlay.service with ExecStart=%h/.local/bin/yazses-overlay, Environment=DISPLAY=:0, and After=yazses.service, then systemctl --user enable --now yazses-overlay.