opensteno/plover: a stenotype engine that builds its own version string
Open source stenotype engine
At a glance
- What is it?
- Plover is a Python desktop application for stenography on Windows, Linux and Mac. Its repository page carries no installation command and defers setup to a wiki, while the packaging script execs the package's own init file to discover its version and reaches into git for the release label.
- Who is it for?
- Plover fits anyone who already owns a steno machine and wants a desktop engine rather than a browser tool, and the licensing is the friendliest thing about it: GPLv2+ with an explicit or-later grant, no paid tier and no account. Check three things first.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- opensteno/plover2,608 ★ · +14
| Repository | 2026-10-04 | 2026-11-14 |
|---|---|---|
| opensteno/plover | 2.6k | 2.6k |
14 Stars in the last 41 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Windows packaging has its own command class, with a trim switch
The build system is not a single setuptools script. The packaging entry point pulls four command classes out of a separate module, plover_build_utils.setup: BuildPy, BuildUi, Command and Develop, then rewires their dependency lists so that develop waits on build_py and build_py waits on build_ui. On top of that sits a Windows-specific class, BinaryDistWin, whose description is to create distributions for MS Windows and whose first user option is `("trim", "t", "trim the resulting distribution to reduce size")`, followed by a zipdir option.
A trim flag on the Windows artefact only is a sign of how large a Qt application bundle gets, and it means the packaging story differs by platform rather than being uniform. The root listing agrees: three platform directories sit beside the Python package, each with its own build README that the project page links separately for Windows, Linux and Mac. So the three platforms are not three branches of one build recipe but three build instructions to follow for your system, and the only one whose packaging code appears here is the Windows one.
The version string is exec'd out of the package and patched by git
Metadata is read by running the package's own init file, with a note in the source admitting it should be done without exec. Everything the build needs to know about the software name, version, description, URL, download URL and license arrives that way. The version is then refined against the repository history:
def get_version():
if not os.path.exists(".git"):
return None
version = __version__
git_version = (
subprocess.check_output(["git", "describe", "--tags", "--match=v[0-9]*"])
.strip()
.decode()
)
m = re.match(r"^v(\d[\d.]*(?:(?:\.dev|rc)\d+)?)(-\d+-g[a-f0-9]*)?$", git_version)
assert m is not None, git_version
if m.group(2) is not None:
version += "+" + m.group(2)[1:].replace("-", ".")
return versionTwo behaviours follow directly from those lines. A working checkout gets a development version with the commit distance and short hash appended after a plus sign, with the hyphen rewritten as a dot, so the label stays a valid version. A tree without a .git directory returns no version at all, which is what makes building from an exported archive or a vendor copy a different exercise from building from a clone. The describe call also restricts itself to tags matching v[0-9]*.
Broad exception handling is switched off in lint, on purpose
One lint rule is deliberately disabled, and the reason is written next to it rather than left to a commit message:
[tool.ruff.lint]
ignore = [
# Broad `except Exception` is Plover's deliberate crash-resilience idiom:
# engine hooks, plugin and dictionary loading must never take down the engine.
"BLE001",
]The three named areas are the engine's hook system, plugin loading and dictionary loading, and the rule the project gives up is the one that flags a bare except Exception. In a desktop application that loads third-party plugins, that is a defensible trade: a plugin that raises during import takes the whole typing session down with it otherwise. It also tells you where the extension points are, since these are the code paths the project considers most likely to throw from outside itself. Configuration for the same checker sits in the same file, and the pre-commit configuration at the repository root means the lint decision is enforced before a commit lands rather than at release time.
Every change is a typed fragment under news.d, rendered into NEWS.md
Release notes are generated, and the generator is configured in detail. The changelog file is NEWS.md, fragments live in a news.d directory, the template is news.d/template.md, and the heading format includes the version and the project date with no underline characters at all. Sections are named Features, Bugfixes and API, and each has its own fragment types: the main sections take core, dict, ui, linux, osx and windows fragments, while the API section takes break, dnr and new. Every one of those types is set to show its content in the rendered file.
The type names are the interesting part. A change can be filed as a core engine change, a dictionary change, a user interface change, or against one of three platforms, and separately as a breaking change, a deprecation or a new API. That is a much finer partition than a conventional two-bucket changelog, and for a project whose users are split across Windows, Linux and Mac it means a Linux-only fix is distinguishable from a macOS one in the notes. Both NEWS.md and the news.d directory sit at the repository root, so the convention is visible to anyone reading the tree.
PySide6 is a build requirement, and the metadata is not in pyproject.toml
The build inputs are declared in one place and the package metadata in another. The build system table requires five things:
[build-system]
requires = [
"babel",
"packaging",
"PySide6>=6.11.2",
"setuptools>=79.0.0",
"wheel",
]There is no project table in that file, so the name, version and description come from the legacy setup.py path described in the previous section, and pyproject.toml is left holding build configuration plus the lint and changelog settings. The PySide6 entry is the notable one: the Qt binding is required to build, not merely to run, which means a packaging machine needs the GUI toolkit installed even if it never starts the application. Babel is there for the translation catalogues, which matches a project whose releases are separated by platform. Supporting files around it complete a conventional layout: MANIFEST.in for what goes in the source distribution, setup.cfg, pytest.ini and tox.ini for tests, and a reqs directory for pinned requirement files.
The project page has no installation command at all
The Installation section is four sentences long. Plover runs on Windows, Linux and Mac, and the page sends you to an installation guide that covers downloading, installation and initial configuration. Nothing else is stated there: no download link beyond that guide, no package manager name, no command to type. The help section is built the same way, with pointers to four wiki pages for installation, a beginner's guide, supported hardware and troubleshooting, and then a request to search for or create an issue.
That is a deliberate division of labour rather than an omission, and the surrounding links show how wide the project's published surface is: a homepage at opensteno.org, a wiki, a blog, a Google Group, a Discord server, and a documentation site at plover.readthedocs.io backed by a .readthedocs.yml configuration and a doc directory. What a reader cannot get from this repository is a first-run experience. Setup knowledge lives on the wiki, hardware compatibility lives on a wiki page, and troubleshooting lives on another one, so the repository is where the software is built rather than where it is installed.
Related steno projects are named in other languages, and the artwork lives elsewhere
The programming section points contributors at other steno work, and both alternatives are in languages other than Python: StenoJig in JavaScript and StenoTray in Java. That is an explicit statement about where this project does not intend to go, since Plover itself is a cross-platform desktop application in Python. The art and writing work is spread just as widely. Icons are worked on in a separate repository under the panathea account, the mascot has a name and a history on the blog, and the UX brief is stated as a tension: the application should do a great deal without getting in the way, which the page calls an interesting set of challenges and asks people to raise in Discord with users and developers present.
The Open Steno Project as a whole has its own web presence, and the page asks for contributions there too, naming the project homepage with its source in the opensteno.github.io repository and Plover's homepage with its source living in a gh-pages branch of this repository. Funding is handled in one short paragraph: the software is developed by volunteers, and donations go toward new projects and toward the maintenance costs of publishing Plover.
A GPLv2+ grant written for version 3.1.0 still governs version 5
The licensing statement is specific about its history. Plover is GPLv2+ as of version 3.1.0, which is the or-later grant, and the LICENSE.txt file at the repository root is the reference. The or-later part is the practically useful half here, since it means a downstream packager can ship the code under a later GPL without asking, and the licence text predates the current major version by a long way.
The release cadence sits at patch releases inside a 5.x line: v5.3.0 in April 2026, v5.4.0 in July, and v5.4.1 in late August, with the repository pushed to again on 2026-09-20, a few weeks after that last tag and with no newer release to go with it. The repository is not archived. Together with the typed change categories described earlier, that is the whole maintenance story this project publishes: a GPL grant fixed years ago, patch-level releases roughly every two to three months, and development continuing on the default branch between tags.
Editorial conclusion
Plover fits anyone who already owns a steno machine and wants a desktop engine rather than a browser tool, and the licensing is the friendliest thing about it: GPLv2+ with an explicit or-later grant, no paid tier and no account. Check three things first. There is no installation command in the repository at all, so a new user depends on the wiki being reachable and current. Building from source means three separate platform instructions and a version string that comes from exec'ing plover/__init__.py against a git checkout, so a build from an exported tree has no version to report. And the seven change categories under news.d tell you what the maintainers consider a user-visible change: a plugin or dictionary fix is its own category, which is a good sign that plugin breakage gets treated as a first-class release note.
Frequently asked questions
how to use plover steno
Plover is a cross-platform desktop application written in Python that lets you write on your computer with stenography, and the project states speeds of up to 200WPM and beyond. It runs on Windows, Linux and Mac. Its own page hands setup to the wiki installation guide rather than giving steps, and points at a beginner's guide, a supported hardware page and a troubleshooting page for the rest.
how to install plover plugin
The repository documents no plugin installation of its own. Plugins are named in one place in the source, in the lint configuration, where catching every exception broadly is allowed on purpose so that plugin and dictionary loading cannot take down the engine. Configuration and hardware details live on the wiki pages the project links.
how to install plover
There is no installation command in this repository. The project page says Plover runs on Windows, Linux and Mac, points to an installation guide covering downloading, installation and initial configuration, and links the release page for downloads. Building it yourself needs the platform-specific README for Windows, Linux or Mac.
What is special about plover?
The word names a shorebird as well as this software, which is why the question is ambiguous. In this repository Plover is the stenotype engine: a Python desktop application, part of the Open Steno Project, licensed GPLv2+ since version 3.1.0, developed by volunteers and funded by donations.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/opensteno-plover)Star history chart for your README
[](https://hysenlabs.com/projects/opensteno-plover)Was this useful?