About wispr-flow-dictionary
wispr-flow-dictionary is a skill for Wispr Flow users that reads and maintains local dictation history and dictionary data through a script. It covers error analysis, entry management, and backups, with a database status check before writes.
Key features
- 01Inspect dictation history and formatting differences
- 02Analyze terms, counts, and repeated snippets
- 03Add, remove, and undo dictionary entries
- 04Back up the dictionary before writes
- 05Check database status and schema changes
Use cases
- 01Find recurring speech recognition errors
- 02Prepare dictionary entries from dictations
- 03Turn frequently dictated text into snippets
- 04Revert an incorrectly added dictionary batch
MCP support
Wispr Flow's remote MCP server does not provide access to dictation history or the dictionary; this skill uses a local script to interact with the SQLite database.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ yahyabedirhan/ skills --skill wispr-flow-dictionaryAfter installing, type/wispr-flow-dictionaryin Claude Code to confirm it loaded.
Bundled filesscripts/wispr.py
Details
From the project READMEWispr Flow dictionary
Wispr Flow is a macOS dictation app. It has no CLI, and its remote MCP server covers meetings, not dictation history or the dictionary. It keeps both in a local SQLite database, and scripts/wispr.py is the interface to it. Go through the script for every read and write, so the database internals stay in one place.
Run status first. When it reports a CHANGED schema, stop and inspect the changed tables before any write. Take every count you report from count.
Commands
python3 <skill-dir>/scripts/wispr.py <command> --help
| Command | What it does |
|---|---|
status | Checks the database. A CHANGED schema means an app update changed the database tables the script reads and writes. |
history | Dictations in a window (--since 30m, 3h, 2d, 1h30m, or --from/--to). --diff shows only the words formatting swapped; --fields raw,formatted shows both texts; --out FILE writes to a file. |
terms | Name-like and command-like words in a window, with counts, whether the dictionary has them, and hits since it got them. |
snippets | Links, emails and sentences dictated in full again and again, and whether a snippet already expands to them. |
count TERM... | Dictations containing each term, whole word, any case, with hits since its dictionary entry was added. --field formatted counts only what was pasted. |
dict list / add / remove / undo / backup | The dictionary. Every write backs up first; add prints a batch id that undo reverts. --restart quits Wispr Flow before the write and relaunches it after, which is how the app loads a change. add --snippet makes a trigger phrase that expands to --replace. |
- Backup location:
~/.local/state/wispr-flow/backups/, where the newest 30 are kept. - Overrides:
--backup-dirand--keep-backups, or theWISPR_FLOW_*variables. Put the two options before the command, since the script rejects them after it.
Entries the app learned from the user's edits have source: user_edits, and observedSource holds what it had heard.
The dictionary
- A word, a phrase with no replacement, teaches Wispr the term. Fix with a word first, for a mishearing as much as a misspelling: add
Herdr, notHerder→Herdr. - A rule, a phrase with a replacement, rewrites a phrase every time it is heard. Propose one only when the mistake keeps coming after its word was added, or when the intended word is an ordinary one a word entry can't teach, such as
work tree→worktree. The user decides. - To see whether a mistake came back, count the wrong form in pasted text from the day its word was added:
count <wrong form> --field formatted --from <date>, with the date fromIn dictionary sincein the intended word'scountrow. The since-added columns ofcountandtermscount the entry's own phrase, so they show the word in use, not its mishearings. - A rule's phrase matches whole words, so a plural needs its own rule (
cloud sessions). - Matching ignores case. Add each entry once, spelled exactly as it should appear: brand casing for names (
GitHub,WebMCP), lowercase for commands (npx,to-pr). A second entry in another case does nothing. - A rule is safe only when its phrase is not something the user also means literally.
city→Citibreaks the word city; addCitias a word instead. - A snippet is a short trigger phrase that expands to longer text, such as
my email address→ the address. Propose one only for text the user dictates in full again and again.
Fixing a mistake the user just reported
When the user says a word came out wrong ("I said skill, it wrote SQL"), fix it in the same turn:
countboth forms with no window, which covers the full history, to see whether the wrong form is also a word the user means, as SQL is for a user who works with databases.- Choose the fix:
- If the intended word is missing: add it as a word with
--restart. - If the word is there and the wrong form still turns up since it was added: propose a rule instead.
- If the wrong form is also a word the user means: propose no rule, and tell the user why a rule would do harm.
- If the intended word is missing: add it as a word with
- Tell the user what was added, and that the next review will show whether it held.
Finding transcription mistakes
Look for the words speech recognition gets wrong most: names of people, companies, products, tools, and CLI commands.
-
Read the dictionary, the
termstable and the--diffhistory for the window, the last 24 hours by default. Then read every dictation in the window, raw and formatted:termsand--diffmiss mishearings that came out as ordinary words the formatter left unchanged ("verb tree", "two PR").- When the user names a window: use that window instead.
- When the window is longer than a few hours: write
history --fields raw,formattedwith--outto a file in a temporary directory outside any repository and read that file in pages, since it costs about 30k tokens per day of dictation and the dictations are private.
-
Find candidates: words that are wrong in context, such as a real word where a name belongs ("Herder session", "cloud code"), a name spelled several ways, or a command turned into a word, like "Sila" for CLI. Check the raw text too; formatting sometimes hides a mishearing and sometimes fixes it.
-
Confirm the intended word from the surrounding text and the user's projects: the one open now, and any other the dictation was about, which the
appcolumn shows. Grep them for the name.- Where the intended word can't be established: list it under Unclear and ask.
-
Count every misheard form and every intended form over the same window, and repeated snippets over the last 30 days.
-
Report, in exactly this shape:
### Words to add | Word | Wispr wrote | Dictations | Example | ### Rules to add | Wispr writes | You meant | Dictations | Since its word was added | Example | ### Snippets to add | Trigger | Expands to | Dictations | ### Not fixable with the dictionary - <mishearing>: <why a rule would do harm, or what would fix it instead> ### Unclear - "<what Wispr wrote>": <the context>. What did you say?Leave out anything already in the dictionary.
- When an entry is still being misheard after it was added: it moves to Rules to add ("
CLIis a word, yet heard as Sila twice since it was added"). - When a section is empty: drop it.
- When an entry is still being misheard after it was added: it moves to Rules to add ("
-
Write only after the user approves the list. Put the approved entries in a JSON file:
[{"phrase": "Figma"}, {"phrase": "work tree", "replacement": "worktree"}, {"phrase": "my site", "replacement": "https://example.com", "snippet": true}]Dry-run it with
dict add --file <file> --dry-run, tell the user Wispr Flow will close for a few seconds, write it withdict add --file <file> --restart, and give the user the batch id.
The app syncs the dictionary to the user's account. Entries written this way survive a restart. Gap: whether a sync ever drops them is not known, so say so when reporting a write.
Scripts
- scripts/wispr.py: the one interface to Wispr Flow's database.