> ## Documentation Index
> Fetch the complete documentation index at: https://narrator.ami.rip/llms.txt
> Use this file to discover all available pages before exploring further.

# Browser extension

> Read GitHub pull requests and commits in plain English, inline in GitHub's own diff view.

The Narrator extension, called **Narrator for GitHub**, replaces the code rows in GitHub's diff tables with Narrator's English. It works on pull request "Files changed" pages and on commit pages, follows GitHub's split or unified setting, and can be turned on and off from GitHub's own diff settings menu.

<Frame caption="A pull request on github.com with the extension turned on. Added sentences are green, and unchanged declarations are folded into a summary line.">
  <img src="https://mintcdn.com/narrator-e87f5984/eZy1xgjCws85ObLC/images/extension-diff.png?fit=max&auto=format&n=eZy1xgjCws85ObLC&q=85&s=cda380b80fd14f3077660449ab87019c" alt="A GitHub pull request diff where the code rows have been replaced by English sentences" width="1050" height="502" data-path="images/extension-diff.png" />
</Frame>

Everything runs inside the extension. It fetches the old and new versions of each changed file from GitHub, parses them with the WASM build of the oxc parser, and narrates them inside the extension's own background code. Your code is never sent anywhere else.

## Install it

Narrator for GitHub is on its way to the Chrome Web Store, Firefox Add-ons, Edge Add-ons and the Mac App Store. Until it's listed in your browser's store, download it from the [latest GitHub release](https://github.com/SirTenzin/narrator/releases/latest) and add it yourself. It takes about a minute.

<Tabs>
  <Tab title="Chrome, Arc, Edge, Brave">
    <Steps>
      <Step title="Download it">
        Download [narrator-for-github-chromium.zip](https://github.com/SirTenzin/narrator/releases/latest/download/narrator-for-github-chromium.zip) and unzip it. Keep the folder somewhere it won't be deleted, because the browser loads the extension from it every time it starts.
      </Step>

      <Step title="Open the extensions page">
        Go to `chrome://extensions`. In Arc it's `arc://extensions`, in Edge `edge://extensions`, and in Brave `brave://extensions`.
      </Step>

      <Step title="Load it">
        Turn on **Developer mode** in the top right corner, click **Load unpacked**, and choose the folder you unzipped.
      </Step>
    </Steps>

    To update later, download the new zip, replace the folder's contents, and click the reload icon on the extension's card.
  </Tab>

  <Tab title="Firefox">
    <Steps>
      <Step title="Download it">
        Download [narrator-for-github-firefox.zip](https://github.com/SirTenzin/narrator/releases/latest/download/narrator-for-github-firefox.zip). There's no need to unzip it.
      </Step>

      <Step title="Load it">
        Go to `about:debugging#/runtime/this-firefox`, click **Load Temporary Add-on**, and choose the zip you downloaded.
      </Step>
    </Steps>

    Firefox removes add-ons loaded this way when it quits, so you'll need to load it again after a restart. That goes away once the extension is on Firefox Add-ons. Firefox 140 or newer is required.
  </Tab>

  <Tab title="Safari">
    <Steps>
      <Step title="Download it">
        Download [narrator-for-github-safari.zip](https://github.com/SirTenzin/narrator/releases/latest/download/narrator-for-github-safari.zip), unzip it, and move **Narrator.app** into your Applications folder.
      </Step>

      <Step title="Allow unsigned extensions">
        In Safari, open **Settings**, then **Advanced**, and turn on **Show features for web developers**. Then open the **Developer** tab that appears in Settings and turn on **Allow unsigned extensions**.
      </Step>

      <Step title="Open the app once">
        Right-click **Narrator.app** and choose **Open**. macOS asks for confirmation because the app isn't signed yet.
      </Step>

      <Step title="Turn it on">
        In Safari's **Settings**, open **Extensions** and tick **Narrator**.
      </Step>
    </Steps>

    Safari turns **Allow unsigned extensions** off again when it quits, so you'll need to switch it back on after a restart until the extension is on the App Store.
  </Tab>
</Tabs>

Then open any pull request's **Files changed** tab, or any commit page, on github.com. TypeScript and JavaScript files are shown in English, and other files are left alone.

<Accordion title="Build it from source instead">
  From the repository root, run `bun install` and then `bun apps/extension/build.ts`. Load `apps/extension/chrome/dist` in a Chromium browser, or `apps/extension/firefox/dist/manifest.json` as a temporary add-on in Firefox. On a Mac with Xcode, `bun run safari` in `apps/extension` builds the Safari app into `apps/extension/safari-build`.
</Accordion>

## Turn it on and off

Open GitHub's diff settings menu (the gear icon above the diff) and toggle **Narrator (English)**. The same switch is on the extension's options page. The setting is remembered per browser. When it is off, you see GitHub's normal diff.

## Add a GitHub token

Without a token, the extension can only read public repositories, and GitHub allows 60 anonymous API requests an hour. Open the extension's options page (from the extension's details in your browser, or **Options** in its menu) and paste a token under **GitHub token**. A fine-grained token with read-only **Contents** and **Pull requests** access is enough. With a token the extension can read private repositories you have access to, and the limit rises to 5,000 requests an hour.

The token is kept in the browser's extension storage and is only ever sent to `api.github.com` and `raw.githubusercontent.com`. The extension collects no data at all; the [privacy policy](/privacy) has the details.

## What you'll see

Each changed declaration is shown as a unit with its English, using the same rows as GitHub's diff: removed sentences on the left or in red, added sentences on the right or in green, and edited sentences with the changed words highlighted. Functions that moved between files or were renamed are labelled as such instead of showing up as a deletion plus an addition. See [Units and diffs](/concepts/units-and-diffs) for how that matching works.

If a file's English did not change at all, for example because the edit only touched imports, types, formatting or string contents, the extension says so and shows the code instead.

## How it stays fast

The content script on the GitHub page hands each request to the extension's background script, which does the fetching and narrating. On Chromium, narration runs in a module worker inside an offscreen document, because service workers can't load code on demand. For each pull request or commit, the extension:

1. Asks GitHub for the change and its list of files.
2. Fetches both versions of each changed TypeScript or JavaScript file from `raw.githubusercontent.com`, which doesn't count against the API limit.
3. Lists the repository's files with a single git trees API call, picks out the `package.json` files in each changed file's directory and its parents, and fetches only those. See [Dependency detection](/concepts/dependency-detection).
4. Loads the WASM parser, and then only the plugin chunks for libraries those manifests list. A change to a React app never downloads the Temporal plugin. The SQL parser is only fetched when a changed file contains something that looks like SQL.
5. Picks each plugin's major version per package, so an Effect 3 package and an Effect 4 package in the same monorepo each get the right reading.

While the background script is running, reports are kept per commit, so returning to a pull request you have already read doesn't fetch it again until it gets new commits.

## Package it for the stores

From `apps/extension`, `bun run package:chrome`, `package:edge`, `package:firefox` and `package:safari` build the extension and write upload-ready zips to `apps/extension/store/out`. The Firefox command also writes the source archive that addons.mozilla.org asks for, with build instructions, and rebuilding from that archive gives a byte-identical package. Listing copy, images and a launch checklist for each store live in `apps/extension/store`.

## Limits today

* **No plugin settings.** Plugins are chosen automatically from the repository's manifests, and there is no way yet to add your own plugins or turn one off.
* **Large pull requests.** Every changed file is fetched and narrated, so very large pull requests take longer and, without a token, can use up the anonymous rate limit.
* **TypeScript and JavaScript only.** Other languages are shown as GitHub's normal diff.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.