Main Modules in Automattic Harper: A Complete Architecture Breakdown

The Automattic Harper project organizes its grammar-checking platform into nine distinct modules spanning Rust crates, WebAssembly bindings, JavaScript packages, and desktop applications, all unified under a single monorepo workspace. These components range from the core linting engine to language-server-protocol implementations and browser extensions.

Harper is an open-source grammar checker designed to run everywhere—from browsers to native desktop apps—while maintaining a single Rust-based core for its linguistic logic. Understanding the main modules in Automattic Harper helps developers choose the right integration path, whether they need a command-line tool, a library for their web app, or a full desktop experience. Each module lives in the repository root as a separate crate or package, tied together by a shared Cargo workspace and pnpm configuration.

Core Rust Modules

The foundation of Harper rests on several specialized Rust crates that handle everything from basic linting to document-specific parsing.

harper-core: The Grammar Engine

harper-core is the language-agnostic heart of the system. Located in the harper-core directory, this crate contains the actual grammar-checking logic that all other modules consume.

In harper-core/src/lib.rs, the crate defines the public API for linting documents, including text parsing and span generation. Every other component—from the CLI to the WASM build—depends on this crate for the actual linguistic analysis. When you invoke a lint function anywhere in the Harper ecosystem, it ultimately calls into this core library.

harper-ls: Language Server Protocol Implementation

harper-ls exposes Harper’s capabilities to modern editors through the Language Server Protocol (LSP). Found in the harper-ls crate, this module bridges the core engine with IDE features like real-time diagnostics and code actions.

The entry point at harper-ls/src/main.rs initializes the LSP server and wires the core linter to editor requests, supporting VS Code, Neovim, Helix, Zed, and other LSP-compatible editors.

harper-cli: Command-Line Interface

harper-cli provides a standalone binary for debugging and direct usage of the core engine. This crate handles argument parsing and file I/O for quick linting tasks without editor integration.

The harper-cli/src/main.rs file parses CLI arguments and forwards text directly to the core linter, making it useful for CI/CD pipelines or quick local checks.

harper-wasm: WebAssembly Bindings

harper-wasm compiles the Rust core to WebAssembly, enabling browser and Node.js usage. The crate at harper-wasm exposes a wasm_bindgen API that harper.js consumes.

The entry point in harper-wasm/src/lib.rs wraps core functionality for JavaScript environments, allowing the grammar engine to run in web pages without server-side processing.

harper-typst: Document-Specific Parsing

harper-typst extends the core engine with support for Typst documents. This integration parses Typst ASTs and translates them into Harper spans for linting academic papers and technical documents.

Located in harper-typst/src/lib.rs, this module serves as the entry point for translating Typst-specific syntax while leveraging the same linting rules as the main engine.

harper-thesaurus: Lexical Resources

harper-thesaurus powers synonym suggestions and enriched spelling checks. This auxiliary crate loads static word-frequency lists and thesaurus data used by the main linter to suggest corrections.

The harper-thesaurus/src/lib.rs file initializes these lexical resources, which the core engine references when generating spelling hints and style improvements.

JavaScript and Web Ecosystem

Harper’s web presence relies on a layered JavaScript architecture that wraps the WebAssembly build.

harper.js: The JavaScript API

harper.js (located in packages/harper.js) provides a friendly JavaScript façade around the WASM module. The packages/harper.js/src/index.ts file loads the WebAssembly bundle and re-exports high-level functions like lint and configure.

This package allows Node.js and browser applications to use Harper without managing the WebAssembly compilation directly.

Web Demo and Documentation Site

packages/web houses the public Harper website, built with Vite and SvelteKit. The packages/web/src/routes/+layout.svelte file bootstraps the demo UI that showcases the linting flow in real-time.

This module serves as both documentation and a live playground for testing Harper’s capabilities against sample text.

Desktop and Plugin Integrations

Beyond core libraries, Harper ships with native applications and thin wrapper plugins for various ecosystems.

harper-desktop: Tauri Application

harper-desktop is a cross-platform desktop application built with Tauri v2. Located in the harper-desktop directory, this crate combines a web-based UI with native overlay highlighting capabilities.

The entry point at harper-desktop/src-tauri/src/main.rs launches the Tauri window and manages the highlighter service, providing system-native grammar checking that works across macOS, Windows, and Linux.

Editor Plugins and Extensions

packages/*-plugin directories contain thin wrappers for Chrome, Firefox, VS Code, Obsidian, WordPress, and other platforms. These plugins typically delegate to either harper.js or the LSP server, depending on the host environment’s capabilities.

Each plugin’s src/manifest.json or src/main.ts serves as the integration point, embedding Harper into existing workflows with minimal overhead.

How the Modules Connect

All modules share a common workspace configuration defined in the root Cargo.toml and pnpm-workspace.yaml. This monorepo structure ensures that the heavy-weight Rust core remains the single source of truth while allowing flexible deployment across native, WASM, and JavaScript runtimes.

The architecture follows a deliberate layering pattern: harper-core contains the logic, harper-wasm exposes it to the web, harper.js simplifies the API, and various consumer modules (desktop, plugins, CLI) provide the final user interface.

Getting Started with Each Module

To use Harper from the command line, install and run the CLI:


# Install from source

cargo install --path harper-cli

# Lint a Markdown file

harper-cli lint example.md

For JavaScript projects, import the high-level API:

import { lint } from "harper.js";

const text = "She don't know nothing.";
const result = await lint(text, { dialect: "american" });

console.log(result.lints);
// → [{ message: "Double negative", ... }]

To start the LSP server for editor integration:


# Run the language server

cargo run -p harper-ls -- --stdio

For desktop application development, invoke the core through Tauri commands:

// src/lib/client.ts
import { invoke } from "@tauri-apps/api/tauri";

export async function lintDocument(text: string) {
  return invoke("lint_text", { text });
}

Summary

  • harper-core (src/lib.rs) provides the grammar-checking engine that all other modules depend on.
  • harper-ls exposes linting via Language Server Protocol for editor integration.
  • harper-cli offers standalone command-line access for scripts and debugging.
  • harper-wasm compiles the core to WebAssembly for browser environments.
  • harper.js wraps the WASM build with a TypeScript-friendly API.
  • harper-desktop delivers a native Tauri-based application with overlay highlighting.
  • harper-typst adds document-specific support for the Typst markup language.
  • harper-thesaurus supplies lexical data for spelling suggestions and synonyms.
  • Editor plugins distribute Harper through marketplace extensions for browsers and IDEs.

Frequently Asked Questions

What is the entry point for the core grammar engine?

The core grammar engine initializes in harper-core/src/lib.rs, which defines the public API for document parsing and lint generation. All other modules, whether compiling to native code or WebAssembly, import this crate to access the actual linguistic logic.

How does Harper support browser usage?

Harper compiles its Rust core to WebAssembly through the harper-wasm crate, then wraps it with the harper.js package. The wasm_bindgen exports in harper-wasm/src/lib.rs allow JavaScript environments to load and execute the grammar checker without requiring a server backend.

Can I use Harper as a language server in my editor?

Yes. The harper-ls crate implements the Language Server Protocol, starting from harper-ls/src/main.rs. You can run it directly with cargo run -p harper-ls -- --stdio or install it globally to provide real-time grammar checking in LSP-compatible editors like Neovim, VS Code, or Helix.

Where is the architecture documented beyond source files?

The repository includes an ARCHITECTURE.md file at the root that provides a canonical description of component interactions and data flow. This document explains how the Rust crates, JavaScript packages, and plugin wrappers communicate to provide a unified grammar-checking experience across platforms.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →