Extracts highlights, underlines, and typed notes from a folder of PDFs into a single org-mode file, automatically, whenever a file in that folder changes.
Apple Books does not reliably expose PDF annotations for export — they
live in an internal cache, not in the PDF file or its own annotation
database. This tool instead reads the PDF's own annotation objects
directly, so it works regardless of which app you used to annotate
(Preview on macOS/iOS, pdf-tools in Emacs via poppler, etc.).
pdfannots(MIT,pdfminer.six) does the actual extraction — it recovers the highlighted/underlined text from the annotation's coordinates, since plain highlights don't store their own text.pdf-highlights-to-org.pywraps it: scans a folder, keeps an incremental cache (only reprocesses changed files), writes one org file, logs every run, and sends a macOS notification at the end.- A
launchdLaunchAgent watches the folder and reruns the script on every change.
Annotation types covered: Highlight, Underline (Preview classifies
plain highlighting under this type, not Highlight), Squiggly,
StrikeOut, Text (standalone note), FreeText. Both the highlighted
text and any attached typed comment are captured separately.
pip3 install pdfannots --break-system-packages
brew install terminal-notifierpdf-highlights-to-org.pyandupdate-pdf-highlights-org.shlive in this folder — editPDF_DIRandORG_OUTin the latter to match your own setup.- Copy
com.example.pdfhighlights.plistto~/Library/LaunchAgents/, rename it, and replace everyYOUR_USERNAMEplaceholder with your actual paths (launchd plists can't use$HOME). chmod +x update-pdf-highlights-org.shlaunchctl load ~/Library/LaunchAgents/<your-renamed>.plist
Uses terminal-notifier
rather than osascript -e 'display notification': the latter is
silently dropped by macOS when invoked from a background process with
no real Script Editor in the foreground (confirmed against
~/Library/Group Containers/group.com.apple.usernoted/db2/db — such
notifications are recorded with presented=0). In System Settings →
Notifications, set terminal-notifier's alert style to Banners
(auto-dismisses but stays in Notification Center history) rather than
Alerts.
- EPUB files are out of scope (
pdfannotsonly reads PDF). - Structurally corrupted PDFs (missing
/Root, truncated files, etc.) are logged as errors and skipped, not repaired. - iCloud "placeholder" files not yet downloaded locally are not handled explicitly.
- Large/complex PDFs are capped at a 120s timeout per file.
- The generated org file is fully regenerated on every run — don't hand-edit it.
MIT for this glue code. pdfannots and terminal-notifier are
separate MIT-licensed projects, installed via pip/brew, not
vendored here.