Academics using Emacs on macOS often need to annotate PDF files (research papers, critical editions, book chapters) and have those annotations survive outside Emacs — on MacOs default reader or iOS readers, or simply when sharing a file with colleagues.
The standard Emacs solution is pdf-tools, which renders PDFs inside Emacs buffers and supports highlights, text notes, and margin icons. The question is: how interoperable are those annotations with other readers?
pdf-tools writes annotations into the PDF file using poppler (the underlying C library). The annotations are standard PDF annotation objects — in principle readable by any PDF reader. In practice:
- Skim reads them correctly
- Preview (macOS) does not reliably display them — this is a known rendering issue, not a pdf-tools bug
The root cause: poppler and Apple's PDFKit write annotations in subtly different ways.
Use Skim as a consolidation step. Skim uses PDFKit natively. When it opens and saves a PDF, it rewrites the annotation layer through PDFKit — producing output that is fully compatible with MacOs Preview and iOS readers.
The workflow:
- Annotate in Emacs using pdf-tools — highlights, text notes, margin icons.
All annotations are written into the PDF via poppler on
save-buffer. - Verify in Skim if needed — Skim reads poppler annotations correctly and serves as a reliable macOS control viewer.
- Consolidate via Skim when the PDF is ready for sharing or archiving — Skim rewrites the file through PDFKit, maximising compatibility.
This keeps the PDF as the single canonical store at every step. No sidecar files, no external databases, no manual export/import cycle.
- Emacs with pdf-tools installed
- Skim installed in
/Applications/ - macOS (the AppleScript step is macOS-only)
(defun my/skim-consolidate-current-pdf ()
"Save current PDF buffer via pdf-tools, then rewrite via Skim/PDFKit.
Overwrites the file in place. Makes annotations compatible with
macOS Preview and iOS PDF readers."
(interactive)
(when (eq major-mode 'pdf-view-mode)
(save-buffer)
(shell-command
(format "osascript -e 'tell application \"Skim\"
open POSIX file \"%s\"
repeat until (count documents) > 0
delay 0.5
end repeat
save document 1
close document 1
end tell'" (expand-file-name buffer-file-name)))))
;; Bind to C-c C-s in pdf-view-mode
(define-key pdf-view-mode-map (kbd "C-c C-s") #'my/skim-consolidate-current-pdf)save-bufferis the correct call to flush pdf-tools annotations to disk — pdf-tools hooks into it to write the annotation layer via poppler.- The
repeat untilloop in the AppleScript is necessary becauseopenreturns before Skim has finished loading the document. Without it,save document 1fires too early and throws anInvalid indexerror. - The file is overwritten in place (
save, notexport). No output path needed. - Skim must be installed.
- This consolidation step is optional and only needed when you want maximum
compatibility (archiving, sharing, iOS sync). For day-to-day annotation within
Emacs,
save-bufferalone is sufficient.
Ghostscript rewrites PDFs but flattens annotations into the page content stream rather than preserving them as editable annotation objects. After ghostscript, highlights and notes are no longer extractable, editable, or searchable as annotations — they become visual marks burned into the page. Skim via PDFKit preserves annotations as proper annotation objects.
This workflow was assembled through research into how pdf-tools annotations are stored and what causes compatibility failures with macOS readers. No existing published snippet or workflow combining pdf-tools + Skim for annotation consolidation was found online at the time of writing (March 2026).