Skip to content

Contributing

Contributions welcome. The source code lives on GitHub — fork it, clone it, and send a pull request. Please open an issue first to discuss larger changes, or start a thread in GitHub Discussions.

Areas that need work:

  • More application integrations

Planned Enhancements

  • Window controls (maximize, minimize) — the GNOME extension already exposes them over D-Bus; no plugin drives them yet
  • Further GNOME integration for desktop control
  • Verbal help per section (say "help browser" for spoken commands)
  • Auto-discover installed apps for launcher
  • Clipboard commands (copy, paste)

Development

This project sports a Justfile to simplify all local development activities, and for running the same tasks in the CI pipeline.

just
just all
UV_PYTHON=3.14 just pytest -q -x
just clean

The setup uses uv under the hood, which transparently manages virtual environments and package installation. uv also allows you to install several Python versions on your computer in parallel. We use this to test against all supported Python versions.

Prerequisites

First install the system build dependencies (PortAudio, GCC, Python 3.10–3.14, …) as described under Install from source in the Installation guide — without them the build and run steps below will fail.

Then install uv and just, e.g.

python3 -m pip install uv
uv tool install rust-just

NixOS

Enter a development shell with all dependencies installed, or run the application directly:

nix develop
nix run

To run directly off GitHub, with no clone required:

nix run github:ctsdownloads/easyspeak

Packaging & Version Numbers

The packaging configuration is in pyproject.toml, supported by MANIFEST.in. Version numbers are generated automatically by setuptools-scm based on the latest Git tag and the distance from that tag in number of commits.

We create releases by drafting a new release from the GitHub Releases:

  1. Extend the CHANGELOG by a release entry (see steps 3 through 6 below for the content).
  2. Click on Draft a new release.
  3. Pick or enter the next suitable semantic version number in the tag selector (target: main).
  4. Enter a title, e.g. "<version> · <a-catchy-phrase> · <date>" (in GitHub Releases, leave out the date).
  5. Click on Generate release notes.
  6. Write a concise summary of one or two paragraphs at most.
  7. Commit the CHANGELOG, e.g. with a "Release <version>" commit message.
  8. Finally, press Publish Release (release label "Latest").

Publishing a release builds the easyspeak application packages and attaches them; the easyspeak-lang-* data packages release separately, on their own cadence.

Language packs

A language pack changes only when its models in pins.toml do, so it is versioned and released independently of the application. Its [lang.<code>] version reflects that pack's pinned content and is bumped by just update-pins whenever the models change (review it in git diff pins.toml).

Release a pack from the GitHub Releases, the same way as the app but simpler — no CHANGELOG entry, no generated notes, and it is not the "Latest" release:

  1. Click on Draft a new release.
  2. In the tag selector (target: main), enter lang-<code>-<version>, e.g. lang-en-1.0.0. The version segment must match [lang.<code>].version in pins.toml, or the workflow fails.
  3. Enter the title <version> · Language pack · <Language>, e.g. 1.0.0 · Language pack · English.
  4. For the body, copy the pack's previous release and adjust only what changed (the models rarely do); for the first release of a new language, adapt the English pack's text.
  5. Press Publish Release with the release label set to None — a data package is never the project's "Latest" release.

Publishing runs release.yml, which verifies the tag's version against pins.toml, skips the application pypi and packages jobs, builds the pack, and attaches its .deb and .rpm to the release.