Skip to content

Chrome Extensions

dictionary-extension

Right-click any word on any web page, choose Define ”…” in context, and an inline floating popup appears with a definition tuned to the surrounding sentence. The point is contextual meaning — “render” in “the popup will render near the click” gets a UI-rendering definition, not the meat-rendering one.

right-click on the page
→ content.js captures click coords + target
→ background.js sees the contextMenus click
→ content.js extracts {word, surrounding sentence}
→ background.js POSTs to http://127.0.0.1:9879/define
→ dictionary-server.py shells out to ~/apps/cc/bin/claude-p
--model claude-haiku-4-5-20251001
→ JSON {definition} comes back
→ shadow-DOM popup renders near the click

The local bridge pattern matches fb-commenter/server/ and claude-code-chrome-ext/server/. Using the claude-p wrapper (not bare claude -p) is intentional — it gives the bridge usage logging, rate limiting, and OAuth refresh for free.

Chrome extensions cannot shell out. The only way to invoke claude-p from MV3 is to talk HTTP to a localhost daemon. The daemon (server/dictionary-server.py) listens on port 9879 (9876 is the chrome-log-receiver, 9877 is read-aloud, 9878 is something else on the MBP). Launchd keeps it alive.

  • extension/background.js — context menu registration + bridge fetch
  • extension/content.js — sentence extraction (Range API + caretRangeFromPoint) + shadow-DOM popup
  • extension/popup.html/js/css — toolbar popup with build tag, bridge health indicator, recent history
  • extension/logger.js — shared logger, posts to chrome-log-receiver on 9876
  • server/dictionary-server.py — HTTP bridge (stdlib http.server)
  • server/dictionary-extension-server — named launcher (Background Items label)
  • server/com.dictionary-extension.server.plist — launchd agent
Terminal window
cd ~/apps && git clone https://github.com/ojhurst/dictionary-extension.git
cp ~/apps/dictionary-extension/server/com.dictionary-extension.server.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/com.dictionary-extension.server.plist
curl -s http://127.0.0.1:9879/health # {"ok": true, ...}

Then in Chrome: chrome://extensions → Developer mode → Load unpacked → apps/dictionary-extension/extension.

Terminal window
tail -F ~/apps/cc/logs/dictionary-extension.log # content + background
tail -F ~/apps/dictionary-extension/logs/server.log # bridge

studio, mbp — both machines that have a Chrome James actually opens. The launchd plist must be loaded separately on each machine; post-push-sync.sh only syncs the git tree.