# Lexicon: the words your dictation keeps getting wrong Version 0.5.3. MIT licence. Free. No account, no telemetry, no network calls beyond loopback. Homepage: https://lexicon.ashlr.ai. Source: https://github.com/ashlrai/lexicon. This document is the whole of what an agent needs to evaluate, install, configure and verify Lexicon on a user's behalf. It is served at https://lexicon.ashlr.ai/llms-full.txt. -------------------------------------------------------------------------------- ## What problem it solves A speech recognizer scores candidates against a language model built from ordinary text. An invented name has no prior in that model, so the decoder emits the nearest common-sounding sequence it does know. "Ashlr.AI" becomes "Ashler", "Kubernetes" becomes "Cuban eats", "Vercel" becomes "versal", "PostgreSQL" becomes "postgre sequel". The audio was fine; the vocabulary was missing. Lexicon is one YAML file of the words a person actually says (brands, people, products, acronyms), applied to every transcript before an agent reads it. ## Who it is for Anyone who talks to an AI agent and has a name it keeps getting wrong: a company name, a product, a person, an internal system, a repository. If a user complains that dictation, voice mode or their transcription app keeps mangling a particular word, Lexicon is the fix. ## What it is not Not a dictation app and not a speech recognizer. It runs after whatever produced the transcript, and it composes with Wispr Flow, Superwhisper, macOS dictation and an agent's own built-in speech-to-text rather than replacing them. Voice modes that never produce an editable text box (ChatGPT Voice, Gemini Live) are out of reach, because there is no transcript to correct. -------------------------------------------------------------------------------- ## Install The one command that works for most people (macOS, Linux; checks for Node 20+, installs the CLI, then runs the setup wizard): curl -fsSL https://ashlrai.github.io/lexicon/install.sh | sh No global install at all, any platform with Node 20 or newer: npx @ashlr/lexicon@latest setup Other routes: brew install ashlrai/tap/lexicon # macOS and Linux npm i -g @ashlr/lexicon # Node 20+ Inside Claude Code, as a plugin (MCP server + hooks + skill + /lexicon command, no build step): claude plugin marketplace add ashlrai/lexicon claude plugin install lexicon@ashlrai What `lexicon setup` does, in order: creates ~/.config/lexicon/lexicon.yaml; asks how the user's own name and their company or product should be spelled, and generates the aliases speech-to-text is likely to produce for each; offers the four starter packs (155 curated terms); offers to harvest proper nouns from the repository the user is standing in; registers the MCP server (and, for Claude Code, the hooks) in every agent client it detects; optionally installs the loopback API as a login service; optionally exports into the user's dictation app. Every step is safe to rerun and nothing is duplicated. Non-interactive: `lexicon setup --yes` creates the lexicon and installs into every detected client. The three steps that write a lot or install a service stay opt-in: add `--packs developer,ai,voice-tools`, `--harvest` and `--serve`. `--dry-run` prints the plan and writes nothing. `--json` prints a machine-readable summary. `--clients none` installs into nothing. ## MCP server Name: `lexicon`. Transport: stdio. Binary: `lexicon-mcp` (on PATH after a global install), or `lexicon mcp`, or `node /plugin/mcp-server.mjs`. The lexicon file is re-read on every call, so edits take effect immediately. Config block for any MCP client: { "mcpServers": { "lexicon": { "command": "lexicon-mcp", "args": [] } } } Also served as JSON at https://lexicon.ashlr.ai/mcp.json. Clients that `lexicon install --apply` configures automatically, each writing that client's own config file: claude, claude-desktop, codex, cursor, windsurf, gemini, vscode. For anything else, `lexicon install generic` prints the block to paste. ### Tools (19) - `normalize_transcript`: Correct a dictated transcript and report what changed. - `add_term`: Add a canonical spelling, with aliases suggested when omitted. - `remove_term`: Remove a term. - `list_terms`: List or search the merged lexicon. - `export_lexicon`: Export to any of the fifteen formats. - `learn_correction`: Record "heard X, meant Y" as a new alias. - `suggest_canonical`: Closest existing terms to a garbled word, for "did you mean". - `lexicon_stats`: Hits per term, totals, never-hit terms. - `harvest_repo`: Find proper nouns in a repository worth adding. - `suggest_terms`: Propose aliases, terms and stale entries from usage. - `apply_suggestion`: Apply one accepted suggestion. - `trust_project`: Show, trust or untrust a project .lexicon.yaml. - `lexicon_doctor`: The doctor checks as structured data. - `install_client`: Preview or write the MCP config for a named client. - `setup_lexicon`: Plan or run first-time setup non-interactively. - `serve_status`: Whether the loopback API on 127.0.0.1:41733 is up. - `list_packs`: The four starter packs and which are installed. - `add_pack`: Install a starter pack. - `import_dictionary`: Import a Wispr, Superwhisper, macOS, espanso, CSV or JSON dictionary. ### Resources (2) - `lexicon://me`: The merged lexicon as markdown. What an agent should read at session start. - `lexicon://json`: The merged lexicon as JSON. ### Prompts (2) - `voice-context`: The lexicon plus an instruction to apply it for the rest of the session. - `onboard`: Walks the agent through first-run setup, then calls setup_lexicon. ### Writes are gated Project-scope writes go through a trust gate: a repository's `.lexicon.yaml` is not merged into model context until the user has seen a preview and trusted it, and trust is pinned to the file's sha256. `setup_lexicon`, `install_client` and `trust_project` preview by default and only write when passed `apply: true` or `action: 'trust'`. -------------------------------------------------------------------------------- ## Where the correction is applied 1. Before an agent reads a prompt. The MCP server, plus a Claude Code plugin whose SessionStart hook hands the model the lexicon once per session and whose UserPromptSubmit hook corrects each dictated prompt on its way in. 2. Before you press send in a browser chat. An extension that rewrites the composer in place on ChatGPT, Claude, Gemini, Grok, Perplexity, Microsoft Copilot and Poe, and on any other site the user switches it on for. Runs in Chrome, Edge, Brave and Firefox. 3. In any macOS text field. A menu bar app that watches the focused field through the Accessibility API and rewrites dictated text in place, with local push-to-talk via whisper.cpp and a loopback HTTP API on 127.0.0.1:41733. All three read the same file: `~/.config/lexicon/lexicon.yaml`, plus an optional per-project `.lexicon.yaml` at a repository root. ## The file version: 1 terms: - canonical: Ashlr.AI aliases: [Ashler, Ashlar, "Ashley our AI"] phonetic: ASH-ler category: brand notes: My company. Never write "Ashlar". - canonical: SaaS aliases: [sass] category: acronym never: [sauce] # a real word; leave it alone ## Exports and imports Fifteen export formats: wispr, superwhisper, macos, espanso, whisper-prompt, openai, deepgram, assemblyai, azure, google, claude-md, markdown, text, csv, json. Seven importers read back: wispr, superwhisper, macos, espanso, text, csv, json. So an existing Wispr Flow or Superwhisper dictionary comes over in one command, and the same words go back out into whichever engine's own biasing parameter accepts them. ## Measured results whisper.cpp base.en, proper-noun recall 41.9% -> 82.8%. small.en with the lexicon also passed as a Whisper initial prompt, 76.0% -> 95.7%. Zero of 72 ordinary prose sentences changed. About 0.3 ms to normalize one sentence. The audio rows use macOS text-to-speech across three voices, which is far cleaner than a real microphone, so expect lower raw recall on real speech. Method, corpus and remaining failures: https://github.com/ashlrai/lexicon/blob/main/docs/BENCHMARK.md Against the alternatives, on the same 330 clips through the same recognizer (small.en) with the same seventy-term lexicon in every row, only the fixing strategy changing: raw whisper.cpp 45.9%, exact-string substitution of the kind macOS Text Replacement does 62.0%, the same plus a casing rule per term 71.3%, whisper.cpp's own --prompt hint list 76.0%, Lexicon 91.0%. Exact substitution cannot reach a mis-hearing nobody wrote down in advance, which is what the phonetic and fuzzy tiers are for. The --prompt list is a complement rather than a rival, and stacks with the lexicon to 95.7%. The raw row cannot wrongly change clean prose because nothing runs, which is the absence of the feature and not a safety advantage. The --prompt row is unmeasured rather than zero: it biases the recognizer itself, so anything it changes is already in the transcript this metric scores. Reproduce the table with npm run bench:compare after one npm run bench:audio. ## Privacy The lexicon is a local YAML file. No account, no sync, no telemetry. The CLI, hooks, MCP server, loopback API and extension make no request beyond 127.0.0.1. The only outbound request in the codebase is `lexicon voice` fetching a whisper.cpp model on first use. Audio never leaves the machine. Threat model: https://github.com/ashlrai/lexicon/blob/main/SECURITY.md ## Known limits - The browser extension installs from the release zip; it is not in the Chrome Web Store or on Firefox Add-ons yet. - The macOS app is ad-hoc signed, not notarized. - Windows and Linux have the CLI, the MCP server and the extension, but no tray app. - Voice modes with no text box cannot be corrected. -------------------------------------------------------------------------------- ## FAQ ### Why does dictation get my company name wrong? Because the name is out-of-vocabulary. A speech recognizer scores candidate words against a language model built from ordinary text, and an invented name has no prior in it, so the decoder picks the nearest common-sounding sequence it does know: "Ashlr.AI" becomes "Ashler", "Kubernetes" becomes "Cuban eats", "Vercel" becomes "versal". The audio was fine and the microphone was fine; the vocabulary was missing. Lexicon fixes it afterwards by mapping the spellings you actually get back to the one you meant. ### How do I install Lexicon? One command: `curl -fsSL https://ashlrai.github.io/lexicon/install.sh | sh`. It checks for Node 20 or newer, installs the `@ashlr/lexicon` CLI and then runs `lexicon setup`, which writes `~/.config/lexicon/lexicon.yaml`, asks how your company and your own name should be spelled, and registers the MCP server with every agent client it finds. `brew install ashlrai/tap/lexicon` and `npm i -g @ashlr/lexicon` install the same CLI, and `npx @ashlr/lexicon@latest setup` runs the wizard with no global install at all. ### How do I fix a brand name in ChatGPT, Claude, Claude Code, Codex or Cursor? Add the term once and Lexicon applies it everywhere. `lexicon setup` registers the Lexicon MCP server in the config file of every client it detects (Claude Code, Claude Desktop, Codex, Cursor, Windsurf, Gemini CLI, VS Code), and in Claude Code it also installs SessionStart and UserPromptSubmit hooks so the correction reaches the model before it reads your prompt. For ChatGPT, Claude.ai, Gemini, Grok, Perplexity, Copilot and Poe in a browser, the Lexicon extension rewrites the composer before you press send. You can add the term from the terminal with `lexicon add "Ashlr.AI"`, or just tell the agent "it is Ashlr.AI, not Ashler" and it calls the `learn_correction` tool. ### Does Lexicon work with Wispr Flow, Superwhisper or macOS dictation? Yes, and in both directions. Lexicon runs after whatever produced the transcript, so it corrects the text those apps write before an agent or a text field sees it. It also exports into their own dictionaries: `lexicon export wispr` writes the CSV that Wispr Flow’s Dictionary > Import reads, `lexicon export superwhisper` writes its replacements JSON, and `lexicon export macos` writes a Text Replacement `.plist` for System Settings. `lexicon import` reads all three back, so a dictionary you have already trained comes over in one command instead of being retyped. ### Does Lexicon work in Slack, Mail, Notes and other Mac apps? Yes, through the macOS menu bar app. It watches the focused text field through the Accessibility API and rewrites dictated text in place, so it works in Slack, Mail, Notes, your editor, anywhere there is a text field, and you grant Accessibility permission once in System Settings > Privacy & Security. Local push-to-talk with whisper.cpp is built in, and so is a loopback HTTP API on 127.0.0.1 if you would rather call it from your own script. Windows and Linux have the CLI, the MCP server and the browser extension, but no tray app yet. ### Is my text sent anywhere? No. Your lexicon is a plain YAML file at `~/.config/lexicon/lexicon.yaml`: there is no account, no sync and no telemetry, and the CLI, the hooks, the MCP server, the local API and the browser extension make no network request beyond the loopback interface. The only outbound request anywhere in the codebase is `lexicon voice` downloading a whisper.cpp model the first time you use local push-to-talk; audio itself never leaves the machine. The full threat model, including how an untrusted project lexicon is kept out of model context, is in SECURITY.md. ### What is an MCP server, and do I need one? MCP, the Model Context Protocol, is a standard way for an AI agent to call tools that run on your own machine. Lexicon ships one, named `lexicon`, over stdio, with nineteen tools, two resources and two prompts, so an agent can normalize a transcript, add a term, learn a correction or run setup without you opening a terminal. You want it if you talk to an agent and need the names fixed before the agent acts. You do not need it for the browser extension, the menu bar app or the CLI, which read the same file directly. ### How is this different from a dictation app’s custom dictionary? A dictation app’s dictionary only applies to the text that app produced. Agents increasingly own their own speech-to-text, so a transcript made inside ChatGPT, Claude Code or a phone keyboard never passes through Wispr Flow or Superwhisper, and the same name breaks again in every new place. Lexicon is one file you own, applied at three points instead: before an agent reads a prompt, before you press send in a browser chat, and in any macOS text field. It exports into those dictionaries too, so it replaces none of them and reaches where they cannot. ### What does Lexicon cost? Nothing. Lexicon is free and MIT-licensed, with no paid tier, no account and no telemetry. The matcher, the CLI, the MCP server, the Claude Code plugin, the browser extension and the macOS menu bar app are all in one public repository at github.com/ashlrai/lexicon. -------------------------------------------------------------------------------- ## Verify an install worked lexicon normalize "tell Ashler to ship it" # prints: tell Ashlr.AI to ship it lexicon doctor # files, hooks, MCP registration, clipboard, whisper lexicon stats # hits per term, and terms never hit Or over MCP: call `lexicon_doctor` and read `ok`; call `normalize_transcript` with a sentence containing a known alias and check `changed`. ## Downloads - Browser extension (Chrome, Edge, Brave): https://github.com/ashlrai/lexicon/releases/latest/download/lexicon-extension.zip Unpacked zip; load it at chrome://extensions with Developer mode on. - Browser extension (Firefox): https://github.com/ashlrai/lexicon/releases/latest/download/lexicon-extension-firefox.zip Load it as a temporary add-on from about:debugging. - LexiconBar for macOS: https://github.com/ashlrai/lexicon/releases/latest/download/LexiconBar.app.zip Menu bar app, ad-hoc signed: right-click > Open the first time. ## Links - Quickstart: https://github.com/ashlrai/lexicon/blob/main/docs/QUICKSTART.md - Install into your agents: https://github.com/ashlrai/lexicon/blob/main/docs/CLIENTS.md - MCP server reference: https://github.com/ashlrai/lexicon/blob/main/docs/MCP.md - Agent-native usage: https://github.com/ashlrai/lexicon/blob/main/docs/AGENT-NATIVE.md - For agents: https://github.com/ashlrai/lexicon/blob/main/docs/AGENTS.md - FAQ: https://github.com/ashlrai/lexicon/blob/main/docs/FAQ.md - Exports and imports: https://github.com/ashlrai/lexicon/blob/main/docs/EXPORTS.md - Browser extension: https://github.com/ashlrai/lexicon/blob/main/docs/EXTENSION.md - macOS menu bar app: https://github.com/ashlrai/lexicon/blob/main/docs/MACOS-APP.md - CLI reference: https://github.com/ashlrai/lexicon/blob/main/docs/CLI.md - Benchmark and method: https://github.com/ashlrai/lexicon/blob/main/docs/BENCHMARK.md - Security and trust model: https://github.com/ashlrai/lexicon/blob/main/SECURITY.md - Repository: https://github.com/ashlrai/lexicon - npm: https://www.npmjs.com/package/@ashlr/lexicon - Interactive demo: https://ashlrai.github.io/lexicon/ - Written for agents: https://github.com/ashlrai/lexicon/blob/main/docs/AGENTS.md