Skip to content
jiru-labsPublic

About

Private, open-source Grammarly alternative for Chrome: your text goes only to the AI you choose — your own API key, a local model, or Chrome's built-in one. No backend, no account, no telemetry.

Topics

Resources

Contributing

Stars

6 stars

Watchers

0 watching

Forks

Repository files navigation

ProofKey

Chrome Web Store Version License

A Grammarly-style writing assistant for Chrome that talks to your LLM, using your API key — or, in Google Chrome, to the model Chrome already keeps on your computer, with no key at all.

No backend, no account, no telemetry. Your text goes from your browser straight to the provider you picked, and nowhere else.

Typing a draft, the underlines appearing, one fix applied from the card, then the shortcut fixing the rest

Recorded against the shipped content script with canned corrections, so no key was involved. On a real site the suggestions come from the model you configured.

Install from the Chrome Web Store — or build it from source if you would rather read the code first.

New here? In Google Chrome it works as installed: Chrome's built-in model checks your writing on your own computer — free, no account, one download. For every action rather than two, start with Gemini: about two minutes to a key, and ordinary use usually costs nothing.

What is actually known to work is a much shorter list than what is built. The table below is the whole of it — reports are the fastest way to grow it.


Where it works today

Everything here was run by hand, in a real browser, against a real key. Everything else is either covered by automated tests or by nothing at all, and COMPATIBILITY.md marks every row with the evidence behind it.

Sites

Site Status
Gmail · Telegram Web · Outlook / Hotmail · Tuta · X / Twitter · Reddit Verified — 2026-08-02 to 2026-09-02
Infomaniak Mail · iCloud Mail Verified — 2026-09-14, published build; the editor sits inside a cross-origin frame, so ProofKey offers that one extra origin when the cursor lands there: Allow in its toast, then the browser's own prompt
WhatsApp Web Verified — 2026-09-10, published build, live checking and quick actions; the 2026-09-04 "Broken" reading was taken with the site switched off
Slack · Notion · Discord · LinkedIn · GitHub Untested — same code path as a verified one, but nobody has run it
Google Docs Not supported — text is painted to a canvas, so there is nothing to underline

Providers

Provider Status
Google Gemini · xAI (Grok) · OpenRouter · OpenCode Go · llama.cpp (self-hosted) Verified against real keys
Chrome's built-in model (Gemini Nano, no key) Verified — 2026-09-13, Chrome 153 on one laptop, through the real service worker. Live checking and Fix grammar only; why
The other 31 presets Prefilled, not confirmed — the base URL is filled in for you, that is all it means

Untested does not mean broken: most of these share a code path with something verified. It means nobody has checked, and this project would rather say so.

Why

Grammarly and LanguageTool are excellent, and both route your writing through their servers. ProofKey keeps the interaction model — inline underlines, a suggestion card, quick rewrite actions — and swaps the engine for an endpoint you control. Point it at a model running on your own machine and nothing leaves it at all.

