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

> Explore the Automattic/harper project structure in Bash using find, tree, and git ls-tree. Map Rust crates, TypeScript packages, and the Tauri app directly from your terminal.

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

---

**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:

- **Cargo workspace** ([`Cargo.toml`](https://github.com/Automattic/harper/blob/main/Cargo.toml)) — manages all Rust crates
- **PNPM workspace** ([`pnpm-workspace.yaml`](https://github.com/Automattic/harper/blob/main/pnpm-workspace.yaml)) — manages all JavaScript/TypeScript packages

The root [`ARCHITECTURE.md`](https://github.com/Automattic/harper/blob/main/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

```bash
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

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

```

Each [`Cargo.toml`](https://github.com/Automattic/harper/blob/main/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`](https://github.com/Automattic/harper/blob/main/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

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

```

Harper's [`pnpm-workspace.yaml`](https://github.com/Automattic/harper/blob/main/pnpm-workspace.yaml) defines these as workspace members under `packages/`:

| Package | Purpose | Entry Point |
|---------|---------|-------------|
| [`harper.js`](https://github.com/Automattic/harper/blob/main/harper.js) | Browser/Node WASM wrapper | [`src/index.ts`](https://github.com/Automattic/harper/blob/main/src/index.ts) |
| `web` | Documentation site (SvelteKit) | `src/routes/docs/**` |
| `vscode-plugin` | VS Code extension | [`src/extension.ts`](https://github.com/Automattic/harper/blob/main/src/extension.ts) |
| `obsidian-plugin` | Obsidian editor integration | [`main.ts`](https://github.com/Automattic/harper/blob/main/main.ts) |
| `chrome-plugin` | Browser extension | [`src/background.ts`](https://github.com/Automattic/harper/blob/main/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

```bash
tree -L 3 harper-desktop

```

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

- [`src-tauri/src/main.rs`](https://github.com/Automattic/harper/blob/main/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`](https://github.com/Automattic/harper/blob/main/src/lib/client.ts) — TypeScript bridge for `addToDictionary` and other backend calls
- [`vite.config.js`](https://github.com/Automattic/harper/blob/main/vite.config.js) — Forces dev server to port 1420 (Tauri requirement)

## Finding Entry Points and Key Files

### Locate Binary Entry Points in Rust Crates

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

```

Or more specifically for the language server:

```bash
ls harper-ls/src/main.rs

```

Critical entry points to bookmark:

- [`harper-ls/src/main.rs`](https://github.com/Automattic/harper/blob/main/harper-ls/src/main.rs) — LSP server used by Neovim, VS Code, and other editors
- [`harper-cli/src/main.rs`](https://github.com/Automattic/harper/blob/main/harper-cli/src/main.rs) — CLI for quick linting and debugging
- [`harper-wasm/src/lib.rs`](https://github.com/Automattic/harper/blob/main/harper-wasm/src/lib.rs) — WASM exports powering web integrations
- [`harper-desktop/src-tauri/src/main.rs`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/src/main.rs) — Desktop application bootstrap

### Count Source Files by Language

```bash
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.

## Navigating Documentation Source Files

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

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

```

Key directories mirror the site's sidebar structure defined in [`packages/web/vite.config.ts`](https://github.com/Automattic/harper/blob/main/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`](https://github.com/Automattic/harper/blob/main/AGENTS.md) under "Core Documentation Directories."

## Essential Workspace Files to Examine

| File | Command to Inspect | Why It Matters |
|------|-------------------|--------------|
| [`Cargo.toml`](https://github.com/Automattic/harper/blob/main/Cargo.toml) | `cat Cargo.toml` | Rust workspace membership and dependencies |
| [`pnpm-workspace.yaml`](https://github.com/Automattic/harper/blob/main/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`](https://github.com/Automattic/harper/blob/main/ARCHITECTURE.md) | `head -50 ARCHITECTURE.md` | High-level system design |
| [`AGENTS.md`](https://github.com/Automattic/harper/blob/main/AGENTS.md) | `grep -A 20 "Documentation" AGENTS.md` | Docs site structure and agent guidelines |

## Practical Exploration Workflow

Combine these commands into a reusable script:

```bash
#!/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`](https://github.com/Automattic/harper/blob/main/main.rs) and [`index.ts`](https://github.com/Automattic/harper/blob/main/index.ts)** files to understand runtime entry points
- **Reference [`ARCHITECTURE.md`](https://github.com/Automattic/harper/blob/main/ARCHITECTURE.md) and [`AGENTS.md`](https://github.com/Automattic/harper/blob/main/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`](https://github.com/Automattic/harper/blob/main/Cargo.toml) workspace and [`pnpm-workspace.yaml`](https://github.com/Automattic/harper/blob/main/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`](https://github.com/Automattic/harper/blob/main/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`](https://github.com/Automattic/harper/blob/main/packages/web/vite.config.ts), with content sourced from `packages/web/src/routes/docs/`.