Built in the open.
Steered by you.

What we're building, what's next, and what arrived. Vote for what you want, suggest what's missing, or help build it.

The roadmapUpdated recently
In progress0featuresbeing built now
Arrived0this monthin a release you can install
Ideas waiting1ideafrom people who use it

Now. Next.
Later.

Each feature goes through up to five stages. Votes tell us what matters to you; they don't decide alone.

Now

0 in progress
AI Rewrite, routed and measuredAI Rewrite that fits what you're writing.Spec
  1. spec, now
  2. build
  3. test
  4. ship
00 on GitHub · 0 here
Why, and how to help

First a harness that measures what AI Rewrite writes, on several models. Then a shorter prompt: a mode for the kind of text, and modifiers for language, length, tone and format. A second, faster step ships only if the measurements say it helps.

Discuss on GitHub →

Next

4 planned
NotetakerRecord a conversation you're in. Read who said what.Spec
  1. spec, now
  2. design
  3. build
  4. test
  5. ship
10 on GitHub · 1 here
Why, and how to help

Your microphone and the Mac's sound are recorded as two tracks, so who said what is exact in a one-to-one call, with no speaker model at all. Then summarise it, ask it questions and export it. Capture stays on this Mac, and a person starts every recording.

Discuss on GitHub →

More providersMore engines for speech and for AI Rewrite.Planned
10 on GitHub · 1 here
Why, and how to help

Every provider sits behind one registry, with a guide to adding one. A new provider is a good contribution. Open an issue first: a new provider is a new place your words go.

Discuss on GitHub →

LocalizationSpeechText in more languages.Spec
  1. spec, now
  2. build
  3. test
  4. ship
00 on GitHub · 0 here
Why, and how to help

The app speaks only English today. Translations come in the order people ask for them.

Discuss on GitHub →

PlaygroundTry your own dictations on other models, side by side.Spec
  1. spec, now
  2. design
  3. build
  4. test
  5. ship
00 on GitHub · 0 here
Why, and how to help

Pick dictations from History and run them through other models and prompts. See what came out, how long it took and what it cost, next to what you got. Nothing is sent until you start a run, and the run shows its cost first.

Discuss on GitHub →

Later

On the horizon
AutomationStart a dictation from Shortcuts, a script or an agent.
00 on GitHub · 0 here
Why, and how to help

A URL scheme, Shortcuts, a CLI and an MCP server. Other tools can start a dictation or read a transcript.

Discuss on GitHub →

Rich text pasteFormatting that stays formatting, wherever you paste.
00 on GitHub · 0 here
Why, and how to help

When you ask AI Rewrite for formatting and the app you paste into does not render Markdown, like Mail, Notes or Pages, it is pasted as rich text. A rich field shows real bold; a plain one gets clean text with no asterisks.

Discuss on GitHub →

Missing something?
Check before you post.

Type your idea. As you type, we show matching features and ideas, so you can vote for one that's already there or post a new one.

New idea· GitHub Discussions
Post it on GitHub

Search all ideas on GitHub

Waiting room

Top ideas

No ideas waiting. Be the first.

All ideas on GitHub

Open source.
Here's how to join in.

CONTRIBUTING.md has the whole story. These are the points that matter before your first idea or pull request.

The full document

CONTRIBUTING.md 14 sections · 1,947 words

Contributing to SpeechText

Contributions are welcome. This document exists so you never waste work on something that was never going to be merged.

Before you write code

Small fix? Just open a PR. Typos, crashes, a wrong constant, a broken edge case — no ceremony needed.

Anything bigger? Open an issue first and wait for a reply. This includes new features, refactors, new settings, UI changes, and anything touching the recording pipeline. A PR that arrives without a prior issue may be closed even if the code is good, simply because it takes the project somewhere it isn't going.

Issues labelled good first issue and help wanted are pre-approved — take one and go.

What is likely to be accepted

  • Bug fixes, crash fixes, race conditions
  • Accuracy or latency improvements with a measurement behind them
  • New speech or LLM providers that fit the provider registry (ProviderDescriptor, see docs/adding-a-provider.md) — open an issue first (a new provider is a new place user data goes), then follow docs/adding-a-provider.md
  • Accessibility and localization work
  • Test coverage for code that currently has none
  • Documentation that fixes something wrong or missing

What is unlikely to be accepted

  • New third-party dependencies. The app is Apple frameworks plus four packages, each a deliberate decision with its own boundary: WhisperKit and FluidAudio for local speech models (FluidAudio also runs the voice activity detector), Sparkle for updates, and llama.cpp for AI Rewrite on this Mac — the last as a prebuilt binary package (Packages/LlamaBinary/) run in the SpeechTextLLM XPC service, which the app never links. Each is imported by one file per use. A fifth is fine if it earns its place the same way: a measurement showing it beats what we have, and one file that names it. What this rule is against is a package imported from three places across the app.
  • Large refactors that arrive unannounced
  • Reformatting or restyling existing code
  • Features that expand the product's scope without a prior discussion
  • Anything that sends user data somewhere new

