# Rewrite with AI — Chrome Extension

Highlight text anywhere, right-click, and rewrite it with ChatGPT.

Context menu actions:
- **Summarize this**
- **Rewrite this better**
- **Rewrite this professionally**
- **Rewrite this casual**
- **Shorten this text**
- **Extend this text**

The result replaces your selection **in place** inside inputs, textareas, and
rich editors (Gmail, contenteditable, etc.). If there's **nothing editable to
replace** — e.g. you ran it on read-only text or on the whole page — the result
is shown in a **modal** with a Copy button instead.

**No selection?** Right-click anywhere and the action runs on the **whole page's
text** (great for "Summarize this"). While it works, a spinner toast shows
progress in the bottom-right.

## Inline autocomplete

While typing in any text box, you can pull a suggestion inline:

- **`///your hint///`** — wrap a hint in triple slashes to suggest the next
  sentence/paragraph based on the hint and the text before the cursor.
  e.g. `... and in conclusion ///wrap up optimistically///`
- **`////`** (four slashes) — continues the writing using the surrounding
  (before **and** after) context, no hint needed.
- **`////your instruction////`** — wrap a custom instruction in four slashes to
  run it over the surrounding text. e.g. `////translate the paragraph above to
  English////` or `////turn this into a bullet list////`

After a short pause a popup appears near the cursor — press **Tab** to insert (or
click it), **Esc** to dismiss. The trigger text is removed when the suggestion is
inserted. Toggle it on/off in the popup ("Inline autocomplete").

> Tip: autocomplete is snappiest in **API mode**. In ChatGPT-tab mode each
> suggestion drives the chatgpt.com tab, so it's slower. It's disabled on
> chatgpt.com itself.

## Two ways to reach ChatGPT

Pick the mode in the extension popup (the blue **R** icon):

| Mode | Who it's for | How it works | Trade-off |
| ---- | ------------ | ------------ | --------- |
| **API key** | Anyone with an OpenAI account / API key | Calls the official `api.openai.com` Chat Completions API | Stable & reliable. Billed to your OpenAI account. |
| **ChatGPT tab** | Anyone, no account/key needed | Drives a real **chatgpt.com** tab in your browser (logged in or logged out / "incognito" style) | Free, no key. Uses the live site, so it depends on ChatGPT's UI and your session. |

> A registered/plan user can use **either** mode. Someone without an API key can
> use **ChatGPT tab** mode.

### How ChatGPT-tab mode works

Instead of calling a private API (which Cloudflare blocks for raw requests), it
uses the **actual ChatGPT web app** through your browser session:

1. Finds an open `chatgpt.com` tab — or opens one in the background.
2. Types your prompt into the composer and sends it (`chatgpt-page.js`).
3. Watches the streamed reply until it finishes, then reads the text back.

Because it runs inside a real, Cloudflare-cleared tab, there's no proof-of-work
and no API key. If ChatGPT shows a login wall or captcha, open `chatgpt.com`,
get a chat ready, then retry.

**Two options for ChatGPT-tab mode** (in the popup):

- **Which chat — Existing vs New**
  - *Existing*: reuses your currently open chat (keeps context).
  - *New*: starts a fresh chat every time (navigates to a new conversation).
- **Chat type — Normal vs Temporary**
  - *Normal*: a regular chat, saved to your history.
  - *Temporary*: a temporary chat (`?temporary-chat=true`) that ChatGPT doesn't
    save to history — the "incognito" option.

How they combine: *New* always opens a fresh chat of the chosen type. *Existing*
+ *Temporary* reuses an already-temporary tab, or starts a temporary chat if the
open one isn't (a saved chat can't be converted to temporary). *Existing* +
*Normal* just uses the open chat as-is.

> Note: ChatGPT's DOM can change. If sending stops working, update the
> `SELECTORS` in `chatgpt-page.js`.

## Install (load unpacked)

1. Open `chrome://extensions` (or `edge://extensions`).
2. Turn on **Developer mode** (top-right toggle).
3. Click **Load unpacked** and select this folder (`C:\Users\danny\rewrite`).
4. Click the extension icon (blue **R**), pick a mode, fill in settings, **Save**.
   - API mode: paste your key from https://platform.openai.com/api-keys
   - Fetch mode: nothing to configure.

## Use

1. Select text you wrote.
2. Right-click → **Rewrite with AI** → choose a style.
3. Wait for the "Rewriting…" toast; the text is replaced automatically.

## Files

| File | Role |
| ---- | ---- |
| `manifest.json` | MV3 config, permissions, content-script registration |
| `background.js` | Context menus + routes to API or ChatGPT-tab provider |
| `chatgpt-page.js` | Runs in chatgpt.com tabs: types the prompt, waits, returns the reply |
| `content.js` | Snapshots the selection, swaps the text in place, shows toasts |
| `options.html` / `options.js` | Mode + settings UI (also the toolbar popup) |

## Troubleshooting

- **Nothing happens / no toast appears.** The page needs our content script. It's
  now injected automatically on right-click, but if you just (re)loaded the
  extension, reload the page once to be safe. Note: it can't run on restricted
  pages (`chrome://`, the Chrome Web Store, PDF viewer).
- **ChatGPT-tab mode opens a hidden window.** When no ChatGPT tab is open, one is
  created in a **minimized background window** so you don't see it (Chrome can't
  make a truly invisible tab). It's reused afterwards. If you ever need it,
  un-minimize that ChatGPT window.
- **"Couldn't type into ChatGPT's message box."** A hidden/unfocused tab can block
  programmatic typing. Open `chatgpt.com` in a normal visible tab and keep a chat
  ready, then retry — or use API mode for fully headless operation.

## Notes

- API key and settings are stored with `chrome.storage` (in your browser only).
  The key is sent solely to `api.openai.com`.
- ChatGPT-tab mode automates the live site through your own session; it is not an
  official interface and depends on ChatGPT's current UI. Respect ChatGPT's
  Terms of Service.
- To tweak the wording of each action, edit the `ACTIONS` object in
  `background.js`.
