Capability matrix¶
Which features work where, taken from the backends that actually ship in src/yazses/platform/ and the checks yazses doctor runs.
Looking for whether it installs on your machine?
This page assumes YazSes is installed and answers "does this feature work in my session". For operating systems, CPU architectures and install channels — including BSD and what happens on an OS with no backend — see platform support.
Run yazses doctor before reading this. It reports your machine rather than the general case, and it names the fix for anything missing.
The matrix¶
| Capability | Linux / X11 | Linux / Wayland | macOS | Windows |
|---|---|---|---|---|
| Hold-to-talk hotkey | ✅ evdev | ✅ evdev | ✅ | ✅ |
| Text injection | ✅ xdotool | ✅ ydotool¹ | ✅ | ✅ |
| Clipboard fallback | ✅ | ✅ | ✅ | ✅ |
| "No text target" guard | ✅ AT-SPI² | ✅ AT-SPI² | ⚠️ best-effort | ⚠️ best-effort |
| System tray | ✅ Qt | ✅ Qt | ✅ rumps | ✅ pystray |
| Tray input-level ring | ✅ | ✅ | ❌ see ³ | ❌ see ³ |
| Earcon state cues (eyes-free) | ✅ | ✅ | ✅ | ✅ |
| Command safety gate, check digits | ✅ | ✅ | ✅ | ✅ |
| Voice-activity overlay | ✅ | ✅ | ✅ | ✅ |
| Autostart at login | ✅ systemd | ✅ systemd | ✅ launchd | ✅ HKCU\Run |
Offline transcription (transcribe) | ✅ | ✅ | ✅ | ✅ |
| Meeting Mode, diarization | ✅ | ✅ | ✅⁴ | ✅⁴ |
| Voice window focus ("focus the browser") | ✅ xdotool | ❌ not possible | ❌ | ❌ |
| Glance-Type gaze routing | ✅ | ❌ not possible | ❌ | ❌ |
| EMG / BrainFlow activation (experimental, no real-device evidence) | ✅ | ✅ | ✅ | ✅ |
³ The level ring is drawn by the Qt tray, which repaints on the 0.15 s recording poll. The macOS and Windows trays render through rumps/pystray and repaint far less often, so the ring would lag the thing it reports. The earcons carry the same information on every platform, and audio is the channel that works when the tray is not being looked at anyway.
⁴ This applies to installs made with pip, pipx or uv. The macOS .dmg and the Windows .exe cannot add the speaker-label libraries afterwards, so Meeting Mode and diarization need the PyPI install there today. A Windows diarization add-on is prepared on main but not released: its sherpa-onnx binaries embed GPL code, so it is held back.
¹ Wayland needs ydotool and a running ydotoold; wtype works only on wlroots compositors and is blocked on GNOME and KDE. For a non-Snap install, yazses setup installs and enables the right one. ² Needs python3-pyatspi + gir1.2-atspi-2.0 from your package manager (not pip). Without it the guard still works, but by best-effort window heuristics.
Why the two ❌ rows are not bugs¶
Wayland forbids one application from focusing or reading another's window. That is the security model working as designed, and no portal exposes the capability today. So voice window control and look-to-pane gaze routing are X11-only, and YazSes reports them as unavailable rather than offering a feature that silently does nothing. Layout commands your compositor binds itself are unaffected.
Everything else on Wayland — dictation, commands, the tray, the overlay, transcription — works normally.
What Glance-Type does on Wayland¶
Look-to-pane needs three separate things from the desktop: an absolute screen position for your gaze, the position and size of other applications' windows, and permission to focus one. X11 provides all three. A Wayland application is given none of them, and the Remote Desktop permission that lets YazSes move the pointer (Head-Pointer) does not change that: pointer control and "which window should get this dictation" are separate capabilities.
So on Wayland there is no gaze target. Look-to-pane stays off, your dictation goes to the window you already have focused, and nothing is guessed. yazses gaze status and yazses doctor say so, with the reason, instead of showing a feature that silently does nothing. To use look-to-pane, log in to an X11 session (on GNOME, "GNOME on Xorg").
Exactly what Glance-Type does and does not do on a Wayland session (GNOME, KDE Plasma, Sway, Hyprland and the rest):
| On Wayland | |
|---|---|
| Send dictation to the window you look at | No. Dictation goes to the window that already has focus. |
| Focus or raise the window you look at | No. |
| "close this" / "minimize this" / "focus that" | Refused, with a notification. Nothing is closed, and the command is never sent to the focused window instead. |
Gaze calibration (yazses gaze calibrate) | Refused, because nothing could use the result. |
| Head-Pointer (moving the pointer with your head) | A separate feature. It uses the Remote Desktop permission, and granting that permission does not create a gaze target. |
yazses gaze status prints the row for your session, for example screen position: no; other windows' geometry: compositor-specific only; focus another window: compositor-specific only; pointer injection (separate, not a target): with permission. "Compositor-specific only" means a desktop offers the capability only through its own private interface, such as KWin scripting or a GNOME Shell extension. YazSes does not depend on any of those.
Below that row, yazses gaze status lists what Glance-Type does on this session: the table above, for your session. yazses doctor, yazses status and the hands-free controls window print the same list on the Gaze target row. On X11 the list also says what "close this" does when gaze cannot pick a window. By default it closes the focused window without asking. With [gaze] refuse_destructive_fallback = true it is refused.
These Wayland answers come from protocol documentation and toolkit source code. Nobody has yet watched them on a live GNOME or KDE session, so they are unverified on real hardware. The checks still to run are listed in the design spec.
Linux: which session am I in?¶
echo $XDG_SESSION_TYPE # x11 or wayland
yazses doctor # reports the same, plus the injector it will use
Known platform-specific traps¶
- Linux — hold-to-talk reads the keyboard through evdev, so a non-Snap install needs the
inputgroup and a full logout, not a new terminal.yazses doctorsays when that is pending. The Snap instead needs itsraw-inputinterface connected manually, and dictates on X11 or on GNOME/KDE Wayland through thexdg-desktop-portalRemoteDesktop API; the universal installer, APT andpipxremain the most-tested Wayland path. - macOS — Accessibility and Microphone permissions are per-binary. An update that changes the app's identity re-prompts. Input Monitoring is read when the daemon starts, so a grant given while it runs needs a restart;
yazses doctorsays when the running daemon started before the grant, and the macOS troubleshooting section covers the menu-bar icon restarting an idle daemon by itself (tested with simulated daemons only). - Windows — an app running as administrator does not receive input from a non-elevated process (User Interface Privilege Isolation). Dictation into Task Manager or an elevated PowerShell silently does nothing unless YazSes is elevated too;
yazses doctorreports which case you are in. The microphone switch "Let desktop apps access your microphone" governs the.exe, pip, winget, Scoop and Chocolatey installs but not the Store (MSIX) build, which has its own YazSes entry in the same settings page (microphone access).
Camera permission and packaging¶
The camera features — Glance-Type gaze routing, the Face-Gesture Switch and the Head-Pointer — are experimental and off by default. With all of them off, YazSes never asks your operating system about the camera, so it can never raise a camera permission prompt.
Turning one on raises a second question that has nothing to do with permissions: can the copy of YazSes you installed run a camera feature at all? Frozen and confined packages cannot. The .dmg, the Windows .exe, the MSIX, the snap and the flatpak are all built without mediapipe and opencv-contrib-python, and none of them can install a Python package afterwards.
That is why none of them asks for camera access. A camera capability a package cannot use is a permission request with no upside — you would be asked to trust something no code in that download could do.
| Install format | Camera features | OS declaration it would need | Declared today |
|---|---|---|---|
| a source / PyPI install (pip, uv, pipx) | ✅ with the extra | — | ❌ no |
| a distribution package (AUR, Fedora, Nix) | ✅ with the extra | — | ❌ no |
| the macOS .app bundle (.dmg / Homebrew cask) | ❌ no | NSCameraUsageDescription + com.apple.security.device.camera | ❌ no |
| the Windows installer (.exe, also via Chocolatey, Scoop and WinGet) | ❌ no | — | ❌ no |
| the Windows MSIX package | ❌ no | DeviceCapability webcam | ❌ no |
| the snap | ❌ no | camera plug | ❌ no |
| the flatpak | ❌ no | --device=all | ❌ no |
If you need the camera features, install from PyPI — pipx install 'yazses[gaze]' — and then yazses features enable gaze.
In those five formats yazses features enable gaze (and facegesture, headpointer, yazses handsfree enable, and the tray's Hands-free panel) refuses before it writes your config. It says the package cannot add libraries and names the PyPI install. The camera feature is never switched on in a package that could not run it.
yazses doctor grows a Camera row as soon as a camera feature is enabled, and it tells the four causes apart: a package that cannot run one, a missing mediapipe / opencv-contrib-python, no camera device, and a refused or not-yet-granted OS permission. It never reports access it could not confirm — an undetermined permission is reported as undetermined, not as granted.
Adding a platform¶
Implement the Protocol interfaces in src/yazses/platform/<os>/ and register the sys.platform value in platform/factory.py; the daemon and CLI need no other change. src/yazses/platform/bsd/ is the worked example, at about 60 lines — see platform support and the architecture guide.
An OS with no backend is still useful: transcribe and the text commands never touch the platform layer.