How features are planned

Every feature goes the same way, in the open, so you can see where anything stands and where your help fits.

  1. An idea starts in Ideas. One idea per discussion; upvote the ones you want. Each new idea gets an answer within a week, and one of three labels: under review, accepted or declined (with the reason).
  2. An accepted idea becomes an issue of type Feature with the roadmap label and a horizon: horizon: now, horizon: next or horizon: later — the same three sections as ROADMAP.md. The issue links back to its idea with a line Idea: #<number>.
  3. The issue's title is the feature's bold name in ROADMAP.md, word for word, and the issue ends with the card on speech-text.app/roadmap — a last section in this format:

    ### On the website
    
    - Pitch: one line, at most 60 characters, plain text (no backticks or HTML)
    - Icon: one of: apple github slack mail messages gmail docs notion chatgpt claude t3code terminal whatsapp discord linear play pause sparkles insert copy pointer rotate drop check keyboard mic mic-fill bolt sun moon slash sparkles-slash history retry key lock laptop cloud chip chevron logo-arrow speaker speaker-slash expand collapse x
    - AI: yes or no (yes gives the card the violet AI accent)
    - Why: at most three sentences; **bold**, _italic_ and links only, no code, HTML or headings

    The card's title is the issue's title, its column the horizon: label, and its order the feature's place in ROADMAP.md.

  4. Its stages are sub-issues, one each, labelled stage: spec, stage: design, stage: build, stage: test and stage: ship. A closed sub-issue is a stage done. A feature only has the stages it needs.
  5. When a feature is blocked, it gets state: waiting, and the first line of the issue says what on: Waiting: <reason>.
  6. It ships in a milestone named after the version, as its tag without the v (0.10.0, 0.11.0, …). The feature issue is closed when the release is out.
  7. A feature we decide against is closed as not planned, with a comment starting Dropped: <reason>.

👍 on a feature issue is a vote. Votes tell us what matters to you; they are weighed with measurements and with ROADMAP.md, and do not decide alone.

Where to help: sub-issues and issues labelled good first issue or help wanted (code), and verification (trying a build by hand). Comment on the issue before you start, so two people don't build the same thing.

Your first pull request

  1. Clone the repository and turn on the hooks: git config core.hooksPath .githooks (see Hooks).
  2. Open SpeechText/SpeechText.xcodeproj in Xcode, or run the tests from a terminal:

    xcodebuild test -project SpeechText/SpeechText.xcodeproj -scheme SpeechText -destination 'platform=macOS'

    The first build resolves the Swift packages and takes a while; after that the suite (about 710 tests) runs in a few seconds.

  3. Pick an issue labelled good first issue, say in a comment that you are taking it, and open a pull request when it is ready. A draft pull request is a fine way to ask a question.

Hooks

One command turns on the repo's git hooks, and the sign-off, the DEVELOPMENT_TEAM check and the SPDX header stop being things you have to remember:

git config core.hooksPath .githooks
  • prepare-commit-msg adds the DCO Signed-off-by line to every commit, so -s is no longer something to forget.
  • pre-commit refuses a commit that puts a DEVELOPMENT_TEAM back into project.pbxproj, adds a source file without the SPDX header, adds an app source file that is in no target, or adds a Swift file to the app or to Packages/SpeechTextCore named like one already in the other. It reads the staged content and takes a fraction of a second; --no-verify bypasses it.

The test suite is deliberately not in a hook — CI runs it on every pull request and on every push to main, and a hook slow enough to avoid is a hook that gets bypassed.

Signing your commits (DCO)

Every commit you author must carry a Signed-off-by line. Turn the hooks on (above) and it is added for you; otherwise Git adds it when asked:

git commit -s -m "Fix hotkey re-registration after sleep"

This is the Developer Certificate of Origin — you are stating that you wrote the code, or otherwise have the right to submit it under the project's license. There is no CLA and you keep the copyright to your contribution.

That is a commitment, not a current convenience: no CLA will be introduced later, and the client will not be relicensed under closed terms. Your contribution stays yours, under GPL-3.0-or-later.

If you forget, git commit --amend -s fixes the last commit, and git rebase --signoff main fixes every commit on the branch.

Pull requests are merged as squashes — the only merge method the repository allows — so there is no merge commit to sign. The squash commit keeps the Signed-off-by trailers of the commits it replaces; when merging, leave them in the message.

Pull request checklist

