Open-Source Grammar Checking: How Typlx Works Under the Hood
June 27, 2026
Open-source grammar checking has come a long way, but there has always been a gap. LanguageTool offers an open-source core built on hand-written rules and pattern matching. Harper is a fast, Rust-based rule checker designed for speed and simplicity. Both are valuable projects, but neither delivers what modern writers increasingly need: LLM-powered, browser-integrated, local-first grammar checking. That combination simply did not exist as an open-source project until Typlx. This post is a technical deep-dive into how Typlx works, why it is built the way it is, and how you can contribute.
The Central Design Constraint: Local-First
Every architectural decision in Typlx flows from a single constraint: grammar checking must happen on the user's device. Your text never leaves your machine. This rules out the backend API approach that most commercial grammar checkers rely on, where your keystrokes are sent to a remote server for analysis. The trade-off is real — local inference requires the user to run a local model server, and smaller models cannot match the quality of the largest cloud-hosted LLMs. But the privacy guarantee is absolute, and for many users and organizations, that guarantee is non-negotiable. Typlx accepts this trade-off and optimizes within it rather than compromising on it.
Architecture: The Chrome Extension
Typlx ships as a Chrome extension built on Manifest V3, Chrome's current extension platform. Manifest V3 introduces a service worker model in place of persistent background pages, which influences how the extension manages state and communicates with the local LLM server. Here is the high-level directory structure:
typlx-extension/
├── manifest.json
├── background/
│ └── service-worker.js
├── content/
│ ├── content-script.js
│ └── llm-bridge.js
├── popup/
│ ├── popup.html
│ └── popup.js
└── models/
└── grammar-model/
Content Script Layer
The content script is injected into every page the user visits and has two numbered responsibilities:
- Input detection. The content script monitors the DOM for editable elements — text inputs, textareas, contenteditable regions, and rich text editors. It attaches event listeners and uses a debounce timer to avoid triggering grammar checks on every keystroke.
- DOM annotation. When grammar suggestions are returned from the LLM, the content script annotates the page by underlining flagged text and attaching tooltip-style suggestion overlays. It manages the lifecycle of these annotations, removing them when the user edits the text or accepts a suggestion.
The LLM Bridge
The LLM bridge (llm-bridge.js) is the layer responsible for communicating with the local model server. Typlx does not bundle its own inference engine. Instead, it communicates over HTTP with a locally running model server. The two primary supported backends are Ollama and LocalAI, though any OpenAI-compatible API running on localhost will work. All communication is strictly localhost-only — the bridge refuses to send requests to any non-local address. This is enforced at the code level and verified during the Chrome Web Store review process. The bridge handles prompt construction, request formatting, response parsing, and error handling (for example, when the local server is not running or the model has not been pulled yet).
Service Worker
The Manifest V3 service worker replaces the persistent background page from Manifest V2. In Typlx, the service worker handles:
- Extension lifecycle management (installation, updates, enabling/disabling)
- Routing messages between the content script, the popup, and the LLM bridge
- Managing user preferences and extension state (which sites are enabled, sensitivity settings, model configuration)
- Badge updates to show the number of active suggestions on the current page
- Coordinating the wakeup/sleep cycle inherent to Manifest V3 service workers, ensuring that in-flight grammar checks are not lost when the worker is terminated
How Grammar Checking Works Step by Step
Here is what happens from the moment you type to the moment you see a suggestion underline:
- Input detection with debounce timer. The content script detects a change in an editable element. A debounce timer (default: 800ms of inactivity) prevents the extension from firing on every keystroke. Only when the user pauses typing does the process continue.
- Text extraction. The content script extracts the text content from the editable element. For simple inputs and textareas, this is straightforward. For contenteditable regions and rich text editors (Google Docs, Notion, etc.), the extraction logic walks the DOM tree and reconstructs the plain text while preserving paragraph boundaries.
- Prompt construction. The extracted text is wrapped in a structured prompt designed for grammar checking. The prompt instructs the model to return a JSON array of suggestions, each containing the original text span, the suggested replacement, the category of error (spelling, grammar, style, punctuation), and a brief explanation.
- Local inference via localhost fetch. The LLM bridge sends the constructed prompt to the local model server via a
fetch()call tohttp://localhost:<port>/v1/chat/completions. The request includes parameters for temperature (set low, typically 0.1, for deterministic output) and max tokens. The bridge streams the response where the server supports it. - Result parsing. The bridge parses the model's response, extracting the JSON array of suggestions. It validates the structure, discards malformed entries, and maps each suggestion's text span back to the character offsets in the original extracted text.
- DOM annotation. The content script receives the parsed suggestions and annotates the DOM. Each flagged span is wrapped in a highlight element with a colored underline (red for errors, blue for style suggestions). A click or hover on the underline reveals a tooltip with the suggestion, explanation, and accept/dismiss buttons.
- User interaction. When the user accepts a suggestion, the content script replaces the flagged text in the editable element and removes the annotation. When the user dismisses a suggestion, only the annotation is removed. Accepted and dismissed suggestions are logged locally (never transmitted) to improve prompt construction over time.
Why LLMs Rather Than Rule-Based Checking?
Rule-based grammar checkers like LanguageTool, Harper, and Vale work by matching text against predefined patterns and rules. They are fast, predictable, and excellent for catching common errors — subject-verb agreement, comma splices, misspellings, and style guide violations. For many use cases, they are sufficient and arguably preferable.
LLMs bring a different capability: contextual understanding. Rather than matching patterns, an LLM processes the entire sentence (or paragraph) as a unit and evaluates it holistically. This produces advantages in several areas:
- Word choice in context. An LLM can distinguish between "affect" and "effect" based on the sentence's meaning, not just the surrounding words.
- Awkward phrasing. Rule-based systems struggle with sentences that are grammatically correct but awkwardly constructed. LLMs can flag these and suggest more natural alternatives.
- Tone and register. An LLM can detect when formal language appears in a casual context (or vice versa) and suggest adjustments.
- Complex sentence structure. Dangling modifiers, misplaced clauses, and ambiguous pronoun references are difficult for rule-based systems but natural for LLMs to catch.
- Multilingual and code-switching text. LLMs handle text that mixes languages or includes technical jargon more gracefully than rule-based systems with fixed dictionaries.
The trade-offs are real. LLM inference is slower than rule matching. It requires a local model server. Smaller models will occasionally hallucinate suggestions that are incorrect. Typlx addresses this by keeping suggestion confidence thresholds high and by planning to bundle a lightweight, fine-tuned model specifically optimized for grammar checking in a future release, removing the need for users to install a separate model server.
The Open-Source Model and What It Enables
Typlx is open-source under the MIT License. This is not a marketing decision — it is a structural one. Open source enables four things that matter for a tool that processes your writing:
Auditability. Any user, security researcher, or organization can read the source code and verify that text never leaves the device. You do not have to trust Typlx's privacy claims — you can verify them. The localhost-only constraint in the LLM bridge is visible in the code, and any attempt to change it would be visible in the commit history.
Community contributions. Grammar checking is inherently language-specific and context-specific. The prompt templates, suggestion categories, and UI behaviors that work well for academic English may not work well for casual German or technical Japanese. An open-source model allows native speakers and domain experts to contribute improvements that the core team could not build alone.
Forking and adaptation. Organizations with specific needs — compliance requirements, custom style guides, integration with internal tools — can fork Typlx and adapt it without waiting for upstream features. The MIT License imposes no restrictions on this.
Trust without reliance on trust. Closed-source grammar checkers ask you to trust that they handle your data responsibly. Open-source grammar checkers let you verify it. This distinction matters especially for journalists, lawyers, medical professionals, and anyone writing sensitive content.
How to Contribute
Typlx welcomes contributions at every level. See CONTRIBUTING.md in the repository for detailed guidelines. Here are the main categories:
Non-Code Contributions
- Bug reports with reproduction steps
- Prompt template improvements for better suggestion quality
- Documentation improvements and tutorials
- Translations and localization for non-English languages
- Testing with different local model servers and models
- Writing about Typlx, creating guides, or recording walkthroughs
Code Contributions
- Content script improvements (better detection of editable elements, support for more rich text editors)
- LLM bridge enhancements (support for additional model servers, streaming improvements, error handling)
- UI/UX improvements to the suggestion overlay and popup
- Performance optimizations (reducing debounce latency, caching repeated checks)
- Test coverage (unit tests, integration tests, end-to-end tests with Puppeteer)
- Accessibility improvements (keyboard navigation, screen reader support)
Infrastructure
- CI/CD pipeline improvements
- Automated testing against multiple Chrome versions
- Build system optimizations
- Model benchmarking infrastructure (comparing grammar-check quality across different local models)
- Documentation site generation and hosting
Get the Extension
Typlx is free and open-source. You can install it from the Chrome Web Store, or clone the repository and build it yourself. If you try it and find something that could be better, open an issue or submit a pull request. Every contribution — from a typo fix in documentation to a new model server integration — makes the project better for everyone.
Typlx is open-source. Contributions welcome. Also available as a mobile keyboard for Android and iOS.
Last updated: June 2026