| name | pdf-read-diff |
| description | Render a PDF and its `pdf read` markdown side by side, page by page, and report where the read view is wrong (reading order, field labels, tables, missing/merged content, invisible glyphs). Use when checking how faithfully the read view reproduces a PDF, or when iterating on read-view fixes across one or many PDFs. Takes a PDF path as an argument. |
pdf-read-diff
Compare what pdf read PRODUCES against what the PDF actually LOOKS like, so read-view bugs are visible and fixable. For each page it renders two PNGs at matching width — the real page and the read-view markdown — and you compare them by eye and write up the inaccuracies.
The read view's job (from CLAUDE.md): render content as what it is and make it readable top-down — items on the same visual line stay on one line, form fields are HTML controls with proper labels, images are , tables are tables, and reading order never interleaves columns. This skill finds where that breaks.
1. Render both sides
Run the bundled script with the target PDF:
bun .claude/skills/pdf-read-diff/render.ts <file.pdf>
The script is a thin wrapper over the CLI itself: pdf render for the real pages, pdf render --read --html for the read view, pdf read for the citable markdown. By default it writes to a timestamped run folder under the project's ./tmp (gitignored) — ./tmp/pdf-read-diff/<YYYY-MM-DD_HH-MM-SS>_<name>/ — so both you and the user can open the images. Pass --out <dir> to override (e.g. to group a batch under one folder). Layout inside the run folder:
actual/<name>-p<N>.png the real PDF pages (pdf render, in-process)
read/<name>-read-p<N>.png the read view (pdf render --read, headless Chrome)
read/<name>-read-p<N>.html the HTML each read image was shot from
read/read.md the full `pdf read` output
read/<name>.images/ the figures the read view references (extracted)
The read view renders images as ;
render --read extracts those files so the screenshots show the real figures.
A wrong crop, missing figure, or misplaced image is itself a finding. Address
and pdf:TYPE comments appear in the screenshots as small gray/amber chips.
It prints a manifest pairing each page's actual PNG with its read PNG. No npm
deps, no poppler. Needs Chrome (set $CHROME if not at a standard macOS app
path); --dpi <n> changes resolution (default 120). Without --pages, both
sides follow pdf read's default window (first 25 pages) — the manifest notes
any pages beyond it.
2. Compare page by page
Read read/read.md first (you'll cite its line numbers). Then, for each page, use the Read tool on actual/<name>-p<N>.png and read/<name>-read-p<N>.png (the manifest prints the exact pairs) and compare them directly. Do not skip pages — table and multi-column pages are where the worst bugs hide, and they are often not page 1.
3. What to look for
Go through these deliberately for every page:
- Reading order / interleave. Does the read view flow top-down the way a human reads the page? On multi-column or form-grid pages, watch for columns collapsed into one interleaved stream (e.g. a left rail, field labels, and a right-hand note read row-by-row across each other), a scrambled masthead, or a section label split into several bogus
# headings.
- Same line, same line. Items on one visual row in the PDF should stay together; items in different columns should NOT be glued onto one line. Flag both directions.
- Form fields. Every value-entry control (
<input type="text">, <textarea>, <select>) should be a real HTML control with an accurate, adjacent label (an aria-label and/or a label line right beside it). Flag: missing labels, wrong labels (a label from a different cell/the wrong sentence), fields dumped far from their prose, and checkboxes/radios whose choice text isn't beside them.
- Tables. Wide data tables must render as Markdown tables, not as space-separated "number soup." A cell that spans multiple rows (rowspan) must read as one contiguous block, not be split across the rows around it. Check row/column headers survive.
- Content integrity. Missing text, duplicated text, or two distinct source lines merged into one paragraph (a tell: an unrelated sentence starting mid-line). Captions, footnotes, and headings present and attached to the right thing.
- Invisible / special glyphs. White-on-white or knocked-out glyphs that vanish (e.g. a "⚠ CAUTION" badge), icon-font logos, math regions, rotated text.
- Heading classification. Real headings marked as headings; body text and rail labels NOT promoted to
#; consistent treatment of like elements.
Positioning itself is not a bug — the read view is linear by design. Judge reading order and grouping, not x/y coordinates.
4. Report the inaccuracies
Produce a Markdown report (this is the deliverable — the point is to fix these next):
- Lead with a severity table (
# | Inaccuracy | Pages | Severity), most-severe first.
- Then one section per finding: what's wrong, why it matters, the
read.md line number(s), and the fixture page. Quote the offending markdown when short.
- Call out what the read view got right too, so effort isn't wasted re-fixing it.
- Severity: Critical = unreadable/unusable or wrong data (number-soup tables, column interleave). High = misleading or lost labels/associations. Medium/Low = polish.
Batch usage
For several PDFs, run the script once per file and compare each, then either write one report per PDF or a combined report grouped by PDF. Work through them one at a time. When a fix lands, re-run the skill on the same PDF to confirm the finding cleared and nothing regressed.