# How to Find Configuration Files in Automattic/harper: A Complete Guide to Core, LSP, and Desktop Settings

> Master Automattic/harper configuration. Discover core, LSP, desktop, plugin, and web app settings. This guide makes finding harper config files simple and efficient.

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

---

**Harper stores configuration across five distinct areas—core defaults in [`harper-core/default_config.json`](https://github.com/Automattic/harper/blob/main/harper-core/default_config.json), user-specific files for the language server under `~/.config/harper-ls/`, desktop settings in `~/.config/harper-desktop/`, plugin descriptors in each package, and web-app build configs—with all paths resolvable through the `dirs::config_dir()` pattern in [`harper-ls/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/config.rs) and [`harper-desktop/src-tauri/src/config/mod.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config/mod.rs).**

The **Automattic/harper** repository organizes its configuration across multiple crates and user environments. Whether you're customizing lint rules, debugging the language server, or packaging the desktop app, knowing exactly where each configuration file lives saves hours of searching. This guide maps every configuration entry point in the source tree and shows how Harper resolves them at runtime.

---

## Core Default Configuration

The **core default configuration** ships as a read-only JSON file compiled into the binary. This defines the baseline lint rules, dialect settings, and dictionary data that all Harper tools inherit.

### Location and Structure

- **Source file:** [`harper-core/default_config.json`](https://github.com/Automattic/harper/blob/main/harper-core/default_config.json)
- **Purpose:** Built-in rule sets, dictionary data, and default lint configuration
- **User override:** Not writable at runtime; modify the source and rebuild

```json
{
  "rules": {
    "no-passive-voice": { "enabled": true, "severity": "error" },
    "closed-compound-nouns": { "enabled": false }
  },
  "dictionary": { "dialect": "american" }
}

```

To load these defaults programmatically:

```rust
use harper_core::default_config::DefaultConfig;

fn load_core_defaults() -> harper_core::LintConfig {
    // `DefaultConfig::load()` reads the JSON compiled into the binary.
    DefaultConfig::load().unwrap()
}

```

Modify [`harper-core/default_config.json`](https://github.com/Automattic/harper/blob/main/harper-core/default_config.json) directly when you need to change out-of-the-box behavior, then run `just test-rust` to verify your changes.

---

## Harper LS (Language Server) Configuration

The **language server configuration** handles LSP-specific options: user dictionary paths, ignored lint rules, dialect preferences, and code-action settings. This is the most frequently customized configuration area.

### Runtime Path Resolution

In [`harper-ls/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/config.rs), the `Config` struct defines default paths using `dirs::config_dir()`:

```rust
// Default resolution: $XDG_CONFIG_HOME/harper-ls/ or ~/.config/harper-ls/
config_dir().unwrap().join("harper-ls/dictionary.txt")

```

### Default User Directory

| Platform | Path |
|----------|------|
| Linux/macOS | `~/.config/harper-ls/` or `$XDG_CONFIG_HOME/harper-ls/` |
| Windows | `%APPDATA%\harper-ls\` |

### Creating and Modifying Config Programmatically

```rust
use harper_ls::config::Config;
use std::path::PathBuf;

// The default constructor reads the XDG config directory.
let mut cfg = Config::default();

// Override the dictionary location at runtime (e.g., for tests)
cfg.user_dict_path = PathBuf::from("./my-custom-dictionary.txt");

// Persist the change by writing to the user config folder
cfg.save().expect("Failed to write harper-ls config");

```

The `Config` struct in [`harper-ls/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/config.rs) controls file naming conventions and persistence logic.

---

## Harper Desktop Configuration

The **desktop application** stores UI-related settings and highlighter IPC configuration separately from the language server. It uses Tauri's configuration system with custom Rust-side resolution.

### Configuration Locations

| File | Purpose |
|------|---------|
| [`harper-desktop/src-tauri/tauri.conf.json`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/tauri.conf.json) | Static Tauri configuration (window size, permissions, security policies) |
| [`harper-desktop/src-tauri/src/config/mod.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config/mod.rs) | Runtime config directory resolution |

The Rust module calls `dirs::config_dir()` to resolve `~/.config/harper-desktop/` (or platform equivalent):

```rust
// From harper-desktop/src-tauri/src/config/mod.rs
let config_path = config_dir()?.join("harper-desktop");

```

### Accessing Settings from TypeScript

```ts
import { Client } from './client';

// Retrieve the whole config object from the Rust side
Client.getLintConfig().then((config) => {
  console.log('Current lint config:', config);
});

```

The TypeScript helper resides in [`harper-desktop/src/lib/client.ts`](https://github.com/Automattic/harper/blob/main/harper-desktop/src/lib/client.ts), which communicates with the Rust backend reading from the user config directory.

---

## Plugin and Package Configurations

Harper's **plugin packages** each maintain their own configuration descriptors. These are development-time files, not user-editable at runtime.

| Package | Configuration File | Purpose |
|---------|-------------------|---------|
| WordPress plugin | [`packages/wordpress-plugin/src/harper/block.json`](https://github.com/Automattic/harper/blob/main/packages/wordpress-plugin/src/harper/block.json) | Block definition for Gutenberg integration |
| VS Code extension | [`packages/vscode-plugin/package.json`](https://github.com/Automattic/harper/blob/main/packages/vscode-plugin/package.json) | Extension manifest and contribution points |
| Chrome extension | [`packages/chrome-extension/package.json`](https://github.com/Automattic/harper/blob/main/packages/chrome-extension/package.json) | Browser extension configuration |
| Web documentation | [`packages/web/vite.config.ts`](https://github.com/Automattic/harper/blob/main/packages/web/vite.config.ts) | Vite build configuration and sidebar routing |
| Web documentation | [`packages/web/tsconfig.json`](https://github.com/Automattic/harper/blob/main/packages/web/tsconfig.json) | TypeScript compiler options |

These files follow standard conventions for their respective ecosystems. The WordPress [`block.json`](https://github.com/Automattic/harper/blob/main/block.json) exemplifies plugin-specific JSON descriptors:

```json
{
  "name": "harper/harper",
  "title": "Harper Grammar Checker",
  "category": "common",
  "editorScript": "file:./index.js"
}

```

---

## Searching the Repository for Configuration Files

Use these commands to locate all configuration-related files in the **Automattic/harper** repository:

```bash

# List all JSON configuration files

git ls-files '**/*.json'

# Find config directory resolution code

git grep -R "config_dir"

# Find all Rust files containing Config struct definitions

git grep -l "struct Config" -- '*.rs'

```

Typical `git ls-files` output includes:
- [`harper-core/default_config.json`](https://github.com/Automattic/harper/blob/main/harper-core/default_config.json)
- [`harper-core/irregular_verbs.json`](https://github.com/Automattic/harper/blob/main/harper-core/irregular_verbs.json)
- [`biome.json`](https://github.com/Automattic/harper/blob/main/biome.json) (linting/formatting rules)
- `packages/*/package.json`

---

## Key Files Reference

Bookmark these source locations for quick access:

| File | Purpose |
|------|---------|
| [[`harper-core/default_config.json`](https://github.com/Automattic/harper/blob/main/harper-core/default_config.json)](https://github.com/Automattic/harper/blob/master/harper-core/default_config.json) | Default lint rule set and dialect |
| [[`harper-ls/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/config.rs)](https://github.com/Automattic/harper/blob/master/harper-ls/src/config.rs) | Runtime `Config` struct with path resolution |
| [[`harper-desktop/src-tauri/src/config/mod.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config/mod.rs)](https://github.com/Automattic/harper/blob/master/harper-desktop/src-tauri/src/config/mod.rs) | Desktop config directory handling |
| [[`harper-desktop/src-tauri/tauri.conf.json`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/tauri.conf.json)](https://github.com/Automattic/harper/blob/master/harper-desktop/src-tauri/tauri.conf.json) | Static Tauri application configuration |
| [[`packages/web/vite.config.ts`](https://github.com/Automattic/harper/blob/main/packages/web/vite.config.ts)](https://github.com/Automattic/harper/blob/master/packages/web/vite.config.ts) | Documentation site build configuration |

---

## Summary

- **Core defaults** live in [`harper-core/default_config.json`](https://github.com/Automattic/harper/blob/main/harper-core/default_config.json) and compile into the binary—edit the source to change baseline behavior.
- **Harper LS user configuration** resolves to `~/.config/harper-ls/` via `dirs::config_dir()` as implemented in [`harper-ls/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/config.rs).
- **Harper Desktop settings** store separately under `~/.config/harper-desktop/`, with path resolution in [`harper-desktop/src-tauri/src/config/mod.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config/mod.rs).
- **Plugin configurations** reside in each package's source tree (e.g., [`packages/wordpress-plugin/src/harper/block.json`](https://github.com/Automattic/harper/blob/main/packages/wordpress-plugin/src/harper/block.json)).
- **`git ls-files '**/*.json'`** and **`git grep -R "config_dir"`** quickly surface configuration entry points across the repository.

---

## Frequently Asked Questions

### Where does Harper LS store user configuration on Linux and macOS?

Harper LS follows the **XDG Base Directory Specification**. It stores user configuration in `$XDG_CONFIG_HOME/harper-ls/` if the environment variable is set, otherwise falling back to `~/.config/harper-ls/`. The path resolution logic appears in [`harper-ls/src/config.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/config.rs) using the `dirs::config_dir()` crate.

### How do I change Harper's default lint rules for all users?

Edit [`harper-core/default_config.json`](https://github.com/Automattic/harper/blob/main/harper-core/default_config.json) in the repository source, then rebuild. This JSON file compiles into the binary via `DefaultConfig::load()`, making it the authoritative source for out-of-the-box rule settings. Run `just test-rust` after modifications to ensure the new defaults pass validation.

### What's the difference between harper-ls and harper-desktop configuration?

**Harper LS** configuration controls language server behavior—diagnostics, code actions, dictionary paths, and ignored rules. **Harper Desktop** configuration manages UI state, window geometry, and highlighter IPC settings. They use separate directories (`harper-ls/` vs. `harper-desktop/`) under the XDG config root, with distinct Rust modules handling path resolution.

### How can I programmatically discover where Harper will write config files?

Import the relevant config module and inspect the resolved path. For Harper LS: `Config::default()` reveals the active paths after `dirs::config_dir()` resolution. For Desktop: the `config_dir()` function in [`harper-desktop/src-tauri/src/config/mod.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/config/mod.rs) exposes the same information. Both respect `$XDG_CONFIG_HOME` on Unix systems and `%APPDATA%` on Windows.