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:
- Cargo workspace (
Cargo.toml) — manages all Rust crates - PNPM workspace (
pnpm-workspace.yaml) — manages all JavaScript/TypeScript packages
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 componentharper-cli/— command-line interface atsrc/main.rsharper-ls/— Language Server Protocol implementationharper-wasm/— WebAssembly build targeting browsersharper-comments/— comment parsers for code-aware lintingharper-brill/— Part-of-speech tagging modelharper-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 highlightersrc/routes/+page.svelte— Svelte UI with editor and settings tabssrc/lib/client.ts— TypeScript bridge foraddToDictionaryand other backend callsvite.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:
harper-ls/src/main.rs— LSP server used by Neovim, VS Code, and other editorsharper-cli/src/main.rs— CLI for quick linting and debuggingharper-wasm/src/lib.rs— WASM exports powering web integrationsharper-desktop/src-tauri/src/main.rs— Desktop application bootstrap
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.
Navigating Documentation Source Files
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 modelweir/— rule language referencerules/— generated rule catalogintegrations/— editor plugin guidesharperjs/— JavaScript SDK documentationcontributors/— 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-treefor clean top-level directory listings without build artifacts - Use
findwith-name Cargo.tomland-name package.jsonto locate all project boundaries - Use
tree -L 3for visual hierarchies of complex components likeharper-desktop/ - Check
main.rsandindex.tsfiles to understand runtime entry points - Reference
ARCHITECTURE.mdandAGENTS.mdfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →