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.13.0 · Welcome, KDE Plasma! · 2026-10-11¶
EasySpeak Comes to KDE Plasma, Says What Went Wrong, and Licenses Every File the REUSE Way
EasySpeak now runs on KDE Plasma too. Its tray icon puts it to sleep, wakes it
up, opens Help and About, and switches "Start at Login" on or off. "Open
settings", "open calculator" and other app names open the KDE counterparts, and
the About information appears in Plasma's own look where kdialog is installed.
A new Compatibility page shows which features work on which desktop; the mouse
grid, head tracking and typing dictated text still need GNOME. The packages no
longer pull GNOME's libraries onto other desktops, and every file's copyright and
license is declared following the REUSE specification.
When something goes wrong, EasySpeak now says so out loud instead of only in the terminal, and Ctrl+C ends it quietly. It also understands more ways of asking: "dictation", "deactivate yourself", "exit the application", "open trash", "close downloads", and opening or closing the About dialog by name.
What's Changed¶
- Settings raises the open preferences dialog by @bittner in #201
- "Stop listening" releases the mic at once by @bittner in #200
- Dictation Plugin: compare Title Classes with lowercase, remove unneccessary "inserted 0 chars" when triggered by has_focused_text_field() by @SolanumForte in #202
- Remove the Bencher integration by @bittner in #205
- Tray icon for KDE Plasma and other desktops by @bittner in #204
- REUSE-compliant licensing by @bittner in #206
- About dialog by voice, more natural replies by @bittner in #208
- Dictation fails gracefully on KDE Plasma by @bittner in #209
- Open System Settings on KDE Plasma by @bittner in #210
- Open KDE apps on KDE Plasma by @bittner in #212
- About dialog works on NixOS by @bittner in #211
- No GNOME libraries forced on other desktops by @bittner in #218
- Mouse grid says why it can't appear by @bittner in #214
- Core reports failures out loud by @bittner in #217
- More ways to ask for the About dialog by @bittner in #219
- Browser plugin reports failures out loud by @bittner in #215
- Fix test failing on Python 3.10–3.12 by @bittner in #222
- Ctrl+C quits without a stack trace by @bittner in #220
- More ways to ask EasySpeak to quit by @bittner in #221
- Head tracking says why it stopped by @bittner in #216
- Say "dictation" to dictate by @bittner in #224
- Compatibility page, KDE in the desktop badge by @bittner in #223
- Native About window on KDE Plasma by @bittner in #226
- "Start at Login" in the KDE tray menu by @bittner in #225
- Trash, and closing folders, by voice by @bittner in #227
- KDE docs: Start at Login, native About by @bittner in #228
- Close the About dialog by voice by @bittner in #229
- Package checks for KDE support by @bittner in #230
Full Changelog: 0.12.0...0.13.0
0.12.0 · A Faster Ear · 2026-09-14¶
Parakeet Recognizes the Speech by Default, in Its Own Package, and Dictation Keeps Its Capitals
Speech is now recognized by NVIDIA's Parakeet TDT v3 instead of Whisper: one
model for 25 European languages that tells them apart by itself, several times
faster on a short command than the Whisper model of a language pack, and with
punctuation and capitalization of its own. It ships as a third package,
easyspeak-stt-parakeet, installed once next to the app and a language pack, and
is fetched on first start where downloads are allowed. Whisper stays behind
EASYSPEAK_STT=whisper and takes over, with a note at startup, when the Parakeet
model is not there or the language is one it does not cover. Dictation no longer
lowercases what was said: "United States" and German nouns keep their capitals,
while the control words still match however they were cased.
The About window credits every model and voice EasySpeak ships with its owner and license, the plugin contract diagram matches the reference one, and the docs deploy of a release no longer trips over the deploy of the merge before it.
What's Changed¶
- Serialize the docs deploys of a release by @bittner in #189
- Retry the docs push on a fresh gh-pages when another deploy won by @bittner in #190
- Show the translator and vocabulary in the plugin contract diagram by @bittner in #191
- Mark the translator and vocabulary optional in the plugin contract by @bittner in #192
- Dash the plugin boxes in the contract diagram like the reference one by @bittner in #193
- Describe the translator and vocabulary as independent by @bittner in #194
- Keep the capitalization Whisper writes when dictating by @bittner in #195
- Credit the speech models and voices in the About window by @bittner in #197
- Recognize speech with Parakeet TDT v3 by default by @bittner in #196
- Package the Parakeet speech model as easyspeak-stt-parakeet by @bittner in #198
Full Changelog: 0.11.0...0.12.0
0.11.0 · Commands in Your Language · 2026-09-13¶
Commands, Dictation Control Words and the Help Screen in the User's Language, and a Microphone That Stays Open
With EASYSPEAK_LANGUAGE set, or the new --language option, the general,
app, folder, media, sleep and system commands take that language's words —
"öffne den Rechner", "lauter", "geh schlafen" — and so do the words inside
dictation, "Komma", "neue Zeile", "Notizen beenden", and the word that starts
it, "Diktat"; the English words keep working everywhere. What a plugin listens
for is a vocabulary.toml table beside its reply catalog, one per language, so
tuning a phrase, or adding the spellings Whisper makes of it, is editing a file;
the help screen lists the words of the active language, built from those tables.
The grid, browser and head-tracking modes still take English words. A typo in
the language code is reported at startup, and so is why replies fall back to
English.
The microphone now stays open after every command, whether it replied, acted silently or did not understand, and gives up only after about ten seconds of silence, so "open documents" or a misheard word no longer sends you back to the wake word. The docs' diagrams enlarge on click, and the file manager can be closed by its everyday names — the one your desktop is configured for.
What's Changed¶
- Speak the dictation control words in the user's language by @bittner in #174
- Add a
--languageoption to the command line by @bittner in #176 - Report an unknown language and why replies fall back to English by @bittner in #177
- Show the help screen in the active language by @bittner in #181
- Start dictation with the active language's word by @bittner in #180
- Take commands in the user's language in the simple plugins by @bittner in #182
- Make the docs' diagrams enlarge on click and show the plugin locale by @bittner in #184
- Keep the mic open after every command, reply or miss by @bittner in #187
- Build the help lines from the vocabulary tables by @bittner in #185
- Hear the file manager as Whisper writes it by @bittner in #186
Full Changelog: 0.10.0...0.11.0
0.10.0 · Answers in Your Language · 2026-09-12¶
Spoken Replies in German, Italian, French and Spanish, a Language Pack for Each, and Plugins as Packages
EasySpeak now answers in the language it is spoken to. EASYSPEAK_LANGUAGE=de,
it, fr or es with the matching language pack gives dictation, spoken
replies and the voice in that language; commands stay English words, as do the
dictation control words for now. The replies are gettext catalogs beside the
code that speaks them, one per plugin, with per-string fallback to English, and
the voice follows the language of the replies — so a language without a
translation, or without its voice pack installed, gets English replies in the
English voice rather than a voice reading the wrong language. Italian, French
and Spanish packs join the German one; a further language is a pins.toml
entry, an nfpm file and eleven .po files, and just translations <lang> and
just check-translations keep the catalogs in step with the code.
Underneath, plugins are Python packages now, each carrying its own locale/,
and route by an explicit PRIORITY instead of numeric filename prefixes; a
plain module still loads. EASYSPEAK_MODELS_DIR says where language packs are
installed, which the Nix dev shell uses to link packs in on demand
(easyspeak-lang de it) instead of fetching every language up front. As since
0.9.0, this release needs packs on the per-language layout: easyspeak-lang-en
1.1.0 or newer.
What's Changed¶
- Complete the 0.9.0 changelog entry by @bittner in #160
- Build every language pack into the Nix dev shell by @bittner in #161
- Read the replies with the voice of their own language by @bittner in #162
- Speak the replies in the user's language, German first by @bittner in #164
- Add the Italian language pack and Italian replies by @bittner in #165
- Add the French language pack and French replies by @bittner in #166
- Add the Spanish language pack and Spanish replies by @bittner in #167
- Tidy up before the next release by @bittner in #168
- Answer in English when the language's voice is not installed by @bittner in #171
- Fetch language packs on demand in the Nix dev shell by @bittner in #170
- Check that the reply catalogs keep up with the code by @bittner in #169
Full Changelog: 0.9.0...0.10.0
0.9.0 · Speaking Your Language · 2026-09-12¶
Dictation in Other Languages, Per-Language Packs, and Voice Control Proven on a Real Desktop
EASYSPEAK_LANGUAGE sets the language you dictate in — commands stay English
words — and picks the language pack installed for it. Each pack now lives under
its own /opt/easyspeak/models/<language>, so several can sit side by side, and
German is the first beyond English: easyspeak-lang-de pairs the multilingual
Whisper small with the Piper thorsten voice. This release needs
easyspeak-lang-en 1.1.0 or newer, as the 1.0.0 pack installs the old tree.
Translating the dictation control words (comma, stop notes, …) is still
ahead.
The bulk of the work between the two releases, though, is a dozen fixes from
running EasySpeak on a real GNOME/Wayland desktop rather than reading the
source: every mode's microphone loop now runs from the core, so the tray and
the idle timeout keep working inside grid, browser and dictation modes; command
words match as whole words, so "upgrade" no longer opens the grid; dictation
learns backspace, scratch that and keystrokes such as enter, tab, escape and
the arrows; the browser gets voice toggles for GPU rendering and ad blocking,
and detects ad blocking by asking qutebrowser itself; and an opt-in require
wake word keeps a video playing through the speakers from being transcribed as
commands. wl-clipboard becomes a hard dependency, the Nix dev shell supplies
every tool the code invokes, and line coverage is back at 100%.
What's Changed¶
- docs: Update installation instructions by @bittner in #131
- Add a CLI option to print version information by @bittner in #132
- Fix benchmark job by allowing Whisper model downloads by @bittner in #134
- Fix voice control breaking down in practice by @ctsdownloads in #135
- fix(clipboard): drop the xclip fallback and require wl-clipboard by @ctsdownloads in #136
- refactor(browser): hold session state on core, not module globals by @ctsdownloads in #137
- fix(dictation): match command words as whole words by @ctsdownloads in #138
- fix: whole-word grid triggers, and scroll past overflow-hidden by @ctsdownloads in #139
- chore: strip explanatory comments by @ctsdownloads in #140
- fix(browser): stop hint mode hearing its own prompt by @ctsdownloads in #141
- feat(dictation): backspace and scratch that by @ctsdownloads in #142
- fix(dictation): backspace no longer cancels scratch that by @ctsdownloads in #143
- feat(dictation): send enter, tab, escape and arrow keys by @ctsdownloads in #144
- feat: keystroke commands in dictation and browser mode by @ctsdownloads in #145
- feat(browser): voice toggles for rendering and ad blocking by @ctsdownloads in #146
- feat: option to require the wake word inside modes by @ctsdownloads in #147
- fix: wait for the real wake word in modes, not a text prefix by @ctsdownloads in #148
- fix(dictation): do not ask for the wake word before every sentence by @ctsdownloads in #149
- fix(nix): supply the runtime tools the code actually invokes by @ctsdownloads in #150
- Restore full line coverage of the voice-control paths by @bittner in #151
- Detect ad blocking by asking qutebrowser, not a stray python3 by @bittner in #152
- Support languages other than English by @bittner in #156
- Adding environment variable for customizing the language of the Whisper model by @SolanumForte in #154
- Give each language pack its own models directory by @bittner in #157
- Add the German language pack by @bittner in #158
New Contributors¶
- @SolanumForte made their first contribution in #154
Full Changelog: 0.8.0...0.9.0
0.8.0 · Voices on Their Own · 2026-07-04¶
Independently Versioned Language Packs and Verifiable, Pinned Model Downloads
Language packs now carry their own version and ship on their own release tag
(lang-en-1.0.0 is the first), decoupled from the application's release
cadence — a lang-en-* tag builds and publishes each pack on its own, and
points at a Releases view filtered to that language.
Version pinning also becomes transparent: a checked-in pins.toml records
exactly which model and dependency versions an install resolves to, and speech
models are now verified against per-file checksums — so an offline-by-default
setup stays reproducible and tamper-evident. This groundwork also paves the way
for a proper NixOS package, whose fully-pinned, hash-verified builds need
exactly this manifest. Rounding it out, filesystem handling moves to pathlib,
prek pre-commit hooks add file-hygiene and shellcheck gates, the API reference
regains its missing modules, and a flaky freedesktop link check (a WAF 418) is
quieted.
What's Changed¶
- Transparent version pinning (
pins.toml) by @bittner in #116 - Adopt pathlib for filesystem paths by @bittner in #118
- Pin per-file checksums for speech models by @bittner in #119
- Add missing modules to the API documentation by @bittner in #122
- Give language packs their own version by @bittner in #123
- Split language-pack builds from the application build by @bittner in #124
- Add prek pre-commit hooks for file hygiene and shellcheck by @bittner in #125
- Fix flaky link check on freedesktop's WAF (418) by @bittner in #127
- Release language packs on their own trigger by @bittner in #126
- Fold language-pack builds into the Release workflow by @bittner in #128
- Skip the Docs workflow for language-pack tags by @bittner in #129
- Link the language pack to its filtered Releases view by @bittner in #130
Full Changelog: 0.7.0...0.8.0
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