alpacalabsllc/product-spec-pdf-parser
Extract structured FF&E specs from PDF price books, fact sheets, or spec sheets into a schedule. Use for product PDFs; not web URLs or EPDs.
npx skills add https://github.com/AlpacaLabsLLC/skills-for-architects --skill product-spec-pdf-parser
Extract structured FF&E data from product PDF files — price books, fact sheets, configurator sheets, and spec sheets. Uses PyMuPDF for text extraction and Claude's reasoning to parse wildly varying PDF layouts into a standardized schedule.
The user provides PDFs in one of these ways:
.pdf files)Also ask (or use defaults):
expand (one row per variant/SKU, default) or summarize (comma-separated variants in one row)Persistent products use the nearest project-root product-library.csv with no extra columns. Read ../../schema/product-schema.md and ../../schema/csv-conventions.md.
Skill-specific named values: Source is pdf-parser; Status is saved; Link, Thumbnail, Vendor, Sale Price, and Image URL are blank unless directly supported by the PDF.
NotesPDFs contain fields that don't have dedicated master columns. Append these to Notes using | as delimiter:
Variant: Diamond, BlackPrice adder: +$130 (PostureFit SL)Origin: SwedenSource: alphabeta-fact-sheet.pdfExample Notes cell: Variant: Diamond, Black | Origin: Sweden | Source: alphabeta-fact-sheet.pdf
Different PDF types require different approaches:
expand vs summarize modeParse the user's input to identify PDF file(s) and output preferences.
.pdf files and report countexpand unless the user says otherwiseUse PyMuPDF (fitz) to extract text from each PDF. Run this Python script via Bash:
import fitz
import sys
import json
pdf_path = sys.argv[1]
doc = fitz.open(pdf_path)
pages = []
for i, page in enumerate(doc):
text = page.get_text()
pages.append({"page": i + 1, "text": text})
doc.close()
print(json.dumps({"filename": pdf_path.split("/")[-1], "total_pages": len(pages), "pages": pages}))
For each PDF, extract all pages and save the JSON output.
Read the extracted text and identify all products, variants, and specifications. This is the core intelligence step — Claude reasons over the text to structure it.
For small PDFs (≤20 pages): Process all pages at once.
For large PDFs (>20 pages): Process in chunks of 10 pages at a time. After each chunk:
Parsing instructions:
Show a summary markdown table with the parsed products. Include:
If persistence was requested, use this results table as the change preview and present the single confirmation gate. Do not ask the same confirmation first in prose.
Without persistence, leave the result as Markdown. After approval to persist, serialize all complete canonical rows as one JSON array and invoke python3 "${CLAUDE_PLUGIN_ROOT}/skills/master-schedule/scripts/csv-library.py" append product --project <project-root> --row-json <batch.json> exactly once. The shared helper validates the complete batch and CSV before one atomic replacement; never loop per row. PDF-specific data stays in Notes; do not create extra columns or secondary structured exports.
After processing, always report:
Parsed: X products from Y PDF(s)
- filename.pdf: N products extracted
- filename2.pdf: M products extracted
Issues: [list any problems]
Take alpacalabsllc/product-spec-pdf-parser from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.