lang-check 0.2.3

Multilingual prose linter with tree-sitter extraction and pluggable checking engines
Documentation
<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="assets/titlecard-dark.png" />
    <source media="(prefers-color-scheme: light)" srcset="assets/titlecard-light.png" />
    <img alt="LangCheck" src="assets/titlecard-light.png" height="79" />
  </picture>
</p>

A fast, extensible grammar and style checker for Markdown, HTML, LaTeX, Typst, and more. Ships as a VS Code extension backed by a Rust core binary that communicates over a length-prefixed Protobuf protocol.

## Features

- **Multi-engine checking** — local Harper engine for instant feedback, optional LanguageTool for deep grammar analysis, external binaries, and WASM plugins via Extism
- **Tree-sitter parsing** — extracts prose from Markdown, HTML, LaTeX, Typst, and more while skipping code blocks, math, and markup
- **SpeedFix panel** — keyboard-driven batch review: press `1``9` for suggestions, `a` to add to dictionary, `i` to ignore, `Space` to skip
- **Inline suggestions** — inlay hints, ghost text completions, and quickfix code actions
- **Standalone CLI**`language-check check`, `fix`, `list-rules`, and `config` subcommands
- **Workspace indexing** — background indexing with redb-backed caching
- **Rule normalization** — unified rule IDs across providers for consistent severity overrides
- **Prose insights** — word count, sentence count, and Automated Readability Index in the status bar
- **Inspector** — debug webview showing AST structure, prose extraction ranges, and check latency
- **i18n** — extension UI localized in English, German, French, and Spanish

## Quick Start

### VS Code Extension

1. Install the extension from the VS Code marketplace (publisher: `KaiErikNiermann`)
2. Open a Markdown, HTML, LaTeX, or Typst file — checking starts automatically on save
3. Press `Alt+F` to open the SpeedFix panel

### CLI

```sh
# Build from source
cd rust-core
cargo build --release

# Check a file
./target/release/language-check check README.md

# Auto-fix high-confidence issues
./target/release/language-check fix docs/

# List available rules
./target/release/language-check list-rules
```

## Project Structure

```
lang-check/
├── rust-core/          Rust core binary (server + CLI)
│   ├── src/
│   │   ├── engines.rs      Harper, LanguageTool, External, WASM engines
│   │   ├── orchestrator.rs  Multi-engine coordinator
│   │   ├── prose.rs         Tree-sitter prose extraction
│   │   ├── rules.rs         Rule normalization
│   │   ├── config.rs        YAML/JSON configuration loader
│   │   ├── workspace.rs     redb-backed workspace indexing
│   │   └── ...
│   └── bin/
│       ├── language-check-server.rs   Protobuf stdio server
│       └── language-check.rs          Standalone CLI
├── extension/          VS Code extension (TypeScript)
│   ├── src/
│   │   ├── extension.ts    Activation, commands, providers
│   │   ├── client.ts       Protobuf IPC client
│   │   ├── api.ts          Public API for other extensions
│   │   ├── downloader.ts   Core binary auto-download
│   │   └── trace.ts        Protobuf message tracing
│   ├── webview/            SpeedFix + Inspector UIs (Svelte 5 + Tailwind)
│   ├── l10n/               Runtime localization bundles
│   └── package.nls.*.json  Command/setting translations
├── proto/              Protobuf schema (checker.proto)
├── docs/               Sphinx documentation
├── scripts/            Build utilities
└── docker-compose.yml  Local LanguageTool server
```

## Configuration

Create a `.languagecheck.yaml` in your workspace root:

```yaml
engines:
  harper: true
  languagetool: true
  languagetool_url: "http://localhost:8010"
  external:
    - name: vale
      command: /usr/bin/vale
      args: ["--output", "JSON"]
      extensions: [md, rst]
  wasm_plugins:
    - name: custom-checker
      path: .languagecheck/plugins/checker.wasm

rules:
  spelling.typo:
    severity: warning
  grammar.article:
    severity: off

performance:
  high_performance_mode: false
  debounce_ms: 300
  max_file_size: 1048576

auto_fix:
  - find: "teh"
    replace: "the"
```

See `language-check config init` to generate a default configuration.

## Development

### Prerequisites

- Rust 2024 edition (1.85+)
- Node.js 18+ and pnpm
- Protobuf compiler (`protoc`)

### Building

```sh
# Rust core
cd rust-core
cargo build

# Extension
cd extension
pnpm install
pnpm run proto:gen
pnpm build
```

### Testing

```sh
# Rust — unit tests + snapshot tests (insta)
cd rust-core
cargo test

# Extension — vitest
cd extension
pnpm test
```

### Linting

```sh
# Rust
cargo clippy -- -D warnings
cargo fmt --check

# TypeScript
cd extension
pnpm lint
```

### Local LanguageTool

```sh
docker compose up -d
# LanguageTool API available at http://localhost:8010
```

### Git Hooks

The project uses [Lefthook](https://github.com/evilmartians/lefthook) for pre-push checks (cargo check, clippy, fmt, test, and tsc).

## Plugin System

Language Check supports three extension mechanisms:

| Type | Sandboxed | Config key | Protocol |
|------|-----------|------------|----------|
| External binary | No | `engines.external` | JSON over stdin/stdout |
| WASM plugin | Yes (Extism) | `engines.wasm_plugins` | `check(input) -> output` export |
| VS Code API | N/A || `LanguageCheckAPI` interface |

See `docs/advanced/plugins.md` for the WASM plugin development guide.

## Documentation

Full documentation is built with Sphinx:

```sh
cd docs
pip install -r requirements.txt
make html
# Open _build/html/index.html
```

## License

[MIT](LICENSE)