How to Explore the Automattic/Harper Project Structure in Bash: A Comprehensive Guide

Use find, tree, and git ls-tree commands to map the Harper monorepo's Rust crates, TypeScript packages, and Tauri desktop app from the terminal.

The Harper project is a sophisticated grammar-checking ecosystem maintained by Automattic, organized as a Rust-and-Node monorepo with multiple interconnected components. Whether you're contributing to the core linting engine, debugging the language server, or extending editor integrations, knowing how to navigate the structure efficiently in Bash saves hours of exploration. This guide provides precise command-line techniques to map the repository, locate entry points, and understand component relationships.

Understanding the Harper Monorepo Architecture

Harper follows a workspace-based monorepo pattern with two primary build systems:

The root ARCHITECTURE.md provides a narrative overview, but Bash exploration reveals the live structure faster.

Core Commands to Map the Repository Structure

List Top-Level Directories for Quick Orientation

git ls-tree -d -r HEAD | cut -f2 | sort -u | awk -F'/' '{print $1}' | uniq

This command strips away nested paths, showing only the repository's immediate children tracked by Git. You'll see harper-core/, harper-cli/, harper-ls/, packages/, harper-desktop/, and other key folders without generated artifacts cluttering the view.

Discover All Rust Crates

find . -name Cargo.toml -exec dirname {} \; | sort

Each Cargo.toml marks an independent Rust crate. In Harper, this reveals:

  • harper-core/ — the grammar-checking engine used by every other component
  • harper-cli/ — command-line interface at src/main.rs
  • harper-ls/ — Language Server Protocol implementation
  • harper-wasm/ — WebAssembly build targeting browsers
  • harper-comments/ — comment parsers for code-aware linting
  • harper-brill/ — Part-of-speech tagging model
  • harper-desktop/src-tauri/ — Tauri backend for the desktop app

Locate All JavaScript/TypeScript Packages

find . -name package.json -exec dirname {} \; | sort

Harper's pnpm-workspace.yaml defines these as workspace members under packages/:

Package Purpose Entry Point
harper.js Browser/Node WASM wrapper src/index.ts
web Documentation site (SvelteKit) src/routes/docs/**
vscode-plugin VS Code extension src/extension.ts
obsidian-plugin Obsidian editor integration main.ts
chrome-plugin Browser extension src/background.ts
harper-editor Shared Svelte UI components src/lib/*.svelte
lint-framework Web demo abstraction layer src/*.ts

Visualize the Desktop Application Structure

tree -L 3 harper-desktop

The Tauri-based desktop app (harper-desktop/) combines:

  • src-tauri/src/main.rs — Rust entry point launching the window and highlighter
  • src/routes/+page.svelte — Svelte UI with editor and settings tabs
  • src/lib/client.ts — TypeScript bridge for addToDictionary and other backend calls
  • vite.config.js — Forces dev server to port 1420 (Tauri requirement)

Finding Entry Points and Key Files

Locate Binary Entry Points in Rust Crates

grep -R "fn main" --include="*.rs" -l | head -10

Or more specifically for the language server:

ls harper-ls/src/main.rs

Critical entry points to bookmark:

Count Source Files by Language

echo "Rust files: $(find . -name "*.rs" | wc -l)"
echo "TypeScript files: $(find . -name "*.ts" | wc -l)"
echo "Svelte files: $(find . -name "*.svelte" | wc -l)"

This gauges relative project size and identifies where your contributions will have the most impact.

Harper's public documentation lives in packages/web/src/routes/docs/. Use find to explore topics:

find packages/web/src/routes/docs -type d | sort

Key directories mirror the site's sidebar structure defined in packages/web/vite.config.ts:

  • about/ — product overview and privacy model
  • weir/ — rule language reference
  • rules/ — generated rule catalog
  • integrations/ — editor plugin guides
  • harperjs/ — JavaScript SDK documentation
  • contributors/ — architecture and testing guides

The authoritative mapping appears in AGENTS.md under "Core Documentation Directories."

Essential Workspace Files to Examine

File Command to Inspect Why It Matters
Cargo.toml cat Cargo.toml Rust workspace membership and dependencies
pnpm-workspace.yaml cat pnpm-workspace.yaml Node package boundaries
justfile cat justfile or just -l Task runner commands (just dev-desktop, just check)
ARCHITECTURE.md head -50 ARCHITECTURE.md High-level system design
AGENTS.md grep -A 20 "Documentation" AGENTS.md Docs site structure and agent guidelines

Practical Exploration Workflow

Combine these commands into a reusable script:

#!/bin/bash

# explore-harper.sh — Quick orientation for new contributors

echo "=== Harper Repository Overview ==="
echo "Rust crates:"
find . -maxdepth 2 -name Cargo.toml -exec dirname {} \; | sed 's|^./|  |'

echo ""
echo "JS/TS packages:"
find packages -maxdepth 2 -name package.json -exec dirname {} \; | sed 's|^|  |'

echo ""
echo "Entry points:"
for main in harper-cli/src/main.rs harper-ls/src/main.rs harper-desktop/src-tauri/src/main.rs; do
    [ -f "$main" ] && echo "  $main"
done

echo ""
echo "Documentation folders:"
ls -d packages/web/src/routes/docs/*/ 2>/dev/null | head -10 | sed 's|^|  |'

Summary

  • Use git ls-tree for clean top-level directory listings without build artifacts
  • Use find with -name Cargo.toml and -name package.json to locate all project boundaries
  • Use tree -L 3 for visual hierarchies of complex components like harper-desktop/
  • Check main.rs and index.ts files to understand runtime entry points
  • Reference ARCHITECTURE.md and AGENTS.md for authoritative high-level documentation

Mastering these Bash techniques transforms Harper's substantial codebase into a navigable, searchable workspace where any file is discoverable in seconds.

Frequently Asked Questions

What makes Harper a "monorepo" rather than separate repositories?

Harper houses all components—core Rust engine, language server, desktop app, web packages, and editor plugins—in a single Git repository with unified builds. The Cargo.toml workspace and pnpm-workspace.yaml coordinate cross-package dependencies, enabling atomic commits that span multiple components and consistent versioning across releases.

How do I know whether to look in a Rust crate or a JS package for specific functionality?

Grammar checking and parsing logic reside in Rust crates under the root (files with .rs extensions). User interfaces, editor extensions, and web wrappers live in packages/ as TypeScript or Svelte code. If you're debugging lint behavior, start with harper-core/; if you're fixing a VS Code bug, check packages/vscode-plugin/.

Why does harper-desktop have both Rust and TypeScript source files?

Harper Desktop uses Tauri, a framework that pairs a Rust backend (process management, native APIs, the core engine) with a web frontend built in Svelte. The src-tauri/ directory contains Rust code, while src/ contains the Svelte UI that runs in a WebView. They communicate through Tauri's IPC bridge defined in src/lib/client.ts.

Where is the live demo website's source code?

The public documentation and interactive demo are built from packages/web/, a SvelteKit application. The WASM-powered live editor imports from packages/harper.js/, which wraps harper-wasm/ exports. Routes are configured in packages/web/vite.config.ts, with content sourced from packages/web/src/routes/docs/.

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 →