Features

  • Quick actions on any selected text, from the right-click menu or Ctrl+Shift+K: fix grammar, improve writing, make professional, make friendly, simplify, summarize, expand, convert to bullet points, and translate. Translate uses the first language your profile names — its own field, then the one you asked for explanations in, then your first language — so it usually works without being configured, and says which setting is missing rather than guessing when none of them is set.
  • Editable prompts. Every built-in action is a prompt you can rewrite, and you can add your own.
  • A key per action. Any action, including one you wrote, can be given its own shortcut in the options page — press the combination, and it is recorded. These are handled inside the page rather than by Chrome's shortcut system, which is limited to four keys fixed at build time and can only be changed from chrome://extensions/shortcuts. The trade is that ProofKey has to be loaded in a page to see a keypress there, so these keys run on the sites you list and nowhere else. The right-click menu works everywhere with no site permission, and Ctrl+Shift+K does too — when Chrome actually assigned it.
  • Live checking is quieter than the quick actions, on purpose. It fires on a pause you did not ask for, so it treats messaging conventions as valid: no full stop added to a line that lacks one, no capitalising a lowercase sentence start, no expanding slang. Ctrl+Shift+K you pressed deliberately, so it completes the correction, capitals included.
  • Chrome's built-in model, with nothing to set up. In Google Chrome the first connection is Chrome's own on-device model: no key, no account, and ProofKey sends your text nowhere — Chrome runs the check on the computer. It is smaller than the cloud models, so ProofKey offers it live checking and Fix grammar only — the two it measured well on.
  • 36 provider presets over two transports, plus a free-form Custom option for any OpenAI-compatible endpoint. Prefilled is not the same as confirmed — five have been used against a real key so far, see COMPATIBILITY.md.
  • Fallback chain. Put a local model first and a cloud key second; ProofKey moves down the list when one fails, and tells you which one failed.
  • Mixed-language text: measured, and it only partly holds. The interface is English; the text doesn't have to be, and the prompts are written to detect the language and work inside it — including a single message that mixes two, which rule-based checkers cannot handle at all. The rule forbidding translation has been in the prompt since v0.1.0. On gemini-2.5-flash, re-measured on 2026-10-03 over eight mixed fixtures (tools/action-eval.ts, 10 runs): Fix grammar keeps the mixture in 69 of 80 checks, Summarize 70 and Convert to bullet points 71 — the misses are almost all a Japanese sentence whose English cancel comes back as the katakana loanword キャンセル, plus an occasional team → equipo. The five rewrites do worse: Improve writing, Make professional, Make friendly, Simplify and Expand translate borrowed words in 21 to 51 of 80 checks (el deadline → el plazo), and two reworded rules tried on 2026-10-03 did not fix it (#1). Earlier versions of this line said 160/160 and 80/80: those runs could not see the Japanese fixture fail, a scoring bug fixed the same day. Measured on that one model; the other models are in MODELS.md.
  • Doesn't flatten your voice — as an instruction, not yet as a measurement. Regional variety (en-GB/en-US, pt-BR/pt-PT, zh-Hans/zh-Hant) and politeness register (tú/usted, du/Sie, tu/vous, Japanese registers) are written into every action's prompt as choices to preserve, not errors to normalise. That's asserted, not tested: tools/action-eval.ts scores whether mixed-language words survive, not whether register does, and a run of its informal-register fixture caught fix-grammar flattening "porfa" to "Por favor" anyway. Read this bullet as what the prompts say, not as a number.

Install

Get it from the Chrome Web Store. Settings opens by itself. In Google Chrome it already has Chrome's built-in model selected — click Download model once and you are done. In any other browser, set up a provider; if you have never used an LLM API before, start here.

Install from source

git clone https://github.com/jiru-labs/proofkey.git
cd proofkey
npm install
npm run build

Then:

  1. Open chrome://extensions
  2. Turn on Developer mode (top right)
  3. Click Load unpacked and select the dist/ folder
  4. Click the ProofKey icon → Settings, and configure a provider

npm run dev rebuilds on change; press the reload button on the extension card in chrome://extensions to pick changes up.

Configuring a provider

Every provider needs the same three things: a base URL, an API key, and a model. Picking a preset fills in the base URL for you; Fetch models lists what your key can actually reach.

No API key at all: Chrome's built-in model

Google Chrome ships a small language model of its own (Gemini Nano) and lets extensions use it through its Prompt API. ProofKey selects it for you on a fresh install, so there is nothing to sign up for:

  1. Open ProofKey Settings — it opens by itself after installing.
  2. On the Chrome built-in AI card, click Download model. Chrome fetches it once from Google — 4.0 GB when it was measured here.
  3. When the card says Ready, reload any tab you already had open.