Short on purpose. Anything a machine can refuse for you is not on it:

  • One concern per PR. Don't mix an unrelated fix into a feature.
  • Logic you want tested goes in Packages/SpeechTextCore/Sources/SpeechTextCore/, which needs no project edit; views and anything that touches AppState or SpeechEngine stay in SpeechText/SpeechText/ (see docs/development.md). A type the app uses is public there — the compiler says so, but as cannot find 'X' in scope in an app file, which reads like a missing import.
  • UI changes include a before/after screenshot. Anything with motion or timing includes a short video.
  • The description says what changed and why, and under Needs a real-app run what only a person can check in the running app (or "None").

Everything else is checked for you. CI runs the test suite (which compiles the app too, and fails on any compiler warning in our code — see docs/development.md), refuses a DEVELOPMENT_TEAM written back into project.pbxproj, refuses a Swift file without its SPDX header, fails when docs/adding-a-provider.md no longer matches the provider code, refuses import SwiftUI (or an engine's import) in Packages/SpeechTextCore, and requires a Signed-off-by on every commit in the pull request. The hooks above catch the same things before you push, except the provider guide, and add the sign-off itself.

Review

.github/CODEOWNERS names who reviews; for now that is the maintainer, who looks at every pull request. Expect a first response within a few days — this is one person's project, so it is not an SLA, and a nudge on the pull request after a week is welcome.

  • CI must be green before a merge. GitHub refuses a merge while Tests, Swift lint or Checks is red, and DCO sign-off is a step of Checks, so an unsigned commit blocks the merge too.
  • A pull request that lists something under Needs a real-app run is not blocked on you: the maintainer checks those items in a real build, with a real microphone and the apps the e2e run cannot read back. Say as precisely as you can what to check.
  • Review comments are about the change, not you. If the answer to a comment is "that was on purpose", say so and why; the code is full of decisions that look like oversights.

Issue and pull request numbers

The history was rewritten before the repository went public (docs/development.md has the story). Issue and pull request numbers from before it were removed from the code, the docs and the commit messages, so a #N you find here is this repository's. If a comment refers to an earlier decision you cannot find, ask in an issue.

Formatting

Match the surrounding code — its layout, its naming, its comment density, its idiom — and leave the lines you did not change alone. The code is wrapped the way Xcode wraps it, which no formatter reproduces, so a formatter is never run over the codebase.

What is checked is a short list of swift-format's rules about constructs to avoid (a .forEach where a for loop reads better, two enum cases on one line, a block comment). Run scripts/lint-swift.sh before you push: it lints the Swift files your branch changes against origin/main and ignores every finding about layout. CI runs the same script as Swift lint. It reports findings on the lines you changed and nothing else: an old finding elsewhere in a file you touched is not yours to fix here (restyling pull requests are refused above). Its configuration is .swift-format.

Language

Everything in the repository is written in English: code, comments, commit messages, pull requests, issues and documentation — the same language as the app's UI. Words in other languages appear only as data, such as a non-English transcript a test or an explanation quotes.

Setting up

docs/architecture.md is a short overview of how the app is put together — start there. docs/development.md covers building, testing and the project layout. CLAUDE.md is the exhaustive architecture reference — read the relevant section before changing the recording pipeline.

License

SpeechText is GPLv3 or later, copyright (C) 2026 Vladyslav Husakov. By contributing you agree your work is published under it. You keep the copyright to your contribution — there is no CLA.

New source files start with the two-line SPDX header the rest of the codebase carries:

// SPDX-FileCopyrightText: 2026 Vladyslav Husakov
// SPDX-License-Identifier: GPL-3.0-or-later

Substantial contributions may add their own SPDX-FileCopyrightText line below it.

The short version

Before you startwritten by hand from CONTRIBUTING.md
  • Ideas first. Post yours in Ideas, or upvote one already there. Every new idea gets an answer within a week.
  • Small fix? Open a pull request. Anything bigger? Open an issue first and wait for a reply: a pull request that arrives without one may be closed, however good the code.
  • Welcome: bug fixes, measured gains in accuracy or speed, accessibility, localization, tests. Unlikely: new dependencies, unannounced refactors, restyling, anything that sends user data somewhere new.
  • Give your agent the map. CLAUDE.md is the full architecture reference. git config core.hooksPath .githooks turns on the hooks; they and CI check the sign-off, the headers and the tests for you.
  • What only you can add: one concern per pull request, a before/after screenshot for a UI change, and under Needs a real-app run, what to check in the running app.
  • You keep the copyright. Commits are signed off (git commit -s); there is no CLA, and the license stays GPL-3.0-or-later.
  • Where to start: good first issue, help wanted or verification. Comment before you start, so two people don't build the same thing.

Promised.
Shipped.

A roadmap that never records an arrival stops being believed.