Skip to main content

Chrome extension

A side panel that does the two things the desktop app does. Check asks whether a piece of text reads as machine-written. Rewrite puts it back in your voice. One text box feeds both, because the sequence people actually run is "is this obviously AI? … then fix it".

On Gmail and LinkedIn it can also read the composer you are already typing in and write the result back.

Install​

npm run extension:build

Then in chrome://extensions: turn on Developer mode, Load unpacked, choose the extension/ directory. The toolbar icon opens the panel.

Set up​

Checking needs nothing — no key, no account. Open the panel and paste.

Rewriting needs an account. Press Sign in to rewrite in the panel — or just press Rewrite — and rewr.it opens in a tab to approve this browser. Approve it, and the rewrite you asked for runs. The key is created for you, stored on this device only, and listed on rewr.it/account as "rewr.it for Chrome", which is where you revoke it.

Options has the same Sign in with rewr.it, and shows which plan you are on and what is left of it. It also keeps two things for developers:

  • API base URL — https://rewr.it, or http://localhost:3000 against a dev server.
  • Use an API key instead — paste an hn_ key you already made.

Sign out forgets the key in this browser. The key itself still works until you revoke it on your account page.

Check​

Type or paste, and the reading appears above the box: a percentage, a band, and the count of machine tells behind it. Open the list underneath to see what it found and why.

Nothing is sent. analyze() and likelihoodFor() run in the panel — the same code the /detect page runs, in your browser rather than on a server. It works with the network off. That is also why there is no daily limit here: there is no record to make.

The number is a mapping, not a measurement. It says how machine-shaped the text reads, never who wrote it.

Rewrite​

Press the button and the panel crosses to the rewrite, streaming. When it lands you get:

  • The score shift — Machine tells 47 → 6, from the same scorer the Check tab uses. It says so when a rewrite came out worse.
  • A fact check — names, numbers and dates that went missing or appeared. It never blocks the rewrite; it is a regex heuristic and it says so.
  • Insert, Copy, Try another, and Undo for thirty seconds after an insert.

One line under the button says what the rewrite is about to assume: what kind of writing this is, and whose voice it comes back in. The first is a guess from the site you are on and you can change it. The second is set on the website — the panel reports it rather than re-offering it.

On an AI chat site the line says "This looks like AI output" and deliberately does not guess where the draft is going, because the page cannot know.

Gmail and LinkedIn​

Grab from page reads the open composer, or your selection. Insert writes the rewrite back — replacing the selection if that is what you grabbed. Undo restores what was there, for thirty seconds.

There is also a Rewrite button in the composer's own toolbar, a right-click menu item on a selection, and Cmd/Ctrl+Shift+R in the page.

What it stores​

The API base and your key, on this device. Nothing else — no drafts, no rewrites, no history. See what is stored.

Packaging a release​

npm run extension:package

Builds a store-clean copy into extension/store-build/ and zips it. The store build differs from the dev build in exactly three ways: it drops the localhost host permission, pins minimum_chrome_version to 114 (the floor for the side panel API), and carries the key that fixes the extension's id.

That id comes from npm run extension:key, run once. It must exist before publishing, because of CORS.

CORS​

An extension's origin is chrome-extension://<id>.

  • Against loopback (localhost, 127.0.0.1, ::1), any chrome-extension:// origin is allowed. Nothing to configure for local dev.
  • Against production, the id must be listed in HUMANIZER_EXTENSION_IDS on the server. There is no wildcard.

If rewrites work locally and fail against production, this is why — and it is why the id is pinned with a key rather than discovered after upload. An extension whose id nobody listed cannot talk to the API at all.