# How to Debug Automattic/harper: A Complete Guide to Troubleshooting the Grammar Checker

> Debug Automattic/harper easily with RUST_BACKTRACE, RUST_LOG, CLI debug commands, component debuggers, and justfile recipes. Troubleshoot the grammar checker effectively.

- Repository: [Automattic/harper](https://github.com/Automattic/harper)
- Tags: how-to-guide
- Published: 2026-07-26

---

**To debug Automattic/harper, set `RUST_BACKTRACE=1` and `RUST_LOG=debug` environment variables, use the CLI's built-in debug subcommand, attach debuggers to individual components like `harper-ls` or the desktop highlighter, and leverage the repository's `justfile` recipes for streamlined development workflows.**

Automattic/harper is a multi-language grammar-checking ecosystem built around a Rust core (`harper-core`) that powers CLI tools, language servers, desktop overlays, and WebAssembly bindings. Because the same core library runs across diverse front-ends—from terminal applications to browser plugins—debugging requires component-specific strategies while leveraging common Rust tooling. This guide covers the exact source file locations, environment variables, and diagnostic commands needed to troubleshoot issues across the entire Harper codebase.

## Debugging the Core Engine (`harper-core`)

The heart of Harper lives in the `harper-core` crate, where most runtime errors surface. To debug the core library, compile with backtrace support and run the test suite:

```bash
RUST_BACKTRACE=1 cargo test -p harper-core

```

If you need to step through execution, attach `lldb` or `gdb` directly to the compiled test binaries. The core's entry points are located in [`harper-core/src/lib.rs`](https://github.com/Automattic/harper/blob/main/harper-core/src/lib.rs), while the primary lint group construction happens in [`harper-core/src/expr_linter_skeleton.rs`](https://github.com/Automattic/harper/blob/main/harper-core/src/expr_linter_skeleton.rs). Adding `eprintln!` statements in these files provides immediate diagnostic output during development.

## Debugging the CLI (`harper-cli`)

The CLI serves as the primary debugging tool for Harper. It includes a dedicated `debug` subcommand defined in the `Cli` struct at `harper-cli/src/main.rs#L43-L51`, which prints internal state when combined with linting flags.

Run the CLI with debug output enabled:

```bash
cargo run -p harper-cli -- lint --debug path/to/file.txt

```

The actual lint implementation resides in [`harper-cli/src/lint.rs`](https://github.com/Automattic/harper/blob/main/harper-cli/src/lint.rs). You can add temporary `eprintln!` statements here or in the core library to dump runtime values—these diagnostic prints are stripped before release builds.

## Debugging the Language Server (`harper-ls`)

The LSP server (`harper-ls`) forwards requests from editors like VS Code, Neovim, and Helix to the core engine. To debug the server, run it directly with debug logging enabled:

```bash
RUST_LOG=debug cargo run -p harper-ls -- --stdio

```

The server's request handling logic lives in [`harper-ls/src/backend.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/backend.rs). Insert `tracing::debug!` calls in this file to surface the exact JSON-RPC messages exchanged between the editor client and the Harper backend.

## Debugging the Desktop Highlighter (`harper-desktop`)

The desktop UI consists of a Tauri front-end and a native highlighter process that communicates via newline-delimited JSON. You can attach a debugger to the highlighter by running it as a standalone process:

```bash
cargo run -p harper-desktop -- highlighter

```

The highlighter's IPC messages are defined in [`harper-desktop/src-tauri/src/communication/message.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/communication/message.rs). Use `eprintln!` statements in this module to emit debug diagnostics safely without breaking the JSON protocol. The desktop entry point at [`harper-desktop/src-tauri/src/main.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/main.rs) controls the highlighter process lifecycle and bridges the UI components.

## Debugging WebAssembly Builds (`harper-wasm`)

The WASM module powers browser integrations and the [`harper.js`](https://github.com/Automattic/harper/blob/main/harper.js) npm package. Debugging WebAssembly requires source maps and browser DevTools:

1. Build with development source maps using the `justfile` recipe at `justfile#L63-L77`:
   ```bash
   just build-wasm
   ```

2. Open your browser's DevTools and load a page importing [`harper_wasm.js`](https://github.com/Automattic/harper/blob/main/harper_wasm.js)
3. Set breakpoints in the generated JavaScript—the source maps will map execution back to the original Rust code

The build configuration uses `wasm-pack build --target web --dev` to ensure debug symbols are available.

## Essential Environment Variables

All Rust binaries in the Harper ecosystem respect standard Rust logging and backtrace environment variables:

- **`RUST_LOG`**: Controls verbosity using the `env_logger` crate. Use `RUST_LOG=trace` for maximum output, or target specific crates with `harper_core=debug`.
- **`RUST_BACKTRACE`**: Set to `1` for basic stack traces or `full` for complete call stacks on panic.

Example of filtering logs to the core crate only:

```bash
RUST_LOG=harper_core=debug cargo run -p harper-cli -- lint path/to/file.txt

```

For full diagnostic output during testing:

```bash
RUST_BACKTRACE=full RUST_LOG=debug cargo run -p harper-cli -- lint --quiet examples/README.md

```

## Streamlining Development with Just Commands

Harper includes a comprehensive `justfile` with shortcuts for common debugging tasks. The most useful recipes include:

- **`just dev-desktop`**: Spins up the desktop UI with live-reload enabled
- **`just dev-web`**: Launches the documentation site with embedded linting
- **`just test-harperjs`**: Runs the full JavaScript binding test suite to surface WASM bridge errors
- **`just fmt`**: Runs `cargo fmt` and `pnpm format` to prevent spurious parsing failures

List all available commands with `just --list`. These recipes are defined around `justfile#L33-L41` and provide consistent build flags across components.

## Summary

- **Core debugging**: Use `RUST_BACKTRACE=1 cargo test -p harper-core` and attach debuggers to [`harper-core/src/lib.rs`](https://github.com/Automattic/harper/blob/main/harper-core/src/lib.rs)
- **CLI diagnostics**: Leverage the `debug` subcommand at `harper-cli/src/main.rs#L43-L51` and add `eprintln!` statements in [`harper-cli/src/lint.rs`](https://github.com/Automattic/harper/blob/main/harper-cli/src/lint.rs)
- **LSP troubleshooting**: Run `RUST_LOG=debug cargo run -p harper-ls -- --stdio` and instrument [`harper-ls/src/backend.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/backend.rs)
- **Desktop debugging**: Launch the highlighter process with `cargo run -p harper-desktop -- highlighter` and use `eprintln!` in [`harper-desktop/src-tauri/src/communication/message.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/communication/message.rs)
- **WASM debugging**: Build with `just build-wasm` (defined at `justfile#L63-L77`) and use browser DevTools with source maps
- **Universal logging**: Set `RUST_LOG=trace` and `RUST_BACKTRACE=full` for verbose output across all components

## Frequently Asked Questions

### How do I attach a debugger to the Harper language server in VS Code?

Run the server manually with `RUST_LOG=debug cargo run -p harper-ls -- --stdio` in your terminal, then configure VS Code to connect to this running process. Alternatively, set `"harper.ls.logLevel": "debug"` in your VS Code settings to see debug messages in the editor's output panel without manually launching the server.

### Where should I add print statements when debugging the desktop highlighter?

Add `eprintln!("DEBUG: {:?}", your_variable);` statements in [`harper-desktop/src-tauri/src/highlighter_process.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/highlighter_process.rs) or [`harper-desktop/src-tauri/src/communication/message.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/communication/message.rs). Using `eprintln!` (stderr) instead of `println!` ensures the debug output doesn't interfere with the newline-delimited JSON IPC protocol between the highlighter process and the Tauri front-end.

### How can I debug WebAssembly-specific issues in Harper?

Build the WASM module using `just build-wasm`, which invokes `wasm-pack build --target web --dev` with source maps enabled. Open your browser's DevTools, navigate to the sources tab, and set breakpoints in the generated [`harper_wasm.js`](https://github.com/Automattic/harper/blob/main/harper_wasm.js) file—the source maps will automatically map execution back to the original Rust source code in `harper-wasm/src`.

### What is the fastest way to run tests while debugging the core engine?

Use `RUST_BACKTRACE=1 cargo test -p harper-core` to run the core test suite with full backtraces enabled. This command targets only the `harper-core` package, avoiding unnecessary compilation of the CLI, LSP server, or desktop components while you iterate on core logic in [`harper-core/src/lib.rs`](https://github.com/Automattic/harper/blob/main/harper-core/src/lib.rs) or [`harper-core/src/expr_linter_skeleton.rs`](https://github.com/Automattic/harper/blob/main/harper-core/src/expr_linter_skeleton.rs).