Skip to content

v2.16.0 — the snap becomes whole

Released 2026-08-09. Upgrade:

sudo snap refresh yazses     # snap
pipx upgrade yazses          # or: uv tool upgrade yazses

The bug: a snap can never install anything into itself

yazses features enable <name> installs a capability's optional Python packages on demand. That works for every install channel except the one where it silently could not: a snap.

A snap's payload is a read-only squashfs, and the Python we stage is Debian's, which ships a PEP 668 EXTERNALLY-MANAGED marker. Two independent blockers, so pip refuses no matter which flags it is given. YazSes did not know that. It ran pip anyway, and handed the user Debian's error:

error: externally-managed-environment
... try apt install python3-xyz ...
... create a virtual environment using python3 -m venv ...
... it may be easiest to use pipx install xyz ...

Three suggestions, none of which a confined user can act on, and the last of which is the very thing they chose not to do.

Worse, the config key had already been written by the time pip failed. So the capability read as enabled while nothing could ever honour it — precisely the lie features enable already refuses for unwired features.

Auditing the published snap showed the scale: of the 15 capabilities carrying optional Python packages, only two had their libraries aboard. Eight wired capabilities were unreachable for the entire life of every revision — including Meeting Mode.

The fix, on both sides

The snap bundles what fits

Bundled Unlocks
sherpa-onnx meeting, recimport, diarize — Meeting Mode, diarized import, speaker labels
kokoro-onnx + soundfile read-back — the spoken read-back voice

Every bundled package must publish manylinux wheels for x86_64 and aarch64, because the snap builds both and a single-arch dependency fails the arm64 build outright.

What cannot fit refuses honestly, before writing config

Not bundled Why
speechbrain (cocktail) pulls PyTorch, ~1 GB — dwarfs the snap
llama-cpp-python (llm-cleanup) publishes no PyPI wheels; needs a compiler
mediapipe + opencv (gaze) ~110 MB for an experimental webcam feature
praat-parselmouth (prosody) no aarch64 wheel — would break the arm64 build

Enabling one of those inside a snap now explains why, names the packages, and gives the one instruction that works — while noting that config and models do not carry across to an unconfined install. The gate is precise, not a blanket refusal: a capability whose libraries are bundled still enables normally.

yazses settings had the same defect — it wrote the config keys and then reported the missing packages, pointing at a features enable that refuses for the same reason. It refuses before writing too. Turning a capability off is never blocked: that installs nothing, and a locked environment must not trap you with a setting you cannot switch back.

The same gate also catches the general case of an unwritable site directory, such as a root-owned install run as a normal user.

Verified on the real artifact

Not on a build log — the published snap was downloaded, unpacked, and its own interpreter run against its own site-packages:

  • sherpa_onnx, kokoro_onnx, soundfile, onnxruntime, onnx_asr, espeakng_loader — all import
  • features enable meeting and read-back → enable
  • features enable cocktail --force → refuses, and writes nothing to config.toml

On arm64, the native binaries were confirmed to be genuinely ARM aarch64 (libsndfile_arm64.so, libespeak-ng.so), with the espeak-ng-data Read-Back needs.

Community testing is tracked in issue #142arm64 at runtime is the one surface nobody has exercised yet.

Also in this release

  • yazses settings — a settings window generated from the feature registry, so the GUI and the CLI cannot drift. Thanks to @waterlemonnn (PR #134).
  • The contract pins meaning, not only parity (contract 5.1.0) — minimal pairs caught five filler-word bugs that byte-parity vectors could not see.
  • man yazses, generated from the CLI so it cannot drift.
  • [stt] language is real. It was documented but never implemented: every decode path hardcoded language="en", so non-English dictation never worked.
  • install.sh now checks the two hard prerequisites it previously assumed.

Snap users: two interfaces still need connecting

Snap confinement does not auto-connect these, and without them the microphone and the hold-to-talk key both stay dead:

sudo snap connect yazses:audio-record
sudo snap connect yazses:raw-input

See issue #44 — joining the input group cannot grant keyboard capture inside a snap, only the raw-input interface can.