Changelog¶
All notable changes to EasySpeak are documented here. This file is the canonical, GitHub-independent record of releases. It is updated once per release. The format loosely follows Keep a Changelog, and the project adheres to Semantic Versioning.
0.7.0 · Offline by Default · 2026-07-01¶
A Strict Offline Switch, a Clean Abort When the Model Is Missing, and --preview
A single EASYSPEAK_OFFLINE variable now governs whether EasySpeak may reach
the network, and it defaults to strict — nothing is fetched at runtime unless
you opt in, true to the fully-local ethos. The recognition model loads locally
first, so a bundled or previously-cached model needs no network at all. When it
is missing under the default, startup aborts cleanly: an actionable message
(set EASYSPEAK_OFFLINE=relaxed to download it, or install a language pack) and
a non-zero exit, mirroring the existing no-microphone handling. Set relaxed to
opt into the on-demand base.en download from Hugging Face, announced with a
warning.
A CLI-usability fix renames the one-shot --show desktop-integration option to
--preview, aligning the mental model of the two paired options: --preview
now prints exactly what --configure would install, so the two read as a single
preview-then-apply gesture rather than an odd show/configure mismatch. It also
takes exactly one item, since concatenating several files to stdout served no
purpose. Under the hood the data and extension folders move back under src/, the
packaging tests gain a README, and the GitHub Releases workflow is documented in
CONTRIBUTING.
What's Changed¶
- Gate implicit Whisper downloads behind
EASYSPEAK_OFFLINEby @bittner in #114 - Rename
--showCLI option to--previewby @bittner in #113 - Move data and extension folders back to
src/by @bittner in #111 - Add README for the packaging tests by @bittner in #112
- Document the GitHub Releases workflow in CONTRIBUTING by @bittner in #110
Full Changelog: 0.6.0...0.7.0
0.6.0 · Made to Configure · 2026-06-30¶
Configurable Chimes, a Single Hotkey Variable, and Versioned Docs
EASYSPEAK_* environment variables now drive cross-platform/distro configurability:
rather than carrying platform-specific patches, EasySpeak exposes whatever
differs between systems as a variable you set — and documents every one of
them in the generated reference. The wake and sleep chimes, for one, stayed
silent under uv run easyspeak in the Nix dev shell (they only played under
nix run, which rewrote the freedesktop sound path that doesn't exist on
NixOS); instead of special-casing NixOS, the sound directory now lives behind
a new EASYSPEAK_SOUNDS_DIR variable. The two hotkey variables collapse into
one: EASYSPEAK_HOTKEY now holds the combo itself (default ctrl+shift; set
it empty or to off/none to disable), with a mistyped combo logging a
warning and disabling the listener instead of silently arming a dead key.
The documentation site moves to mike's native versioning, so the version
selector switches in place and always knows which version it is on. The
in-development docs from main now serve at /latest/, the most recent
release at /stable/, and every tagged release stays archived under its own
/<version>/ path.
What's Changed¶
- Make desktop sounds configurable, document env vars by @bittner in #103
- Serve main docs at the root, redirect
/latestto it by @bittner in #104 - Tidy the docs deploy scripts and names by @bittner in #106
- Consolidate the env-var reference in the Usage guide by @bittner in #105
- Switch docs deploy to mike's convention by @bittner in #107
- Merge the two HOTKEY env vars and validate the combo by @bittner in #108
Full Changelog: 0.5.0...0.6.0
0.5.0 · New Domain, Modular Extension · 2026-06-30¶
Quick Settings, the easyspeak.dev Domain, and a Modular Extension
EasySpeak gains a GNOME Quick Settings toggle as an alternative to the panel tray icon, and the extension's Settings dialog grows desktop-integration controls and a Website link. Under the hood the wake-word engine is swapped to pyopen-wakeword and the default Python moves to 3.14, while spawned desktop apps no longer inherit the dev shell's libraries — so the file manager and friends launch against their own.
The project also settles into its own easyspeak.dev domain everywhere, and
the GNOME extension moves into a UUID folder (gnome@easyspeak.dev), splits from
a monolith into compositor-only ES modules behind a thin entrypoint, and now
derives its per-user autostart entry from the canonical desktop file instead of a
drifting copy. Rounding it out: CI is hardened with lint, link-checking, and
packaging verification; the distro-package checks are grouped behind a single
build; and the extension-refresh unit no longer fails when its uv interpreter
has vanished.
What's Changed¶
- Swap wake-word backend to pyopen-wakeword and bump default Python to 3.14 by @bittner in #93
- Add a Quick Settings toggle as an alternative to the tray icon by @bittner in #96
- Add extension Settings dialog, desktop integration, and Website link by @bittner in #91
- Stop leaking dev-shell libraries into spawned desktop apps by @bittner in #95
- Use the newly acquired easyspeak.dev domain everywhere by @bittner in #98
- Move GNOME extension to a UUID folder, rename to gnome@easyspeak.dev by @bittner in #100
- Split GNOME extension into ES modules; consolidate autostart entry by @bittner in #101
- Fix extension-refresh unit failing on a vanished uv interpreter by @bittner in #89
- Harden CI: lint, link check, packaging verification, and release fold by @bittner in #97
- Group the distro package checks; rename "native" → "distro" by @bittner in #102
- Add a tray icon and menu screenshot, reduce file sizes by @bittner in #94
- docs: Show the tray menu and Quick Settings side by side by @bittner in #99
Full Changelog: 0.4.0...0.5.0
0.4.0 · Packaged and Polished · 2026-06-24¶
Native Packages & a Docs Site
EasySpeak now ships as native Debian (.deb) and Fedora (.rpm) packages, with
the language data split into separate packages so you install only the voices
you need. Dictation now actually works — backed by a proper AT-SPI backend that
reports failures honestly instead of silently doing nothing — and gains a silent,
keyboard hold-to-dictate activation for when you'd rather not speak the wake
word. The GNOME tray grows an About dialog and a Help entry, and the extension
is renamed simply "EasySpeak".
Under the hood, terminal output moved from print() to structured logging, the
codebase adopted Ruff's full "ALL" ruleset with curated exceptions, and a batch
of post-0.3.0 review findings were cleaned up; EasySpeak also fails gracefully
now when an audio device or gdbus is missing. Rounding it out is a hosted MkDocs
and Material documentation site on GitHub Pages — complete with screenshots and
Git-LFS-tracked media — while CI is streamlined onto main as the dev branch
is phased out.
What's Changed¶
- feat(packaging): native
.deb/.rpmwith split language data by @bittner in #77 - Make dictation work: provide the AT-SPI backend and report failures honestly by @bittner in #69
- feat(core): silent (keyboard) hold-to-dictate activation by @bittner in #70
- feat(tray): add About dialog and Help to the tray menu by @bittner in #73
- refactor(extension): rename "EasySpeak Grid" to "EasySpeak" by @bittner in #74
- Switch terminal output from
print()to logging by @bittner in #68 - Adopt Ruff "ALL" ruleset with curated exceptions by @bittner in #65
- fix: address post-0.3.0 review findings (browser-launch trap, AT-SPI caret, hotkey shutdown) by @bittner in #72
- Fail gracefully when audio device or gdbus is missing by @bittner in #86
- docs: hosted MkDocs + Material + mkdocstrings site on GitHub Pages by @bittner in #71
- Integrate screenshots in documentation by @bittner in #85
- Serve latest docs at site root, check dead links in README by @bittner in #84
- Track media files with Git-LFS, move images to docs/media by @bittner in #83
- Fix docstring markup (reStructuredText ➜ MarkDown) by @bittner in #81
- Trigger CI workflows on main only, phasing out dev by @bittner in #87
- Fix broken docs screenshots, skip demo video in CI by @bittner in #88
Full Changelog: 0.3.0...0.4.0
0.3.0 · Smoother and More Conversational · 2026-06-13¶
Tray Icon & Instant Feedback
This release puts EasySpeak in your GNOME tray — a status indicator with voice deactivate — and makes it feel snappier by speaking feedback in parallel with carrying out your command: the spoken reply now starts playing while the action runs, instead of only after it has finished. It also adds native on-screen displays and chimes for volume and brightness via media keys, and a persistent Piper process that loads the voice model once for faster speech. EasySpeak now owns the full GNOME-extension lifecycle — shipped as package data, staged so a failed refresh can't corrupt an install, and time-bounded against hanging system calls. The interaction model grew more conversational too: it keeps listening between commands without repeating the wake word, handles "stop" gracefully instead of quitting, and gives friendlier misunderstanding feedback — backed by new integration/acceptance test tiers and a 99% coverage floor.
What's Changed¶
- feat(apps): add more GNOME apps, handle default terminal by @bittner in #57
- perf(tts): load the voice model once via a persistent piper process by @bittner in #56
- refactor(core): new
speechmodule, suppress ALSA error output by @bittner in #58 - feat(system): native OSD for volume and brightness via media keys by @bittner in #61
- feat(core): GNOME tray indicator with voice deactivate by @bittner in #59
- test(extension): extract pure JS helpers and unit-test them by @bittner in #60
- Improve voice interaction: friendlier feedback, parallel replies, richer commands, hands-free chaining by @bittner in #63
Full Changelog: 0.2.0...0.3.0
0.2.0 · Broader Reach · 2026-06-07¶
Runs in More Places
EasySpeak broadens where and how it runs: installation now works on Python 3.13
(with dependencies pinned for 3.10), pyaudio ships as a dependency, and a new
Nix flake supports development and running on NixOS. This release also makes the
Piper TTS model path configurable, auto-installs the MouseGrid GNOME extension on
first run, and adds Whisper transcription-latency benchmarks. Config handling was
extracted into its own module and host-environment setup moved into the plugins,
tidying the codebase alongside steady dependency and security-workflow upkeep.
What's Changed¶
- Allow installing on Python 3.13, pin deps for 3.10 by @bittner in #33
- Add Python package version badge to README by @bittner in #34
- Add pyaudio as a package dependency by @bittner in #36
- Update outdated package dependencies (typer-slim ++) by @bittner in #38
- Update outdated package dependencies by @bittner in #39
- Run safety workflow also in PRs by @bittner in #40
- Update outdated dependencies, restrict schedule for check by @bittner in #41
- Update outdated package dependencies by @bittner in #43
- Fix missing apt update for apt install by @bittner in #44
- Update dependencies and actions by @bittner in #45
- Update outdated package dependencies by @bittner in #49
- Add Nix flake for development and running on NixOS by @bittner in #51
- Make Piper TTS model path configurable via env var by @bittner in #52
- Run performance benchmarks for Whisper transcribe latency by @bittner in #53
- Extract config module and move host-env setup into plugins by @bittner in #54
- Fix No plugins directory found error by @gband85 in #47
- Fix mousegrid error caused by duplicate import by @wkarl in #48
New Contributors¶
Full Changelog: 0.1.0...0.2.0
0.1.0 · Foundation · 2026-02-08¶
Hello, Jarvis
The first release of EasySpeak, published to PyPI as easyspeak-linux: a fully
local, Wayland-native voice control for Linux desktops. Say "Hey Jarvis" to drive
GNOME hands-free with wake-word activation, a mouse grid, browser control,
dictation, and an app launcher — no cloud and no accounts. This release also laid
the project's engineering foundation: a clean src layout, a GHA CI pipeline for
linting, typing, tests, and an automated PyPI publish, and a first suite of unit
tests covering the core engine, CLI, and browser plugin.
What's Changed¶
- chore(gitignore): change gitignore file to
.gitignoreand remove pre-compiled python assets by @tulilirockz in #11 - Add a Justfile, draft packaging setup, contributing docs by @bittner in #14
- Organize Python modules with src layout, add first tests by @bittner in #15
- Add CI pipeline for linting and tests by @bittner in #17
- Allow all CI jobs to finish, reformat codebase, fix linting by @bittner in #18
- Fix type check config, make tests run and pass by @bittner in #19
- Update dependencies (uv.lock) by @bittner in #20
- Add unit tests for core module (mostly EasySpeak class) by @bittner in #21
- Run software safety related jobs only once a day by @bittner in #23
- Refactor application entrypoint (CLI), add tests by @bittner in #22
- Add tests for browser plugin by @bittner in #25
- Update outdated package dependencies by @bittner in #26
- Add tests for dictation plugin by @bittner in #27
- Add tests for apps plugin by @bittner in #28
- Add remaining tests for 100% coverage by @bittner in #29
- Update outdated package dependencies by @bittner in #30
- Build Python package, configure automatic release by @bittner in #32
New Contributors¶
Full Changelog: 0.1.0