Skip to content

Releases: jiru-labs/proofkey

v0.1.17

Choose a tag to compare

@nyakojiru nyakojiru released this 19 Oct 19:16

Rewrites keep a text that switches language from one clause to the next more often (#1).

Text that switches language clause by clause

«Je t'envoie le rapport après le standup, but I still need to review the numbers first» has no single word out of place, so the word lists of 0.1.16 named nothing useful, and the five rewording actions wrote the whole text in one language. ProofKey now splits such a text at punctuation, gives each clause a language only when its short common words leave no doubt, and names each part and its language to Improve writing, Make professional, Make friendly, Simplify and Expand as parts to keep in their language. It fires when one part is English and another is Spanish, French, German or Portuguese.

When a rewrite of such a text still comes back in only one of the two languages, the same request is sent once more and the second reply is used if it keeps both. Not at temperature 0, where the same request gives the same reply; if the second request fails, the first reply is kept. On these texts that is a second request on Expand about four times in ten, billed to your key like the first; the other four actions almost never need one.

Fixed on the way: a long text with its non-English part after the sixth clause had only English parts named, and c’est with a typographic apostrophe was not recognised where c'est was.

How it is known

tools/action-eval.ts, the five rewording actions over six clause-mixed texts (--fixtures clauses), gemini-2.5-flash through OpenRouter:

  • Naming the parts, 10 runs, 2026-10-17, against the version before: 232/300 → 272/300 checks kept both languages. Qwen3-4B on llama.cpp, temperature 0, 3 runs: 3/90 → 36/90.
  • Asking again, 10 runs, 2026-10-19, the same replies scored before and after the second request: 271/300 → 281/300, Expand 33/60 → 42/60, with 27 second requests in 300.
  • Where it fires: over 14,161 paragraphs written in one language (Debian man pages in Spanish, French, German and Portuguese, and English documentation), it named parts in 13, all of them real untranslated English.

Expand still loses the mixture in 18 of 60 checks; #1 stays open. On the released tree, npm run verify reported 688 passing checks and no failures. Details and limits are in MODELS.md.

v0.1.16

Choose a tag to compare

@nyakojiru nyakojiru released this 15 Oct 21:49

Rewrites keep borrowed words in mixed-language text more often (#1).

Mixed-language text

Improve writing, Make professional, Make friendly, Simplify and Expand used to translate the words you borrow from another language: el deadline came back as el plazo, mañana as tomorrow. ProofKey now finds those words itself and names them to the model as words to keep exactly as written:

  • English words inside Spanish, French or Portuguese text (deadline, kickoff meeting, rollback), found with an English word list (SCOWL, 1.2 MB in the package) and, per language, a mask of the English words that language does not have. The word list is read only for text in one of those three languages.
  • Spanish, French, Portuguese or German words inside English text (mañana, pero, merci), found by letters English spells without and a short hand-written list. No word list is needed.

Fix grammar, the live check, Summarize, Convert to bullet points and custom actions do not get the list: a typo that happens to be an English word (boy for Spanish voy) would be kept as written, and Fix grammar exists to fix exactly that. German as the base language is not covered: its dictionary already lists Meeting, Team and Bug. Until then, Terms never to flag (Profile) keeps any word you add.

API keys

The local copy of your keys (since 0.1.14) is now also kept when settings arriving from sync carry the mark a later release will write when it stops putting keys in sync. This prepares that step so that no computer loses its key. It changes nothing about where keys travel today.

How it is known

tools/action-eval.ts, the five rewording actions over the eight mixed-language fixtures, each time with the version before as a control:

  • gemini-2.5-flash through OpenRouter, 10 runs, 2026-10-14: 246/400 → 321/400 checks kept the mixture (the two Spanish fixtures 21/100 → 96/100).
  • The same, 2026-10-15, for the English-base direction: 311/400 → 352/400 (I told her mañana works better, pero… 3/50 → 33/50).
  • Qwen3-4B on llama.cpp, temperature 0: 66/120 → 79/120 (3 runs, 2026-10-14). The English-base change, measured over one run on 2026-10-15, made no difference: 27/40 before and after.

On text in one language with typos, the shipped rule named one misspelling that happens to be an English word (boy). On 2,532 paragraphs of English prose, the English-base rule named words in one paragraph, and they were names. On the released tree, npm run verify reported 658 passing checks and no failures. Details and limits are in MODELS.md.

v0.1.15

Choose a tag to compare

@nyakojiru nyakojiru released this 10 Oct 18:19

OpenCode Go works again.

OpenCode Go

Since about 2026-09-17, OpenCode Go refuses every request that does not carry a session header, and its gpt-* and grok-* models now answer only the OpenAI Responses API. ProofKey 0.1.14 and earlier sent neither, so a Go connection failed on every model.

ProofKey now:

  • sends the x-opencode-session header Go asks for, with a random id that lives as long as the browser session (chrome.storage.session) — no lasting identifier;
  • speaks the Responses API (POST /responses) for Go's gpt-* and grok-* models, and /chat/completions for the rest, chosen per model — an existing Go connection needs no change;
  • defaults the Go preset to gpt-6-luna: 14.0/14 on the live-check fixtures over five runs, no false alarms, 3.5 s for a 14-sentence check.

OpenCode describes Go as "designed for OpenCode and other coding agents" and says its traffic is monitored; proofreading is not coding-agent traffic, so read their terms before relying on it. The preset says so too.

How it is known

Measured on 2026-10-10 against Go's own endpoint with a real key: the errors above, then the live-check measurement of npm run eval over the Responses API (gpt-6-luna 14.0/14, gpt-5.6-luna 13.6/14, grok-4.7 14.0/14). The built extension was then run end to end against Go with tools/provider-test.mjs: every action, the live check, the explain card, a rejected key with fallback, and underline and Apply on three kinds of editor. On the released tree, npm run verify reported 627 passing checks and no failures. Details and limits in MODELS.md and COMPATIBILITY.md.

v0.1.14 — Typing over the in-browser model, measured at a human pace

Choose a tag to compare

@nyakojiru nyakojiru released this 10 Oct 15:47

Typing over the in-browser model stays smooth now, measured at a human pace, and rewrites keep quotations and words in another script.

Typing over the in-browser model, measured properly

0.1.13 stopped a live check when typing resumed. Measured again at a human pace (one key every 80 ms, a 2 s pause after each sentence) instead of in bursts, that did not hold. Each check spent 3.7 s reading ProofKey's check prompt before writing anything, a stretch the model cannot be stopped in, and the check sent again at the next pause paid it again: in Brave on an RX 6600, 33 to 121 of 462 keystrokes took over 100 ms to paint.

Live checks now continue one conversation, so the model reuses what it already read: 0.29 s to its first word instead of 3.7 s, and 0 slow keystrokes in every run after warm-up, in Brave and in Edge. The stop-on-typing is gone; it has nothing left to stop. On the 14 live-check fixtures the quality held (258/280 against 260/280 sent fresh, no false alarms either way).

The model is now also loaded, and the conversation started, when a page with live checking opens, rather than on the first sentence typed there: the warm-up run went from 93 slow keystrokes to 0 in Brave. Typing keeps the model loaded. One stutter remains: right after a quick action, if typing resumes within 2 s, about 10 keystrokes, once.

Also in this release

  • Quick actions that reword text (improve, professional, friendly, simplify, expand, bullet points, summarize, Fix grammar) keep quoted passages and words written in another script as they are, instead of translating them. A mixture in one script, such as an English noun inside Spanish, is still not solved; listing those words under Terms never to flag keeps them (#1).
  • API keys are now also copied to chrome.storage.local, the first step in keeping them out of browser sync. Nothing changes yet for you: keys still sync as before. A later release stops sending them to sync, once every computer has its local copy (PRIVACY.md).

How it is known

On the released tree, npm run verify reported 605 passing checks and no failures. The typing measurements were taken on Windows 11 in Brave 155 and Edge 154 (in-browser model) and Chrome 154 (Gemini Nano, unaffected: 0 slow keystrokes before and after), with the page and runner now in tools/typing-lab/. Translate was also run by hand on Telegram Web for the first time. Measurements and their limits are in MODELS.md and COMPATIBILITY.md.

v0.1.13 — Typing no longer stutters over the in-browser model, and three fixes from Windows

Choose a tag to compare

@nyakojiru nyakojiru released this 07 Oct 22:03

Fixes from a full test on Windows: typing no longer stutters while the in-browser model checks, underlines stay under their words in a scrolling field, and saving settings no longer undoes a site switched on meanwhile.

Typing over the in-browser model

With the model running inside the browser, typing over a live check stuttered: in Brave on an RX 6600, 177 of 361 keystrokes took over 100 ms to paint while it generated, because the model and the page share the GPU. A live check now stops when typing resumes and runs again at the next pause. Actions you ask for are never stopped. After the fix: 0 of 339 and 0 of 340 slow keystrokes, with the checks still completing.

The 2.4 GB model download also ended for good on a single network error. It now tries three more times, and if that fails it says to click Download again. The files already fetched are kept.

Fixes

  • Underlines in a textarea with a scrollbar drifted away from their words after the first wrapped line. Seen in Brave on Windows, where the scrollbar is 16 px wide.
  • A settings page opened earlier, when saved, wrote back old lists: switching live checking on in a tab, then saving a provider change, switched it off again. Save now keeps what changed meanwhile, including words added to the dictionary.
  • When Chrome's built-in model download stops reporting progress (seen at 3% in Chrome 154 on Windows), the card now notices when the model becomes available. After 2 minutes without progress it says so and suggests restarting Chrome.

Also in this release

  • After ten applied suggestions over at least two days, ProofKey asks once for a rating. Only Chrome Web Store installs ask. The count stays in local storage and is never sent (PRIVACY.md).
  • A new store summary that leads with privacy: your text goes only to the AI you pick.
  • PRIVACY.md gains a threat model, and says plainly that settings, API keys included, use chrome.storage.sync.

How it is known

On the released tree, npm run verify reported 588 passing checks and no failures: unit checks, test:render and test:ext. Each fix above has a check that failed on the old code. The stutter, the scrollbar drift, the settings overwrite and the stalled download were found and re-tested in Brave and Chrome on Windows, on 2026-10-04 and 2026-10-05. Measurements are in MODELS.md and COMPATIBILITY.md.

v0.1.12 — Fix grammar keeps your language, and the settings page says when a change is unsaved

Choose a tag to compare

@nyakojiru nyakojiru released this 04 Oct 12:26

Fix grammar no longer writes another language over your text, and the settings page says when a change is not saved.

Fix grammar keeps your language

A small model can answer text that is too broken to recognise in another language: Qwen3.5 4B in Microsoft Edge answered tis is a test, a i am cheking if it work in French on every run. Fix grammar now checks that the reply keeps the author's words. If it does not, the request is asked once more with the language rule restated. If the second reply leaves the language too, your text is left as it was and the error says why.

The check allows for the spelling a proofread fixes, so chat shorthand is corrected rather than refused: pls snd me teh fil b4 frday thx becomes Please send me the file before Friday. Thanks. Measured on Qwen3-4B (llama.cpp): it fires on 0 of 58 same-language corrections and on 38 of 44 real translations, including English into French 7 of 7. It catches a different language, not a close one: Spanish into Portuguese or Catalan into Spanish can pass. Details in MODELS.md.

Unsaved changes on the settings page

The settings page says when changes are not saved yet: a line in the footer, a dot in the tab title and the Save button. Leaving the page with unsaved changes asks the browser to confirm.

Also in this release

  • When the browser has no built-in model (Brave, Edge, or Chrome below its requirements), the message names "Run a model inside this browser" first, before LM Studio, Ollama or llama.cpp.
  • A build-time dependency (nanoid, under Vite) was updated for a security advisory. It is not in the package: every file in dist/ was byte-identical before and after.

How it is known

On the released tree, npm run verify passed 536 checks and failed none: unit checks, test:render and test:ext. The language check was run end to end on 2026-10-04: the built extension in Brave Origin 153, with a Qwen3-4B on llama.cpp that answers ola k ase, aver si qedamos el finde xfa in Portuguese. It retried once, refused, and left the text alone. Two shorthand texts were corrected on the first request. test:render checks that the refusal reaches the page as an error card and the field is unchanged. The unsaved-changes confirmation was seen in Brave Origin.

v0.1.11 — a model inside the browser, a finder for local ones, and multi-line WhatsApp messages

Choose a tag to compare

@nyakojiru nyakojiru released this 30 Sep 15:13

Two new ways to use ProofKey with no API key where the browser has no built-in model, such as Brave, and a fix for multi-line messages on WhatsApp Web.

A model inside the browser

Model in this browser (Qwen3.5 4B, no key) runs the model inside ProofKey itself, on your GPU through WebGPU (WebLLM 0.2.85 in a hidden extension page). Nothing is downloaded until you press its own button, which names the size and the host first: 2.4 GB from huggingface.co, pinned to one revision. After that, nothing you check leaves the computer. It needs WebGPU and about 4 GB of GPU memory.

It is offered live checking, Fix grammar, bullet points and Translate, the actions it measured well on. The rewrites are refused on it and say so. Measured in Brave on Windows with an AMD RX 6600: 13.0/14 on the live check over 10 runs with no false alarms, the same as Chrome's built-in model, and Fix grammar 11/12. One machine; details in MODELS.md.

This adds the offscreen permission (no install warning) and lets extension pages run WebAssembly. The model's compiled WebGPU library ships inside the package; its source repository states no licence, and the question is open at mlc-ai/binary-mlc-llm-libs#166. THIRD_PARTY_NOTICES.txt in the package says where each bundled piece comes from.

Find a model on this computer

Find a model on this computer, on the built-in model's card, looks for LM Studio, Ollama or llama.cpp on their usual ports (1234, 11434, 8080). It only looks when you click, and only on this computer. Then it adds the one it finds as your first provider. When Ollama refuses the extension, the card names the OLLAMA_ORIGINS setting that fixes it. Tested against a real llama-server; not yet against real LM Studio or Ollama.

Multi-line messages keep their line breaks

Correcting a WhatsApp Web message of several lines (typed with Shift+Enter) could join the lines into one or leave a stray word at the end. Edits are now checked against the whole field, and a multi-line reply keeps its line breaks in Lexical editors.

Also in this release

  • When the default action has no shortcut, the notice suggests a free one and says where to set it.
  • The shared language rule has an English example as well as a Spanish one. Local models had been answering English messages in Spanish on Summarize (Qwen3-4B: 2/4 kept English, now 4/4).

How it is known

On the released tree, npm run verify passed 497 checks and failed none. That covers unit checks, test:render and test:ext in Chromium. The in-browser model's test:ext checks run against a stand-in engine, because this machine has no GPU. The real WebLLM was loaded inside the built extension on a software WebGPU adapter. It was also run in Brave on Windows with a real GPU: the download reached Ready and Fix grammar worked on WhatsApp Web. That run was reported by the user, and its output text and latency were not recorded.

v0.1.10 — live checking survives a reload, and a rewrite never lands twice

Choose a tag to compare

@nyakojiru nyakojiru released this 16 Sep 18:17

Three fixes found by testing the whole extension before this release, all three already in 0.1.9, and the two changes that were waiting on main.

Live checking stays on for a site after a reload

Switching live checking on for a site from the toolbar button lasted until the page reloaded, unless the site was also listed for shortcuts. Only sites with per-action shortcuts had the script registered, so at the next load nothing ran; clicking the button to bring it back injected the script and flipped the stored switch — which still read on — to off, with "Live checking is off for this site".

Now sites with live checking on are registered too, once the browser has granted them. Save in Settings asks for them. A toolbar click that has to load the script leaves live checking on, and if the browser has not granted the site yet, the page offers Allow so it is still on after the next reload.

A rewrite the editor changed no longer lands twice

On a Lexical editor (the one WhatsApp Web and Reddit use), a whole-field rewrite could leave the document in the field twice, under a toast saying the editor would not accept the text. It took a model that ends every line with two spaces — a local Qwen3-4B did — for the editor to move the line breaks, the check to fail, and the fallback to paste on top. Those trailing spaces are now taken off a reply when your text did not have them, a write the editor took is never pasted over, and if the editor changed it the toast says to look the text over.

Error messages stay long enough to read

Every toast went after 4.5 seconds, even with the pointer on it. They now stay for about 300 ms a word, never less than 4.5 s, and hold while the pointer or focus is on them.

Also in this release

  • Brave is named when it reports Chrome's built-in model as unavailable, instead of a message that read like a hardware problem, and points at Google Chrome for the no-key setup.
  • No empty download bar under the built-in model's card when nothing is downloading.

How it is known

On the released tree: 222 unit checks, test:render 112/112 and test:ext 91/91 in Chromium, the same 112 and 91 in Microsoft Edge 153 and in Brave Origin 153; a new npm run test:provider against a real local model, 33/33 in Chromium and in Brave; Google Chrome 153 with Gemini Nano, 12/12. Each fix above has a test that fails on the old code; Settings' Save asking the browser for live-check sites is the one part with no test. Brave's new message was seen in Brave itself, on the options card and in the page toast at 1000 px and 360 px.

The built extension was also run on the public demos of Lexical, Quill, ProseMirror, Slate and Draft.js — live underline, Apply, and a whole-field Fix grammar, each re-read twice — 26/26. Those are the editor engines, not Slack, Notion or Discord.

Not yet run on real signed-in sites with this build. And measured along the way, not fixed: on local Qwen3-4B-Instruct-2507 and gemma-3-12b-it, Summarize answered English messages in Spanish; gemini-2.5-flash did not (160/160). Details in MODELS.md.

v0.1.9 — the frame offer's message gets the width

Choose a tag to compare

@nyakojiru nyakojiru released this 15 Sep 20:23

A layout fix for the toast that offers to allow a frame's origin.

The frame offer's message gets the width

On sites that put the editor in a frame from another host (iCloud Mail, Infomaniak), ProofKey shows a toast with an Allow button. Real hosts are long, and side by side with its button the message was left a word or two per line, with the host overflowing underneath. In a 360 px wide document the toast also ran off the left edge.

The button now sits on its own row, the message can break inside a host name, and the toast is capped to the viewport.

How it is known: the render test now offers a frame on a long host at 700 px and 360 px. Before the fix it failed (message 26 px of 408 px, 19 lines; toast at -48 px); after it, all 95 render checks and 77 extension checks pass. It has not been re-run on the real iCloud and Infomaniak pages, where the offer itself was verified on 0.1.7.

Also

  • COMPATIBILITY.md and the README no longer list iCloud and Infomaniak as needing a manual origin grant: the in-page offer was run on both with published 0.1.7, and a person accepted the browser's permission prompt.

v0.1.8 — start on Chrome's built-in model, with no key

Choose a tag to compare

@nyakojiru nyakojiru released this 14 Sep 06:41

A fresh install no longer needs an API key before it does anything.

Chrome's built-in model is the default when nothing is saved

Google Chrome ships an on-device model behind the Prompt API: no key, no account, and no request leaves the computer. ProofKey now uses it as a third transport, and it is the connection a new install starts on. Settings that already exist are untouched.

The options card shows the model's state and a Download model button, since Chrome only fetches the model after a click, with progress while it downloads.

While this model is active, ProofKey offers live checking and Fix grammar (plus your own actions). The other built-in actions say why they are unavailable and come back when a provider with a key is active. That split comes from measurement, on Chrome 153 and one laptop (Ryzen 7 7840U):

  • npm run eval, 10 runs inside an extension service worker at greedy sampling: 13.0/14 on every run, no false alarms.
  • tools/action-eval.ts, every action, 3 runs: Fix grammar kept mixed-language text in 21/24 checks; the rewrites absorbed borrowed words into the main language (9–18/24).
  • A fresh install of the real build in branded Chrome (tools/builtin-test.mjs, 11 checks): Fix grammar in about 5 s, an eight-sentence live check in about 9 s.

Brave Origin 153 defines LanguageModel and reports it unavailable on the same laptop, so the card does not blame the hardware. Other browsers and other hardware are untested.

Also

  • Added full stops are taken back off live-check lines, for every provider. The prompt asks models not to add a full stop to a line that ends without one, and several do it anyway (Nano, grok-4.20-0309-non-reasoning and gemini-2.5-flash-lite among those measured). A single trailing . is now removed from a correction whose original had no terminal punctuation; an added ? or !, an ellipsis, and the stop that closes an abbreviation such as "3 p.m." are kept.
  • Store title and summary now carry the words people search for. The effect is not measured yet: the baseline, taken before this release, was not on page one for any of eight queries, and the same queries get re-run once it is live.
  • Messages that did not come from ProofKey itself are ignored. Nothing outside the extension can reach it today, so this changes no behaviour now; it holds if the manifest ever allows external connections.
  • The README no longer names Ollama in its pitch, since COMPATIBILITY.md has no Ollama row; the verified local server is llama.cpp.

Full evidence, including what is still unmeasured: MODELS.md (see "Results — Chrome's built-in model") and COMPATIBILITY.md