What you get, and what you do not:

  • Private by construction. Every check runs on your computer. ProofKey makes no request, and no provider sees your text; what Chrome itself logs is Chrome's policy, not ours.

  • Live checking and Fix grammar, and nothing else. Measured inside an extension service worker, where ProofKey runs it, it scored 13.0/14 on npm run eval — the same on all ten runs — with no false alarms, and Fix grammar kept mixed-language text intact in 21 of 24 checks (an upper bound: scored before 2026-10-03, when one of the eight fixtures could not fail). The other rewrites did not: asked to improve or reword a message that mixes languages, it translated the borrowed words, and Translate obeyed an instruction hidden in the text. So those actions stay out of the menu while this model is active and come back the moment a provider with a key is. The numbers are in MODELS.md.

  • Slower than a cloud model. In three runs through the real extension, an eight-sentence live check took 8.6–8.8s and a Fix grammar 4.8–4.9s on a laptop with integrated graphics; Gemini answers the eval's larger request in about 1s.

  • Google Chrome on a desktop, and a capable one. Which browsers have it, as measured:

    Browser Built-in model How it is known
    Google Chrome 153 (desktop) Works 2026-09-13: the real extension, freshly installed, 11 checks through its service worker
    Brave, on Linux and Windows Not available — Brave switches the feature off Linux 2026-09-13, on the laptop where Chrome runs it; Windows 2026-09-26 on an 8 GB GPU, where the console says The feature flag gating model execution was disabled
    Microsoft Edge 153 (Linux) Not available — no such model 2026-09-15: LanguageModel is undefined
    Microsoft Edge Canary/Dev (Windows, macOS; behind a flag) Untested — a different model (Phi-4-mini, or the prerelease Aion-1.0-Instruct from Edge 150) Microsoft's Prompt API page, updated 2026-09-02, still calls it an experimental developer preview in those two channels only; ProofKey has not been measured on it
    Vivaldi, Opera, others Untested Nobody has loaded it there

    In every browser without it there are two no-key routes, both in the store release since 0.1.11. A model inside the browser: ProofKey runs Qwen3.5 4B itself, on your GPU through WebGPU — measured in Brave on an 8 GB GPU at 13.0/14 on the live check and Fix grammar level with Chrome's model (MODELS.md); one 2.4 GB download from huggingface.co, started only by its own button, then nothing leaves. It is offered live checking, Fix grammar, bullet points and Translate. Or use a provider with a key, or a model on your own computer. For the second, start LM Studio, Ollama or llama.cpp with a model loaded, then click Find a model on this computer on the built-in model's card: ProofKey checks their usual ports (1234, 11434, 8080) — only when you click, and only on this computer — and adds the one it finds as your first provider. Of the three, llama.cpp is the one measured with ProofKey (Qwen3-4B-Instruct-2507, 11.0/14 on the live check against 13.0 for Chrome's model, see MODELS.md); Ollama needs OLLAMA_ORIGINS="chrome-extension://*", and ProofKey says so when it finds an Ollama refusing it. Details and the full record are in COMPATIBILITY.md. Chrome itself wants 22 GB of free disk and either a GPU with more than 4 GB of memory or 16 GB of RAM with 4 cores — its own requirements, not a ProofKey measurement. Where it cannot run, the card says so and the first request tells you to add a provider.

  • Five languages, officially. Chrome documents English, Spanish, German, French and Japanese for this model. Others are untested.

Measured on one machine so far — Chrome 153, a Ryzen 7840U laptop — so read the latency figures as that machine's.

No API key yet? Start with Gemini

"Bring your own key" is the whole point of ProofKey, but it does mean there is a step before anything works. If you have never done it, this is the shortest path — about two minutes, and for ordinary use Google's free allowance usually covers it.

  1. Open Google AI Studio and sign in with any Google account.
  2. Click Create API key, and accept the terms if you are asked.
  3. Copy the key. It starts with AIza.
  4. In Chrome, click the ProofKey icon → Settings.
  5. Choose Google Gemini from the provider list — the base URL fills itself in.
  6. Paste your key into API key, click Fetch models, and pick gemini-2.5-flash.
  7. Save, then reload any tab you already had open.

Two things are worth understanding before you paste anything sensitive:

  • The free tier is the one tier where the provider may keep what you send. Google's free-tier data handling differs from paid: text sent on a free key may be used to improve their products. ProofKey itself never sees your writing, and that does not change — but "no telemetry" is a promise about ProofKey, not about the provider you point it at. For anything confidential, use a paid key or a local model, where nothing leaves your machine. Google's API terms are the authority on this, not us.
  • If underlines quietly stop appearing, you have hit the free limit. Live checking sends a request each time you pause typing, which a daily cap notices. It is pinned to one connection and does not fall through the fallback chain, so it goes silent rather than reporting an error. Switch live checking off in Settings and the quick actions (Ctrl+Shift+K, right-click menu) carry on working. Your current limits are shown in AI Studio; they vary by account, so this page quotes no numbers.

Once that works, MODELS.md covers what to move to and what it costs. We deliberately publish no quality scores for free tiers on any provider — why.

The ones most people want

Provider Base URL Key from
OpenAI https://api.openai.com/v1 platform.openai.com/api-keys
Anthropic https://api.anthropic.com/v1 console.anthropic.com
OpenRouter https://openrouter.ai/api/v1 openrouter.ai/keys
Groq https://api.groq.com/openai/v1 console.groq.com/keys
OpenCode Go https://opencode.ai/zen/go/v1 your OpenCode account
Ollama (local) http://localhost:11434/v1 not needed
LM Studio (local) http://127.0.0.1:1234/v1 not needed
Custom whatever you paste depends
All 36 provider presets, plus Custom

OpenAI · Anthropic · OpenRouter · Groq · Ollama · LM Studio · OpenCode Go · OpenCode Zen · Google Gemini · DeepSeek · Mistral · xAI (Grok) · Together AI · Fireworks AI · Cerebras · Novita AI · NVIDIA NIM · Z.ai (GLM) · Moonshot (Kimi) · Moonshot China · Qwen Cloud (DashScope) · Alibaba Coding Plan · Hugging Face · Vercel AI Gateway · Kilo Code · StepFun · Arcee AI · GMI Cloud · Xiaomi MiMo · Tencent TokenHub · Ollama Cloud · Azure OpenAI · Azure AI Foundry · MiniMax (+ China) · vLLM / llama.cpp · Custom

Local models

Ollama refuses cross-origin requests by default. Start it so it accepts the extension:

OLLAMA_ORIGINS="chrome-extension://*" ollama serve

LM Studio: start the local server from the Developer tab, then hit Fetch models.

Small local models are less careful about language in rewrites. Measured 2026-09-16 on llama.cpp: Summarize answered English messages in Spanish on both Qwen3-4B-Instruct-2507 and gemma-3-12b-it (two English test messages out of two, on each), where gemini-2.5-flash kept the language 160 times out of 160 across every rewrite. Check a summary before you use it; the numbers are in MODELS.md.

Anything not on the list

Use Custom. Paste the base URL up to and including /v1 — ProofKey appends /chat/completions. If the endpoint has quirks, the connection editor exposes escape hatches for them: extra headers, extra body fields, extra query parameters, and the auth style (Bearer, x-api-key, a custom header name, or a URL parameter). Between those, most gateways and proxies work without code changes.

Ctrl+Shift+K does nothing

Check chrome://extensions/shortcuts first. The key is a suggestion, and Chrome hands those out first-come-first-served: if another extension already held the combination when ProofKey was installed, Chrome leaves ProofKey's slot empty and says nothing about it. Nothing is wrong with your settings, and a clean install from the Web Store is exactly the case where you would never think to look — the shortcut simply never existed. Assign one there; it cannot be set from ProofKey's own options page, which is a Chrome restriction.

Until you do, the right-click menu runs every action, so nothing is unreachable.

The symptom is worth knowing because it does not look like a missing shortcut. The keypress falls through to the page, and the page is free to act on it: on WhatsApp Web, Ctrl+Shift+K inserts an empty monospace block, so the text comes back unchanged with `````` appended and it reads as ProofKey having mangled the field. If the right-click menu corrects the same text correctly, the binding is the problem, not the model or the site. ProofKey's options page now warns when the command is unbound, under Actions.

Does it work where you need it?

Honestly: probably, but nobody has checked. ProofKey has to survive two things it doesn't control — the editor you're typing into and the provider you point it at — and neither can be covered exhaustively by one person.

COMPATIBILITY.md tracks both, and separates an automated test asserts this from a maintainer ran it from a user reported it from nobody has tried. Today that is nine sites and five providers confirmed by a human; almost everything else is untested. A row only moves when there's a link to point at.

Which makes the most useful contribution right now a one-minute report:

Reports that it worked matter as much as bug reports. Nothing else moves a row out of Untested.

Privacy

  • Your key and settings live in chrome.storage.sync. There is no ProofKey server to send them to.
  • Requests go directly from your browser to the provider's endpoint. With Chrome's built-in model there is no request at all: the check runs on your computer.
  • No analytics, no error reporting, no remote logging.
  • The extension declares no host permissions up front. It asks for access to a specific API origin when you save a connection, and for access to a site only when you switch on inline checking there.

One honest caveat: chrome.storage.sync means Chrome syncs your settings — including the API key — across devices signed into the same Google profile, encrypted in transit and at rest by Chrome. If you would rather it never left the machine, that is a storage.local change and a setting worth opening an issue for.

On cost

Live checking spends your key. ProofKey is built to keep that small: it checks about a second after you stop typing rather than on every keystroke, sends only sentences whose text changed, holds back the sentence your cursor is inside until you have stopped at the end of it for about three seconds, and caches results per sentence. Inline checking is off by default and is enabled per site.

That hold-back used to be permanent, which quietly meant a one-sentence message — a tweet, a chat line — was never checked at all, and the badge showed a green tick for text nothing had looked at. The tick now means a verdict on text that was actually sent; grey means not checked yet.

Which model you pick matters more than any of that — the cost spread across current Gemini models is about 20×, and the fastest one measured is also nearly the cheapest. Across providers the spread is wider still: the same live check costs $0.02 per 1,000 on the cheapest model measured through OpenRouter, $0.14 on Gemini and $1.50 on Grok, and takes 0.3s against 1s against 1.6–22s — while OpenCode Go's coding models are flat-rate but run 4s to 100s, past ProofKey's own request timeout at the slow end. MODELS.md has the arithmetic, worked out from ProofKey's real prompt sizes, plus measured quality and latency for forty model configurations. Free tiers are deliberately not measured on any provider, and models whose thinking cannot be turned off are excluded from live checking where that measurably costs you latency, money or a usable reply — by measured harm, not by mechanism, so the fastest model on the page stays recommended despite thinking. npm run cost recalculates it; npm run eval measures a model you are considering.

Permissions

Permission Why
storage Save your settings and connections
contextMenus The right-click menu
activeTab + scripting Inject the assistant into the tab you're using, on demand
optional_host_permissions Requested per origin — for your API endpoint, for sites where you enable inline checking, and for sites where you enable per-action shortcuts

There is no static content_scripts block, so ProofKey does not run on pages you have not turned it on for.

Two features need ProofKey loaded in a page before you act, rather than after: per-action shortcuts, because a key pressed in a page it is not in cannot reach it, and live checking, because nothing can be underlined in a page nothing loaded it into. So for each origin you list under Shortcuts run on or live checking's Enabled on, and only those, it asks for access when you save and registers its content script there. Turning live checking on from the toolbar button works on the page at once; if the browser has not granted that site yet, the page offers Allow so it is still on after a reload. Revoking access from chrome://extensions unregisters it; ProofKey re-checks on every permission change rather than assuming the grant it was given still holds.

Up to 0.1.9 only shortcut origins were registered, so live checking switched on for a site that was not also listed for shortcuts did not come back after the page reloaded, and the toolbar click meant to bring it back turned it off instead.

Development

npm run build       # production build into dist/
npm run dev         # rebuild on change
npm run typecheck   # tsc --noEmit
npm run verify      # typecheck, build, and the browser tests (needs `npm run serve` alongside)

CONTRIBUTING.md covers what each test actually asserts, and the workflow for fixing a bug — reproduce it in tools/harness.html first, and confirm the new test fails before the fix. Two tests here passed while asserting nothing until that check was applied.

Stack: TypeScript, Vite 8, Manifest V3, no UI framework. The options page and the in-page card are plain DOM; the in-page UI lives in a shadow root so host-page CSS cannot reach it.

src/
├─ core/
│  ├─ types.ts       settings and suggestion shapes
│  ├─ presets.ts     the provider registry
│  ├─ prompts.ts     built-in action prompts
│  ├─ browser.ts     extension-API capability detection
│  ├─ storage.ts     settings load/save and merging
│  ├─ shortcuts.ts   chord parsing, matching and labelling
│  └─ providers/     two transports: chat_completions, anthropic_messages
├─ background/       service worker: menus, shortcuts, injection
├─ content/          inline assistant
└─ options/          settings page

Adding a provider

If it speaks POST /v1/chat/completions or Anthropic's POST /v1/messages, it is one row in src/core/presets.ts — no adapter code:

openaiCompatible('acme', 'Acme AI', 'https://api.acme.com/v1'),

Prior art

  • Hermes Agent (Apache-2.0) — the provider model here follows its api_mode abstraction and named-provider design. Base URLs are taken from its PROVIDER_REGISTRY rather than guessed.
  • chatGPTBox (MIT) — selection-triggered UI and per-site adapters.
  • WritingTools (GPL-3.0) — action-set design. Referenced for ideas only; no code from it is used, as GPL-3.0 is incompatible with this project's MIT license.
  • Grammarly and LanguageTool — the interaction model this imitates.

License

MIT — see LICENSE. Fork it, ship it, sell it; the code is yours to use.

The MIT grant covers the code. ProofKey and the ProofKey logo are trademarks of Jiru Labs, and a fork needs its own name — that is the only thing being kept back, and it is what stops a copy of this extension being uploaded under this name with a key logger in it.

About

Private, open-source Grammarly alternative for Chrome: your text goes only to the AI you choose — your own API key, a local model, or Chrome's built-in one. No backend, no account, no telemetry.

Topics

Resources

Contributing

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages