Skip to content
NAVIDIFF DOCUMENTATION

Chrome extension

bash
bun run build        # writes extension/dist
# chrome://extensions → Developer mode → Load unpacked → extension/dist

bun run build is the only step afterwards: the service worker polls GET /build-id (the built content script's mtime) and calls chrome.runtime.reload() when it changes, then the open tab refreshes itself. No clicking reload in chrome://extensions.

Same server, same session, same findings — open the app and the extension together and they stay in sync. On a PR page the extension adds bucket badges to GitHub's own file rows, collapses SKIP files, and docks a sidebar (shadow root, so no style bleed; drag its left edge to resize, double-click to reset). ⌥f pins the selected line, ⌥a asks about it. Clicking a file jumps to it — by DOM row when it's rendered, otherwise via GitHub's own diff-<sha256 of path> anchor, which also works from the Conversation tab.

All network runs in the service worker: extension-origin fetch sidesteps GitHub's connect-src CSP and one socket serves every tab. MV3 workers die after ~30s idle, so the server heartbeats every 20s to keep the socket alive, and the content script reconnects when it gets reaped anyway.

Diagnosing it

Both halves of the extension log to POST /log, which prints to the server journal — a content script's console isn't reachable from a terminal:

bash
journalctl --user -u navidiff -f    # [content] and [sw] lines land here
curl -s localhost:5177/preflight   # git / claude / database / github app

Ready to review a real change?

Open Navidiff