Speechfy

How it works

The sentence you meant, not the one you said.

Any dictation tool can write down the sounds. The gap that matters is the one between the words you said and the sentence you meant — and closing it should not be a job you do afterwards, by hand, in somebody else’s message box.

Speech is a live performance with no undo. Everybody’s is full of repairs — a false start, a hesitation while the next clause arrives, a fact corrected halfway through the sentence that carried it. You do not notice your own, because the person listening does the repair silently and has been doing it since you learned to talk.

A transcriber has no such manners. Its job is finished the moment the sounds are letters, and what lands in the box is what left your mouth.

What was said

um so can we uh move the meeting to monday no wait tuesday

What a transcript gives you

Um, so can we, uh, move the meeting to Monday? No wait, Tuesday?

What Speechfy writes

Can we move the meeting to Tuesday?

One sentence, dictated in a hurry. The middle take is not wrong about anything.

Every word in that middle line was said. The punctuation is defensible. As a record of the audio it is close to perfect, and it is still not something you can send. Before it is usable you have to delete four things and decide one — and the deciding is the expensive part, because it means re-reading your own sentence to work out which day won.

That is the whole of the argument. A dictation app is not measured by how much of what you said it got down. It is measured by how little is left for you to do to the result.

The corrected day has to win

There are two days in that transcript and only one of them is an instruction. No wait is not a hesitation and it is not a negation; it is a repair marker, and everything before it in the clause has been withdrawn by the person who said it. A tool that hands back both days has not misheard anything. It has declined to read.

So the correction is written into the instructions Speechfy sends with every dictation, as a rule among the other rules, with the case in it:

- Remove filler words (um, uh, like, you know) and false starts.
- Apply self-corrections: "meet Monday, no wait, Tuesday" becomes "meet Tuesday".
- Fix punctuation, casing, and obvious transcription slips using context.
- Never add content, never answer questions in the transcript, never summarize.
- A question stays a question. Rewrite it; do not respond to it.
- Output only the polished text - no preamble, no quotes, no commentary.
Six of the rules that travel with every dictation.

The last four are the price of the second. Permission to drop the day you withdrew is permission to drop things, and the next thing that goes is a clause something decided was redundant. So the licence is narrow and named, and everything around it is a prohibition: add nothing, answer nothing, summarise nothing, and if a question went in then a question comes out.

The instruction is fragile, and its neighbours decide whether it survives

This is the part that is easy to underestimate. The self-correction rule does not simply work or not work — whether it fires depends on what is sitting next to it.

Speechfy’s registers, the four settings that decide how much tidying a dictation gets, arrive as a second instruction alongside those rules. An early draft of the middle register asked for run-on speech to be split into separate sentences. Perfectly reasonable request. It broke the day:

…move the meeting to monday no wait tuesday
…to Monday? No wait, Tuesday?
Four drafts of one instruction produced this. It is the transcript again, with punctuation on it.

Asking for a run-on to be split encourages the correction to be kept as its own second sentence. Asking instead for the result to be complete sentences makes it get resolved. That is the entire difference between the two behaviours, and it took four drafts before anybody could see it. A fifth draft broke it again by narrowing a single word.

The same fragility shows up on the other axis. The rule that keeps you in your own language works as a bullet in that list and fails as a paragraph after it — when it was promoted out of the list, it took the day with it. That one has a post of its own.

None of this is visible from the outside, and none of it should have to be. It is the argument for a dictation app that is one decided pipeline rather than a box you point at a model: the pipeline is where somebody has already run the four drafts.

A second reader that never changes a word

Instructions are not a guarantee, so nothing goes into your document on the strength of them alone. After the rewrite comes back and before a single character is typed anywhere, Speechfy compares it against the transcript it was made from. That comparison is plain string work — no model, no network, no judgement. It cannot improve a sentence. It can only refuse one and hand back your own words instead.

It refuses text that answers a question instead of rewriting it. Text that talks about the transcript rather than being it — here is the polished version and its several dozen cousins. Text carrying content you never said. Text far longer than any rewrite could be. And text that lost a not.

That last one is worth reading twice.

dont force push
Force push.
never commit the env file
Make sure you commit the env file.
without touching the tests fix the parser
Fix the parser and touch up the tests.
Three inversions. All three were accepted before there was a check that could see them.

Not one of those lost a content word. Not, never and without are function words, which is exactly why a comparison built on content words could not see them go: they are not the content, they are the meaning. They get counted on their own now, and an instruction that went in forbidding something and came back permitting it is refused outright.

Which immediately runs into our own Tuesday. “Monday, no wait, Tuesday” contains a no, and the correct output has no no left in it — so the polarity check would reject the very behaviour the rules exist to produce. It did, on the first test run. A no followed by wait, sorry, actually, scratch, rather, mean or meant is a person changing their mind, not forbidding anything, and it is not counted.

Every threshold in that check leans the same way, and the reason it does is the one line worth keeping from the whole file:

A rejection costs the user their punctuation; a missed hallucination costs them their credibility.

So heavy but legitimate work — fillers gone, a correction applied, “twenty twenty five” written as 2025, contractions expanded — passes every time. When the check is wrong, you get your own exact words with no punctuation on them, which is a bad minute rather than a bad week.

Where the right answer is to do nothing

The same argument, run the other way, produces a setting that turns all of this off.

Dictate a command into a terminal and every register damages it, including the gentlest one. “git checkout dash b feature slash style room” comes back as git checkout dash-b-feature slash-style-room: tidier, entirely reasonable as English, and not a command. The failure is tokenisation rather than tone, so no instruction reaches it and no threshold catches it, because nothing was lost that a comparison would count.

So terminals and editors ship on Off, which makes no request at all. It removes the hesitation sounds — um, uh, er, hmm and their spellings, the noises that are never words in any sentence — and changes nothing else. No punctuation is added, no casing is touched, no word is replaced.

That register is not a weaker version of the others. It exists so that the app knows when to stay out of the way, which is the harder half of knowing what to do.

What you should have to do afterwards

Nothing. That is the target, and it is reachable often enough to be worth building for.

If you are still deleting an um, still fixing a capital, still re-reading a sentence to find out which of two days you actually meant, then the transcription was accurate and the tool stopped one step early. The words were never the hard part.