How to Find Configuration Files in Automattic/harper: A Complete Guide to Core, LSP, and Desktop Settings
Harper stores configuration across five distinct areas—core defaults in 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 and 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 - Purpose: Built-in rule sets, dictionary data, and default lint configuration
- User override: Not writable at runtime; modify the source and rebuild
{
"rules": {
"no-passive-voice": { "enabled": true, "severity": "error" },
"closed-compound-nouns": { "enabled": false }
},
"dictionary": { "dialect": "american" }
}
To load these defaults programmatically:
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 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, the Config struct defines default paths using dirs::config_dir():
// 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
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 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 |
Static Tauri configuration (window size, permissions, security policies) |
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):
// From harper-desktop/src-tauri/src/config/mod.rs
let config_path = config_dir()?.join("harper-desktop");
Accessing Settings from TypeScript
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, 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 |
Block definition for Gutenberg integration |
| VS Code extension | packages/vscode-plugin/package.json |
Extension manifest and contribution points |
| Chrome extension | packages/chrome-extension/package.json |
Browser extension configuration |
| Web documentation | packages/web/vite.config.ts |
Vite build configuration and sidebar routing |
| Web documentation | packages/web/tsconfig.json |
TypeScript compiler options |
These files follow standard conventions for their respective ecosystems. The WordPress block.json exemplifies plugin-specific JSON descriptors:
{
"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:
# 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.jsonharper-core/irregular_verbs.jsonbiome.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/master/harper-core/default_config.json) |
Default lint rule set and dialect |
[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/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/master/harper-desktop/src-tauri/tauri.conf.json) |
Static Tauri application configuration |
[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.jsonand compile into the binary—edit the source to change baseline behavior. - Harper LS user configuration resolves to
~/.config/harper-ls/viadirs::config_dir()as implemented inharper-ls/src/config.rs. - Harper Desktop settings store separately under
~/.config/harper-desktop/, with path resolution inharper-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). git ls-files '**/*.json'andgit 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 using the dirs::config_dir() crate.
How do I change Harper's default lint rules for all users?
Edit 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 exposes the same information. Both respect $XDG_CONFIG_HOME on Unix systems and %APPDATA% on Windows.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →