Chrome Extensions
dictionary-extension
What it does
Section titled “What it does”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.
Architecture
Section titled “Architecture”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 clickThe 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.
Why a local server
Section titled “Why a local server”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 fetchextension/content.js— sentence extraction (Range API +caretRangeFromPoint) + shadow-DOM popupextension/popup.html/js/css— toolbar popup with build tag, bridge health indicator, recent historyextension/logger.js— shared logger, posts to chrome-log-receiver on 9876server/dictionary-server.py— HTTP bridge (stdlibhttp.server)server/dictionary-extension-server— named launcher (Background Items label)server/com.dictionary-extension.server.plist— launchd agent
Installing
Section titled “Installing”cd ~/apps && git clone https://github.com/ojhurst/dictionary-extension.gitcp ~/apps/dictionary-extension/server/com.dictionary-extension.server.plist ~/Library/LaunchAgents/launchctl load -w ~/Library/LaunchAgents/com.dictionary-extension.server.plistcurl -s http://127.0.0.1:9879/health # {"ok": true, ...}Then in Chrome: chrome://extensions → Developer mode → Load unpacked → apps/dictionary-extension/extension.
tail -F ~/apps/cc/logs/dictionary-extension.log # content + backgroundtail -F ~/apps/dictionary-extension/logs/server.log # bridgestudio, 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.