All skills

Use when PDF files are the primary input or output: read, compare, reconcile, extract text/tables/images, OCR scans, fill forms, split, merge, rotate, rename, compress, or convert between PDF and images. Optimized for private financial, tax, legal, and health documents on macOS.

Use this Skill: https://skilld.dev/gh/paulrberg/agent-skills/pdf

This session only. Nothing lands on disk.

referencesrecipes.md

≈1.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

PDF Recipes

Load only the branch needed for the current task. Keep every output distinct from its input and quote paths.

Inspect and extract

Start with the bundled factual profile, then inspect raw tool output only as needed:

uv run "<skill-dir>/scripts/profile.py" "input.pdf"
pdfinfo -box "input.pdf"
qpdf --check "input.pdf"
pdfimages -list "input.pdf"

Preserve reading order where possible:

pdftotext -layout "input.pdf" "output.txt"
pdftotext -f 3 -l 7 -layout "input.pdf" "pages-3-7.txt"
pdftotext -f 1 -l 1 -x 36 -y 72 -W 540 -H 648 -layout "input.pdf" "crop.txt"
pdftotext -bbox-layout "input.pdf" "layout.html"

Use bounding boxes to diagnose column interleaving or logical half-pages. Escalate to pdfplumber only when the Poppler output cannot preserve the required table structure:

uv run --with 'pdfplumber>=0.11.10,<0.12' python - "input.pdf" <<'PY'
import json
import sys

import pdfplumber

with pdfplumber.open(sys.argv[1]) as document:
    print(json.dumps([page.extract_tables() for page in document.pages], ensure_ascii=False))
PY

Treat extracted tables as candidates, not truth. Rebuild wrapped descriptions and continuations, retain page numbers, and reconcile exact row counts and totals against the PDF.

Compare documents

Extract each input independently with the same appropriate route. Compare normalized facts while retaining the original strings and page provenance. Report:

  • facts present in both documents;
  • facts unique to each document;
  • materially different values, dates, identifiers, qualifications, or footnotes;
  • pages rendered to distinguish source differences from extraction errors.

Do not infer that missing extracted text means missing source content. Inspect the relevant render or OCR coverage first.

OCR scans

Use OCR only for image-only or materially incomplete pages. The default covers English and Romanian:

ocrmypdf --output-type pdf --skip-text -l eng+ron --sidecar "ocr.txt" "input.pdf" "ocr.pdf"
qpdf --check "ocr.pdf"
pdftotext -layout "ocr.pdf" "ocr-check.txt"

Add --rotate-pages or --deskew only when profiling or rendered pages show the need. Add --clean only after accepting that image processing may alter visual evidence. Re-render affected pages after any of these options.

Render and extract images

Render pages for visual comparison:

pdftocairo -png -r 200 "input.pdf" "page"
pdftocairo -f 4 -l 4 -png -r 300 "input.pdf" "page-4"

Extract embedded images without rasterizing whole pages:

pdfimages -list "input.pdf"
pdfimages -all "input.pdf" "image"

Combine ordered images without recompressing them unnecessarily:

img2pdf "page-01.png" "page-02.jpg" --output "combined.pdf"
qpdf --check "combined.pdf"

Confirm image order, orientation, page dimensions, and representative renders.

Merge, split, and rotate

Merge in explicit order:

qpdf --empty --pages "part-1.pdf" "part-2.pdf" -- "merged.pdf"

Extract a range or retain a boundary page for context:

qpdf "input.pdf" --pages . 1-5 -- "part-1.pdf"
qpdf "input.pdf" --pages . 5-10 -- "part-2-with-boundary.pdf"

Rotate selected pages clockwise:

qpdf "input.pdf" "rotated.pdf" --rotate=+90:1,3

Check every result and inspect its first and last page:

qpdf --check "output.pdf"
pdfinfo "output.pdf"
pdftotext -f 1 -l 1 -layout "output.pdf" -

Rename a corpus

Build a complete old-to-new map before writing. Derive names from stable content such as issuer, document type, account suffix, and covered date range. Detect collisions and ambiguous documents first. Copy to the new names unless the user explicitly authorizes renaming originals, then profile both sides and compare hashes when a byte-identical copy is expected.

Compress

Try a lossless structural rewrite first:

qpdf --object-streams=generate --recompress-flate --compression-level=9 "input.pdf" "lossless.pdf"

Use Ghostscript only when a smaller lossy output is acceptable:

gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.7 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH \
  -sOutputFile="compressed.pdf" "input.pdf"

Compare byte size only after qpdf integrity, page count/dimensions, text extraction, forms/annotations where relevant, and representative renders pass. Keep the original and the smallest acceptable validated output.

Final validation

At minimum, require:

qpdf --check "output.pdf"
pdfinfo -box "output.pdf"
pdftotext -layout "output.pdf" "output.txt"

Add domain checks: exact totals and balances for statements, field values and appearances for forms, first/last pages for splits, order and dimensions for image conversions, and visual comparison for OCR or compression.

Source: SKILL.md on GitHub

No alerts5d3 checks · Risk SAFE
  • Gen Agent Trust Hub5d

    The skill provides local PDF processing capabilities on macOS using a suite of standard utilities and Python scripts. It involves the inherent risk of indirect prompt injection from untrusted document data and relies on local command execution, though the implementation follows security best practices to prevent direct command injection.

  • Socket5d

    No alerts

  • Snyk5d

    Risk: LOW · No issues

Signed by skilld at 85eb569. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last week
argument-hint
[file ...]
Other metadata
compatibility
Requires macOS, uv, Poppler, qpdf, Ghostscript, OCRmyPDF with Tesseract language data, and img2pdf.

README badge

README badge for paulrberg/agent-skills/pdf