Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Extract rich data from PDF pages including text spans with metadata, rendered PNG images, and page mapping. Creates persistent artifacts for downstream processing.
.claude/skills/aiskillstore-pdf-page-extract/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 106% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 120% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 136% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 35% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 917% | 0% |
This skill extracts all necessary data from PDF pages to enable accurate AI-driven HTML generation. It produces three critical artifacts:
This is the deterministic, Python-based foundation for the entire pipeline. All extracted data is saved to persistent files for traceability and future processing.
python3 Calypso/tools/read_page_footers.pyanalysis/page_mapping.jsonpython3 Calypso/tools/rich_extractor.pyanalysis/chapter_XX/rich_extraction.jsonoutput/chapter_XX/page_artifacts/page_YY/02_page_XX.pngpython3 Calypso/tools/extract_images.pyoutput/chapter_XX/images/page_YY_image_*.pngpage_YY_images.jsonchapter: <int> - Chapter number (1-8)
start_page: <int> - Starting PDF index (0-based) or page range
end_page: <int> - Ending PDF index (optional if single page)
pdf_path: <str> - Path to PDF file (default: Calypso/PREP-AL 4th Ed 9-26-25.pdf)
output_base: <str> - Output directory (default: Calypso/output)
mapping_file: <str> - Page mapping file (default: Calypso/analysis/page_mapping.json)Per-page artifacts (in output/chapter_XX/page_artifacts/page_YY/):
01_rich_extraction.json - Text spans with metadata02_page_XX.png - Rendered PDF page imagepage_mapping.json - Shared mapping file (symlink or copy)Extraction data (in analysis/chapter_XX/):
rich_extraction.json - Full extraction for all pages in chapterpage_6_pattern_analysis.json - (Optional) Pattern analysis for specific pagesImages (in output/chapter_XX/images/chapter_XX/):
page_XX_image_*.png - Embedded images from pagepage_XX_images.json - Metadata for embedded imagesjson{ "page_number": 16, "pdf_index": 15, "book_page": 17, "chapter": 2, "dimensions": { "width": 612, "height": 792 }, "text_spans": [ { "text": "Rights in Real Estate", "font": "Arial-BoldMT", "size": 27.04, "bold": true, "italic": false, "bbox": { "x0": 72, "y0": 150, "x1": 400, "y1": 177 }, "color": 0, "sequence": 1 } ], "analysis": { "font_sizes": { "27.04": 1, "11.04": 45 }, "font_styles": { "bold_27.04": 1, "regular_11.04": 45 }, "likely_headings": [ { "text": "Rights in Real Estate", "level": 1, "confidence": 0.95 } ], "likely_paragraphs": [ { "text": "Real property consists of...", "type": "body_text" } ] }, "extraction_timestamp": "2025-11-08T14:30:00Z", "extraction_tool": "rich_extractor.py v1.0" }
bashcd Calypso/tools python3 read_page_footers.py \ --start 15 \ --end 28 \ --pdf "../PREP-AL 4th Ed 9-26-25.pdf" \ --output "../analysis/page_mapping.json"
Success indicators:
bashcd Calypso/tools python3 rich_extractor.py \ --pdf "../PREP-AL 4th Ed 9-26-25.pdf" \ --start 15 \ --end 28 \ --output "../analysis/chapter_02/rich_extraction.json"
Success indicators:
bashcd Calypso/tools python3 -c " import fitz pdf = fitz.open('../PREP-AL 4th Ed 9-26-25.pdf') for page_idx in range(15, 29): page = pdf[page_idx] pix = page.get_pixmap(matrix=fitz.Matrix(3, 3)) # 300% zoom for high-res pix.save(f'../output/chapter_02/page_artifacts/page_{page_idx:02d}/02_page_{page_idx}.png') pdf.close() "
bashcd Calypso/tools # For each page with images python3 extract_images.py \ --page 17 \ --pdf "../PREP-AL 4th Ed 9-26-25.pdf" \ --output "../output" \ --mapping "../analysis/page_mapping.json"
Before declaring extraction complete:
01_rich_extraction.json exists02_page_XX.png exists and is validpage_mapping.json existsIf PDF file not found:
If page mapping fails:
If rich extraction produces no text:
"page_type": "image_only"If PNG rendering fails:
All artifacts include metadata:
This enables:
✓ All required files created in correct directories ✓ Rich extraction JSON is valid and complete ✓ PNG image renders correctly ✓ Page mapping is accurate ✓ All data persisted and ready for next skill ✓ No extraction errors or warnings
Once extraction completes successfully:
PDF won't open: Verify file path, ensure PDF is not corrupted No text extracted: Page may be image-only (OCR needed) Wrong page numbers: Check page_mapping.json for accuracy PNG images are blank: Try increasing zoom factor (3x = 300 DPI)
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-06 | fail→fail | 6,833 | 17,880 | +162% | 1 | 1 | 0% | 1,255 | 5,997 | +378% | 0 | 0 | — |
case-01 | fail→fail | 6,437 | 5,028 | -22% | 1 | 1 | 0% | 357 | 3,151 | +783% | 0 | 0 | — |
case-02 | fail→fail | 18,458 | 5,801 | -69% | 1 | 1 | 0% | 3,913 | 2,736 | -30% | 0 | 0 | — |
case-03 | fail→fail | 31,771 | 4,539 | -86% | 1 | 1 | 0% | 6,221 | 2,709 | -56% | 0 | 0 | — |
case-04 | fail→fail | 28,745 | 3,169 | -89% | 1 | 1 | 0% | 6,182 | 2,889 | -53% | 0 | 0 | — |
case-05 | fail→fail | 12,892 | 22,807 | +77% | 1 | 1 | 0% | 2,241 | 5,906 | +164% | 0 | 0 | — |
case-07 | fail→pass | 14,444 | 12,741 | -12% | 1 | 1 | 0% | 2,313 | 4,773 | +106% | 0 | 0 | — |
case-08 | pass→pass | 9,950 | 6,028 | -39% | 1 | 1 | 0% | 1,635 | 3,490 | +113% | 0 | 0 | — |
case-09 | fail→fail | 7,524 | 7,477 | -1% | 1 | 1 | 0% | 1,392 | 3,942 | +183% | 0 | 0 | — |
case-10 | fail→pass | 8,010 | 3,779 | -53% | 1 | 1 | 0% | 1,449 | 3,186 | +120% | 0 | 0 | — |
case-11 | fail→pass | 7,558 | 3,003 | -60% | 1 | 1 | 0% | 1,283 | 3,026 | +136% | 0 | 0 | — |
case-12 | pass→pass | 11,530 | 5,429 | -53% | 1 | 1 | 0% | 1,925 | 3,549 | +84% | 0 | 0 | — |
case-13 | pass→pass | 6,844 | 3,095 | -55% | 1 | 1 | 0% | 1,142 | 2,897 | +154% | 0 | 0 | — |
case-14 | fail→pass | 12,332 | 1,915 | -84% | 1 | 1 | 0% | 2,023 | 2,729 | +35% | 0 | 0 | — |
case-15 | fail→pass | 1,657 | 2,076 | +25% | 1 | 1 | 0% | 279 | 2,837 | +917% | 0 | 0 | — |
case-16 | fail→fail | 15,152 | 2,084 | -86% | 1 | 1 | 0% | 2,590 | 2,803 | +8% | 0 | 0 | — |
case-17 | fail→pass | 9,065 | 1,685 | -81% | 1 | 1 | 0% | 1,468 | 2,743 | +87% | 0 | 0 | — |
case-18 | pass→pass | 8,308 | 2,011 | -76% | 1 | 1 | 0% | 1,186 | 2,772 | +134% | 0 | 0 | — |
case-19 | pass→pass | 11,935 | 2,680 | -78% | 1 | 1 | 0% | 1,909 | 2,857 | +50% | 0 | 0 | — |
case-20 | fail→pass | 9,504 | 2,702 | -72% | 1 | 1 | 0% | 1,623 | 2,951 | +82% | 0 | 0 | — |
case-21 | fail→pass | 16,695 | 7,038 | -58% | 1 | 1 | 0% | 2,929 | 3,793 | +29% | 0 | 0 | — |
case-22 | fail→pass | 8,347 | 3,060 | -63% | 1 | 1 | 0% | 1,326 | 2,926 | +121% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +41 percentage points is the difference between those two pass rates over the 19 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.