mikeonbreeze/cc-crossbeam/adu-pdf-extraction
Claude Code and agent skill by mikeonbreeze/cc-crossbeam
- community
Checking that the SKILL.md file is still in the repository.
This skill extracts construction PDF plan binders into agent-consumable formats. It should be used when a contractor or homeowner provides a PDF binder of construction plans (site plans, floor plans, structural drawings, Title 24 reports) that needs to be parsed for permit review, corrections response, or plan check analysis. Produces three outputs: page PNGs for vision analysis, structured markdown per page via vision extraction, and a JSON manifest for routing.
Install
npx vskill@latest install mikeonbreeze/cc-crossbeam/adu-pdf-extractionSKILL.md
Construction PDF Binder Extraction
Purpose
Extract multi-page construction plan PDF binders into a vision-first structure that enables an AI agent to efficiently navigate, reference, and respond to specific pages and drawing zones within the plans.
Construction PDFs are uniquely challenging because:
- Single PDF pages often contain multiple sub-pages composited together
- Text is rendered by CAD software in non-extractable ways
- Watermarks (e.g., "Study Set - Not For Construction") inject diagonal
characters that pollute text extraction
- Drawing content (dimensions, callouts, symbols) carries critical meaning
that only vision can interpret
- Title 24 energy reports are often rasterized images, not selectable text
When to Use
Invoke this skill when:
- A PDF binder of construction plans is provided (typically 10-30+ pages)
- Plan check corrections need to reference specific sheets and locations
- A permit checklist needs to be generated from submitted plans
- Any construction document needs to be made queryable by an AI agent
Why Vision-First (with Tesseract Cross-Reference)
Four text extraction methods were tested head-to-head on real construction PDFs. Vision wins on every page type for structure and layout. See references/extraction-findings.md for the full comparison data.
| Method | Drawing Pages | Text-Heavy Pages | Rasterized (Title 24) | |
|---|---|---|---|---|
| pdftotext | Garbage | Usable | Empty | |
| pdfplumber | Reversed text | Good | 367 chars | |
| Tesseract OCR | Garbled | Good | Good | |
| Claude Vision | Excellent | Excellent | Excellent |
Vision is the primary extraction method. It handles structure, spatial understanding, watermark transparency, drawing interpretation, and rasterized content reading. No other method comes close on construction PDFs.
Tesseract supplements vision for numeric accuracy. Testing on dense cover sheets revealed that vision at 1568px resolution can hallucinate specific numeric values — "65.0 sq ft" becomes "856", "475 sq ft" gets missed entirely. Tesseract's character-level OCR reliably captures exact digits even on dense pages. The hybrid approach: run both, give subagents both outputs, and cross-reference numbers. On drawing-heavy pages where Tesseract produces garbage, subagents are instructed to ignore it.
Do NOT use pdftotext or pdfplumber for construction PDFs. pdftotext produces garbage on drawings and empty output on rasterized pages. pdfplumber produces reversed text (*TEEHS REVOC*) — completely unusable.
At ~1,500 tokens per page PNG, a full 30-page binder costs ~45K tokens for complete vision extraction — trivial at production pricing.
Extraction Process
Step 1: Prepare Output Directory
Create the output directory structure:
Step 2: Extract Page PNGs + Tesseract Text
Run scripts/extract-pages.sh to split the PDF into page PNGs, resize them for API consumption, and run Tesseract OCR:
The script does three things:
- Split PDF — Uses
pdftoppmat 200 DPI. Each page becomes
pages-png/page-01.png, page-02.png, etc.
- Resize PNGs to 1568px max — Claude's API internally resizes images
to 1568px on the longest side. Construction PDFs at 200 DPI on D-size sheets produce 7200x4800 PNGs — resizing before upload saves bandwidth and avoids the 32MB API payload limit without losing any information the model would actually see. Uses ImageMagick (Linux) or sips (macOS).
- Tesseract OCR — Runs
tesseracton each resized PNG to produce
pages-text/page-01.txt, etc. These raw text dumps supplement vision extraction by providing reliable numeric values for cross-reference. On drawing-heavy pages, Tesseract output will be garbage — subagents are instructed to recognize and ignore it.
Note: CAD-generated construction PDFs commonly produce Poppler warningslike"Syntax Error: insufficient arguments for Marked Content". These areharmless — the PNGs render correctly. The script suppresses these via2>/dev/null.
If pdftoppm is not available, fall back to ImageMagick:
Then manually resize and run Tesseract on the resulting PNGs.
Step 3: Vision Extract Every Page (Rolling Window)
Vision extraction is the most time-intensive step. Use a rolling window of parallel subagents — one page per subagent, max 3 in flight at any time. The full prompt template is in prompts/vision-extract-page.md — read it and use it as the prompt for each subagent.
Why One Page Per Subagent
Each subagent conversation accumulates every image it reads into the message history. With multi-page batches, by the time the subagent processes page 3, all 3 PNGs are in context for every API call. This causes:
- API image limits: Claude's API enforces a 2000px-per-image cap when
>20 images are in the conversation. Construction PNGs at 200 DPI are typically 7200x4800 — well over this limit.
- Token waste: Each additional image in context costs ~1,500 tokens per
API round-trip, even when only analyzing the current page.
- Quality degradation: More images in context = more noise for the model.
One page per subagent means exactly one image in context. No multi-image limits, cleaner extraction, and the Tesseract text file provides numeric cross-reference without adding image tokens.
Resource Constraints
Maximum 3 concurrent subagents. One page per subagent.
This is a hard constraint for deployment to Vercel sandboxes (4 GB RAM total). The orchestrator + 3 subagents = 4 processes, each getting ~1 GB RAM. Do not exceed 3 concurrent subagents under any circumstances.
Rolling Window Orchestration
Instead of fixed rounds (launch 3, wait for all 3, launch next 3), use a rolling window: launch 3 subagents, and as each one completes, immediately launch the next. This keeps 3 subagents in flight at all times until all pages are processed.
- Count the total page PNGs in
pages-png/ - Launch subagents for pages 1, 2, and 3 (3 in parallel)
- As each subagent completes, immediately launch the next page
- Continue until all pages are queued
- Wait for the final subagents to complete
- Verify all
pages-vision/page-NN.mdANDpage-NN.jsonfiles exist
Throughput
| Binder Size | Subagents | Max Concurrent | Approx. Wall Time | |
|---|---|---|---|---|
| 9 pages | 9 | 3 | ~3x single page | |
| 15 pages | 15 | 3 | ~5x single page | |
| 26 pages | 26 | 3 | ~9x single page | |
| 30 pages | 30 | 3 | ~10x single page |
Each subagent takes ~3-4 minutes (read references, read PNG, write .md, write .json). With 3 concurrent, a 26-page binder completes in ~30 minutes.
Output Format
Each subagent writes two files per page to pages-vision/:
- `page-NN.md` — Structured markdown with full extracted content:
- Title block identification (sheet number, title, firm)
- All text content (tables, notes, schedules, specifications)
- Spatial zone mapping for every content element
- Drawing descriptions for non-text content
- Confidence annotations for watermark-obscured or low-resolution content
- `page-NN.json` — Manifest fragment for routing:
- Page metadata (sheet_id, category, subcategory)
key_contentarray with specific values (guided by extraction priorities)topicskeyword tags for corrections letter matchingdrawing_zonesspatial map"NOT SHOWN: [item]"entries for expected-but-absent content- Cover sheet fragment includes
_projectmetadata
The extraction priorities reference (references/adu-extraction-priorities.md) guides subagents on what to capture with specificity and what to flag as absent for each content type. This produces manifest entries targeted for corrections letter routing without any decision-making about compliance.
See prompts/vision-extract-page.md for the full prompt template including both output formats.
Step 4: Assemble the Manifest
The manifest is what makes everything else useful. It enables an agent to route to the correct page(s) without loading all pages into context.
Since each vision subagent already wrote a JSON manifest fragment per page (in Step 3), assembly is deterministic — no LLM needed.
Run the assembly script:
The script:
- Reads all
page-NN.jsonfragments frompages-vision/ - Extracts
_projectmetadata from the cover sheet fragment - Combines into
{ "project": {...}, "pages": [...] } - Validates required fields and page numbering
- Writes
binder-manifest.json
Exit codes: 0 = clean, 1 = assembled with issues, 2 = fatal error.
The orchestrator MUST always review the assembled manifest (see Step 4a). The assembly script is deterministic but not smart — it can concatenate JSON but it cannot catch semantic issues like a wrong category, a vague key_content entry, or a missing _project field that should have been extracted. A quick orchestrator read-through catches things the script never could.
The assembled manifest follows the schema in references/manifest-schema.md. Each page entry captures:
- Sheet ID and title — from the title block
- Category — general, architectural, structural, energy, code_compliance,
mechanical, plumbing, electrical
- What's on the page — key content items with exact values, specific
enough to match correction letter items
- What's NOT on the page —
"NOT SHOWN: [item]"entries for expected-
but-absent content (guided by extraction priorities)
- Topics — keyword tags for routing
- Drawing zones — spatial map of where things are on the page
Step 4a: Orchestrator Review (ALWAYS — Not Optional)
After the assembly script runs, the orchestrator must read binder-manifest.json and review it. This takes seconds and catches things the script cannot.
Standard Review Checklist
- Read the full
binder-manifest.json - Verify
projectmetadata is populated (address, type, owner, sqft) - Verify page count matches PNG count
- Spot-check
sheet_idvalues look reasonable - Check that
key_contentarrays have specific values, not vague entries - If the script reported issues (exit code 1), fix them
- Fix any JSON errors, missing fields, or wrong categories
Cross-Page Consistency Check (Critical)
Vision models can hallucinate individual digits — a "3" read as "2", a "5" as "6". When this happens on the cover sheet, the wrong value cascades into project metadata and poisons everything downstream.
Every page's JSON fragment includes a `title_block_address` field — the address as read independently from that page's title block. The orchestrator must use these to verify project-level values:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingadu-skill-development/skill/adu-pdf-extraction/SKILL.md
Popularity
- Repository stars
- 171
- Repository forks
- 62
- 7-day trend score
- 26
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 18 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/mikeonbreeze/cc-crossbeam/adu-pdf-extraction)