Paw is a Chrome/Firefox extension for sending page context (url, title, selected body, surrounding note) to Emacs via org-protocol, with optional server-side features. It adds a floating action button, keyboard shortcut, single-click word capture, and auto-highlighting powered by a local server.
- Firefox & Firefox Android addons.mozilla.org/en-US/firefox/addon/emacs-paw
- Chrome Chrome Web Store
- Brave: Same as Chrome. If you use paw-server, add
@@||localhost^inCreate custom filtersatbrave://settings/shields/filters.
- Floating “+” button near selection with submenu and protocol actions
- Keyboard shortcut: modifier + key selects word at caret and sends
- Single-click mode: wrap words and send selection on click
- Auto-highlight words returned by paw-server with info bubble
- Optional site bridges (e.g., Netflix) to expose playback controls
- Floating action button with submenu and context menu based on
Protocol(s) - Keyboard shortcut (default Alt + s) to capture word under caret
- Single-click mode to wrap words and send selection to Emacs/paw-server
- Auto-highlight from
GET /wordswith info bubble (check, delete, view) - Org-protocol integration with support for
text,html, and optionalmarkdownformats - Fallback to org-protocol if
POST /pawfails - Save full page HTML via
POST /sourceand optional Wallabag save - Options page for toggles, shortcuts, offsets, Protocol(s), and server
- Popup toggles for Enable, Single-Click, Auto-Highlight, Show Button and quick protocol actions
- Netflix page bridge exposing play/pause/seek via injected script
- Clone this repo or copy the `paw` directory
- Chrome-based:
chrome://extensions→ Enable Developer Mode → Load unpacked → select this folder - Firefox:
about:debugging#/runtime/this-firefox→ Load Temporary Add-on → selectmanifest-v2.json(Firefox uses MV2 format)
Artifacts for distribution are in web-ext-artifacts/.
Open the extension Options page. Stored keys (in storage.sync):
isExtensionDisabled,isSingleClickDisabled,isAutoHighlightDisabled,isShowButtonDisabledshortcutKey,modifierKey(“None” | “Ctrl” | “Alt”)floatingButtonLeft,floatingButtonTop(pixel offsets)protocol,template,url,title,note,bodyserver(defaulthttp://localhost:5001)
Two formats are supported for Protocol(s):
[
{ "protocol": "paw", "format": "text" },
{ "protocol": "eaf-browser", "format": "text" },
{ "protocol": "capture-html", "format": "html", "deselect": true },
{ "protocol": "wallabag", "format": "text", "download": true }
]Supported keys:
| key | type | description |
|---|---|---|
| protocol | string | Emacs org-protocol name |
| format | “text” or “html” | Body format; markdown is also supported in content script |
| download | boolean | If t, upload page HTML to paw-server and include file path |
| deselect | boolean | If t, clear selection after triggering |
paw,eaf-browser
Body defaults to text.
(add-to-list 'org-protocol-protocol-alist
'("Eaf Browser"
:protocol "eaf-browser"
:function org-protocol-eaf-browse
:kill-client t))
(defun org-protocol-eaf-browse (arg)
(let ((url (plist-get arg :url)))
(eaf-open-browser url))
nil)The Python CLI emacs-paw provides a small backend (Flask) for advanced flows:
- POST
/paw: receive selection payload from the extension - GET
/words: serve highlight word list - POST
/source: receive and persist current page HTML
- Install:
pip install emacs-paw - Run server:
paw run_server --port 5001 --save-dir /tmp/paw_server_html_file.htmlIf you use paw.el, you can also
M-x paw-server. - Handle HTML file in Emacs:
(defun paw-server-org-protocol (data) (let* ((url (org-protocol-sanitize-uri (or (plist-get data :url) "")))) (message "URL: %s" url) (when (file-exists-p "/tmp/paw_server_html_file.html") ;; process the HTML file here (delete-file "/tmp/paw_server_html_file.html")) nil))
- Press the toolbar icon to open popup toggles
- Use the Options page to configure Protocol(s), server, shortcuts, offsets
- Select text on a page; use the floating “+” to trigger actions
- Use shortcut (e.g., Alt + s) to grab word under caret and send
- Enable Auto-Highlight to see known words and hover the bubble for details
- Toggle “Show Button” to hide floating button by default; it will still appear when text is selected
storage,activeTabhost_permissions:http://localhost/*(only for paw-server features)
- No data is sent anywhere unless you enable paw-server or trigger org-protocol
- When
serveris set, requests go to your configured local server - No usage analytics or third-party telemetry
- Manifests:
manifest.json(Chrome MV3),manifest-v2.json(Firefox MV2),manifest-v3.json(legacy) - Background:
background.js(service worker on Chrome MV3, persistent script on Firefox MV2) - Content:
content.js(UI, capture, highlight, server/org-protocol integration) - Popup UI:
popup.html,popup.js - Options UI:
options.html,options.js - Bridges:
netflix-bridge.js
To package for both browsers, use ./package.sh or npm run package; artifacts end up in web-ext-artifacts/.
- paw.el: Send word to Emacs and show on paw-view-note
- wallabag.el: Open/save Wallabag entries
- calibredb.el: Open ebook directly in browser