--- name: pdf-ocr-audit description: > Audit PDF files to determine whether OCR (optical character recognition) is needed to make them fully text-searchable. Use this skill whenever the user asks about PDF searchability, OCR status, whether PDFs have embedded text, which PDFs are scans, or wants to audit/inventory a folder of PDFs for text extraction readiness. Also triggers for: "which PDFs need OCR", "are my PDFs searchable", "do these PDFs have text layers", "audit my PDFs", "find scanned PDFs". --- # PDF OCR Audit Skill Determine whether each PDF in a directory (or list of files) has an embedded text layer, and report which ones need OCR to become fully searchable. ## How it works A PDF is "searchable" when its pages contain embedded text objects. A scanned or photographically captured PDF has only image data — text must be extracted via OCR before it can be searched or indexed. Some PDFs are mixed: most pages are digital text but one or two pages (e.g., a cover page with a logo image) have no text. The primary method is to read each page's text layer using `pypdf`. If a page yields non-empty text when extracted, it has an embedded text layer. Pages that yield only whitespace or empty strings are image-only and need OCR. ## OCR verdict logic - **No** — All pages have embedded text. The file is fully searchable as-is. - **Yes** — No pages have embedded text. The file is an image scan and needs OCR throughout. - **Partial** — Some pages have text, some don't. Usually cover/back pages with logos or letterheads. Technically searchable for the text pages, but the image-only pages won't be indexed. Whether OCR is worth it depends on what's on those pages. - **Inaccessible** — The file could not be read (I/O error, corrupted, cloud-only file not locally synced, password-protected). Note the error; do not guess. ## Steps 1. **Identify the target scope.** The user may name a folder, a set of folders, or individual files. Use `find` or `Glob` to enumerate all `.pdf` files (case-insensitive). Note the total count upfront. 2. **Run the analysis script.** Use `scripts/check_ocr.py` (see below). It outputs one CSV line per file: `path,total_pages,text_pages,verdict,notes`. For large folders (>200 files), run with `--timeout` to skip slow/unresponsive files. 3. **Present results as a table.** Columns: Full Path | OCR Needed? | Rationale. The rationale should be human-readable (e.g., "3/3 pages have embedded text — digitally created", "0/2 pages have text — image scan", "1/4 pages lack text — likely cover/logo pages"). 4. **Summarize** counts by verdict at the top or bottom: N files total, N need OCR, N partial, N inaccessible. 5. **Note inaccessible files separately** with their error reason. Common causes: OneDrive cloud-only files not synced locally (EINVAL/EIO), password-protected PDFs, corrupted files. ## Using the script ```bash pip install pypdf --break-system-packages -q python scripts/check_ocr.py /path/to/folder # or for specific files: python scripts/check_ocr.py file1.pdf file2.pdf # with timeout per file (seconds): python scripts/check_ocr.py /path/to/folder --timeout 10 ``` The script prints CSV to stdout. Redirect to a file for large runs: ```bash python scripts/check_ocr.py /path/to/folder > /tmp/ocr_audit.csv ``` ## Large folder strategy If a folder has >500 PDFs, warn the user that a full run may take a while and offer: - Run only a representative sample (e.g., one per subfolder) - Categorize by filename pattern first (files named "Scan", "scan_", "QuickScan", iOS scanner naming like `YYYYMMDD_*_iOS.pdf`, etc. are almost always already-OCR'd or image scans) - Run the full audit as a background job ## Filename heuristics (supplemental, not definitive) These patterns strongly suggest the OCR verdict but must be confirmed by text layer inspection: | Pattern | Likely verdict | Reason | |---------|---------------|--------| | `*scan*.pdf`, `*Scan*.pdf` | Yes (needs OCR) | Raw scanner output | | `*QuickScan*` | Yes (needs OCR) | Raw scanner output | | `YYYYMMDD_*_iOS.pdf` | No (already searchable) | iOS scanning apps (e.g., Scanner Pro, Notes) apply OCR at capture | | `*W2*`, `*1099*`, `*1098*` | No | Tax forms are digitally generated by institutions | | `Scan from YYYY-MM-DD*` | Yes (needs OCR) | Common network scanner / printer output | These are heuristics only — always verify with the text layer check. ## Output format ALWAYS use this exact table structure: ``` | Full Path | OCR Needed? | Rationale | |-----------|-------------|-----------| | /full/path/to/file.pdf | No | 3/3 pages have embedded text — digitally created | | /full/path/to/scan.pdf | Yes | 0/2 pages have embedded text — image-only scan | | /full/path/to/mixed.pdf | Partial | 5/6 pages have text; 1 page (likely cover) is image-only | | /full/path/to/locked.pdf | Inaccessible | I/O error — file may not be locally synced (OneDrive cloud-only) | ``` Followed by a summary line: > **Summary:** 42 files total — 35 No OCR needed, 3 Yes (need OCR), 2 Partial, 2 Inaccessible