Other

/wispr-mining

Mine Wispr SQLite for ASR vocabulary gaps/corrections. Triggers: wispr mining, ASR errors, voice vocabulary.

$ golems-cli skills install wispr-mining
91% best pass rate
23 assertions
8 evals

Updated 2 weeks ago

Extract ASR misrecognition patterns from Wispr Flow's SQLite database and generate clean, importable dictionary files.

Database Location

~/Library/Application Support/Wispr Flow/flow.sqlite

CRITICAL: Always work on a COPY. Before any operation:

cp ~/Library/Application\ Support/Wispr\ Flow/flow.sqlite /tmp/wispr-flow-readonly.sqlite

Then query /tmp/wispr-flow-readonly.sqlite exclusively. Never write to the production database.

Schema Reference

Dictionary Table

ColumnTypePurpose
idVARCHAR(36)UUID primary key
phraseVARCHAR(255)The dictionary entry (vocabulary word or trigger phrase)
replacementVARCHAR(255)NULL = vocabulary entry. Non-NULL = replacement mapping
frequencyUsedINTEGERHow often this entry has fired
isDeletedTINYINT(1)Soft delete flag
isSnippetTINYINT(1)Snippet (long-form expansion), not a correction
manualEntryTINYINT(1)User-added vs auto-detected
createdAtDATETIMEWhen added
lastUsedDATETIMELast trigger time

History Table

ColumnTypePurpose
transcriptEntityIdVARCHAR(36)UUID primary key
asrTextTEXTRaw ASR output (what the mic heard)
formattedTextTEXTAfter Wispr's formatter + dictionary
editedTextTEXTUser's manual correction (NULL if no edit)
appVARCHAR(255)Which app was active
timestampDATETIMEWhen dictated
numWordsINTEGERWord count
isArchivedTINYINT(1)Archive flag

Mining Workflow

Step 1: Copy Database

cp ~/Library/Application\ Support/Wispr\ Flow/flow.sqlite /tmp/wispr-flow-readonly.sqlite

Step 2: Current Dictionary Audit

-- Active dictionary entries (not deleted, not snippets)
SELECT phrase, replacement, frequencyUsed, lastUsed
FROM Dictionary
WHERE isDeleted = 0 AND isSnippet = 0
ORDER BY frequencyUsed DESC;
 
-- Unused entries (candidates for cleanup)
SELECT phrase, replacement, createdAt
FROM Dictionary
WHERE isDeleted = 0 AND isSnippet = 0 AND frequencyUsed = 0
ORDER BY createdAt;
 
-- Snippets (long-form expansions)
SELECT phrase, replacement FROM Dictionary
WHERE isDeleted = 0 AND isSnippet = 1;

Step 3: Find ASR Misrecognition Patterns

-- Words that ASR consistently gets wrong (asrText differs from formattedText)
-- Group by the ASR mistake to find systematic patterns
SELECT
  LOWER(asrText) as asr_pattern,
  formattedText as corrected_to,
  COUNT(*) as occurrences,
  GROUP_CONCAT(DISTINCT app) as apps
FROM History
WHERE asrText IS NOT NULL
  AND formattedText IS NOT NULL
  AND asrText != formattedText
  AND isArchived = 0
  AND LENGTH(asrText) < 100
GROUP BY LOWER(asrText)
HAVING COUNT(*) >= 3
ORDER BY occurrences DESC
LIMIT 50;

Step 4: Find User Edit Patterns

-- Cases where user manually corrected the formatted text
-- These are the HIGHEST-SIGNAL gaps
SELECT
  formattedText,
  editedText,
  app,
  timestamp
FROM History
WHERE editedText IS NOT NULL
  AND editedText != formattedText
  AND isArchived = 0
  AND LENGTH(editedText) < 200
ORDER BY timestamp DESC
LIMIT 50;

IMPORTANT: Classify edits into two buckets:

  1. Whitespace-only edits (trailing spaces, leading newlines, paragraph breaks) — LOW signal, ignore for dictionary purposes
  2. Real content corrections (word changes, missing words, ASR errors) — HIGH signal, these drive new entries

Use TRIM(formattedText) != TRIM(editedText) to filter out whitespace-only edits. Report both counts but only act on content corrections.

Step 5: Cross-Reference with Existing Dictionary

For each ASR pattern found in Step 3, check if it's already covered:

-- Check if a misrecognition is already in dictionary
SELECT phrase, replacement
FROM Dictionary
WHERE isDeleted = 0
  AND (phrase LIKE '%<pattern>%' OR replacement LIKE '%<pattern>%');

Only recommend NEW entries that aren't already covered.

Step 6: Generate Output Files

OUTPUT FORMAT IS CRITICAL. Wispr Flow imports CSV files literally — every line becomes a dictionary entry.

Vocabulary File (new words to recognize)

File: wispr-vocabulary-update.csv Format: One word per line. NO headers. NO comments. NO blank lines. NO quotes unless the word itself contains a comma.

toml
TOML
golems.toml
agentic

Replacements File (trigger → correction mappings)

File: wispr-replacements.csv Format: trigger,replacement per line. NO headers. NO comments. NO blank lines. NO quotes unless values contain commas.

tomo,toml
golems.tomo,golems.toml
Claw.md,CLAUDE.md