TuBrief
구독 채널
비디오
커뮤니티

How to Build Harper: An Offline Grammar Checker Without Data Leaks

TuBrief 편집팀
2026년 7월 25일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

English한국어Español中文العربيةहिन्दीDeutschFrançaisPortuguêsРусскийBahasa Indonesia日本語

관련 영상

Harper: The Free, Private Grammarly Alternative Built in Rust5:40

Harper: The Free, Private Grammarly Alternative Built in Rust

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

How to Build Harper: An Offline Grammar Checker Without Data Leaks

When corporate security policies block external AI tools like Grammarly, developers often find themselves in a tough spot. Leaving typos in technical documentation or code comments hurts credibility when deployed, but manually proofreading everything line by line feels like a huge waste of time.

Harper solves this problem cleanly. Developed in Rust, it is an offline-only grammar checking engine that completely blocks communication with external servers. Unlike LanguageTool, which runs on Java and consumes hundreds of megabytes of memory, Harper uses only around a dozen megabytes. Operating with sub-10ms response times, it ensures your editor won't slow down.


1. Setting Up the Development Environment and Integrating Editor LSP

harper-ls performs syntax analysis entirely within your local machine using only local CPU resources. Simply install the binary via the package manager for your operating system and register it as a standard LSP in your editor.

Package Installation

Run the command in your terminal to install the binary.

  • macOS / Linux: brew install harper
  • Rust Environment: cargo install harper-ls --locked
  • Windows: scoop install harper

Neovim and VS Code Integration

In Neovim, configure target file types and linter rules using nvim-lspconfig.

`lua
local lspconfig = require('lspconfig')

lspconfig.harper_ls.setup({
filetypes = { 'markdown', 'gitcommit', 'rust', 'go', 'typescript', 'python' },
settings = {
["harper-ls"] = {
userDictPath = "~/config/harper/user_dict.txt",
workspaceDictPath = ".harper-dictionary.txt",
linters = {
SpellCheck = true,
SpelledNumbers = false,
AnA = true,
SentenceCapitalization = false,
UnclosedQuotes = true,
WrongApostrophe = false,
LongSentences = true,
RepeatedWords = true,
Spaces = true,
CorrectNumberSuffix = true
}
}
}
})

`

When using the native LSP API in Neovim 0.11 or later, configure vim.lsp.config['harper'] and call vim.lsp.enable('harper'). For VS Code users, simply install the elijah-potter.harper extension and set "harper.path": "/usr/local/bin/harper-ls" in .vscode/settings.json.

Excluding Executable Code and Controlling Inspection Scope

Harper features a built-in Tree-sitter AST parser, allowing it to skip actual source code and selectively inspect only English text inside comment blocks. If you want to completely exclude a specific function's comments from inspection, insert an inline directive.

`javascript
// harper:ignore
function processInternalSecurityToken() {
// spellcheck:ignore
// Internal security token logic
}

`


2. Controlling False Positives with Project Custom Dictionaries

Running only the default English dictionary will flag technical terms like gRPC, OAuth2, and Prometheus as errors. Using a hierarchical dictionary structure helps quickly filter out warning noise.

4-Tier Dictionary Structure

Harper validates words across four layers.

Dictionary Layer Storage Location Purpose
Static Dictionary Embedded in harper-ls binary Read-only base English dictionary DB
User Dictionary ~/.config/harper-ls/dictionary.txt Global dictionary for personal dev environments
Workspace Dictionary Project root .harper-dictionary.txt Project-specific glossary (Git managed)
File-Local Dictionary Saved in OS data path Single-file identifier storage

Registering and Sharing Domain Terms

  1. Create a .harper-dictionary.txt file in the project root directory.
  2. Add frequently used technical terms separated by line breaks.

`text
Kubernetes
gRPC
OAuth2
OpenTelemetry
Prometheus
mTLS
Netty
Etcd

`

  1. Don't panic if a false positive warning pops up in your editor. Simply trigger Code Action (VS Code: Ctrl + ., Neovim: Code Action keybinding) to add the word directly to .harper-dictionary.txt.

As long as this file is committed to your Git repository, all team members will share the exact same word list.

Adjusting Linter Rules

Disable cumbersome rules when writing comments.

  • SentenceCapitalization: Set to false to disable forcing the first letter of comments to be capitalized.
  • LongSentences: Set to false to disable warnings for long sentences, which are common in technical docs.
  • SpellCheck and UnclosedQuotes: Keep set to true to catch spelling errors and unclosed quotes.

3. Integrating with GitHub Actions CI/CD Pipeline

Typos missed in the editor should be caught at the PR stage. Connecting harper-cli, the CLI tool, to your pipeline automatically filters out grammar errors before merging into the main branch.

Configuring the GitHub Actions Workflow

Define a job in .github/workflows/harper-lint.yml to selectively check only changed Markdown files.

`yaml
name: Technical Documentation Linting

on:
pull_request:
paths:
- 'docs/'
- '
.md'

jobs:
harper-grammar-check:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0

  - name: Install Rust Toolchain
    uses: dtolnay/rust-toolchain@stable

  - name: Cache Harper CLI Binary
    uses: actions/cache@v3
    with:
      path: ~/.cargo/bin/harper-cli
      key: ${{ runner.os }}-harper-cli-${{ hashFiles('**/Cargo.lock') }}

  - name: Install Harper CLI
    run: |
      if ! command -v harper-cli &> /dev/null; then
        cargo install harper-cli --locked
      fi

  - name: Get Changed Markdown Files
    id: changed-files
    run: |
      git fetch origin ${{ github.base_ref }}
      FILES=$(git diff --name-only --diff-filter=AM origin/${{ github.base_ref }} HEAD | grep '\.md$' || true)
      echo "files=$FILES" >> $GITHUB_OUTPUT

  - name: Run Harper Lint Check
    if: steps.changed-files.outputs.files != ''
    run: |
      ERRORS=0
      for file in ${{ steps.changed-files.outputs.files }}; do
        echo "Linting $file with Harper..."
        harper-cli lint "$file" || ERRORS=$((ERRORS+1))
      done
      
      if [ $ERRORS -gt 0 ]; then
        echo "Harper validation failed with $ERRORS error(s)."
        exit 1
      fi

`

If you commit .harper-dictionary.txt at the project root alongside your code, the CI runner will also validate against the exact same dictionary list as your editor. If you are using a static site generator (SSG) like MkDocs or Docusaurus, it is safer to configure harper-cli lint docs/ to execute right before running the build script.