dleerdefi/claude-code-construction/schedule-extractor

Claude Code and agent skill by dleerdefi/claude-code-construction

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Extract tabular schedule data from construction drawings — door, window, finish, fixture, panel schedules — and output to Excel. Triggers: 'door schedule', 'extract schedule', 'schedule to Excel', 'panel schedule'.

Install

npx vskill@latest install dleerdefi/claude-code-construction/schedule-extractor

SKILL.md

Schedule Extractor

Extracts tabular schedule data embedded in drawing sheets or spec pages and outputs structured Excel files. Schedules are typically one element among many on a sheet — or the entire sheet may be a schedule.

First: the mode (both workflows)

Before extracting or reconciling, read .construction/project.yaml. Present and readable means AgentCM mode: note its contract_version and follow ${CLAUDE_PLUGIN_ROOT}/reference/agentcm-mode.md. Absent means flat-file mode. A listing that shows the file, or .construction/database.yaml alone, does not decide it: read the file.

Workflow

Extraction Progress:
- [ ] Step 1: Discover schedule locations
- [ ] Step 2: Isolate (crop) the schedule region
- [ ] Step 3: Extract structured data (pdfplumber + vision)
- [ ] Step 4: Validate and clean data
- [ ] Step 5: Output to Excel
- [ ] Step 6: Ingest to AgentCM (AgentCM mode)
- [ ] Step 7: Write a finding
Step 1: Discover Schedule Locations

Use a multi-source discovery approach, checking all available sources:

Source A — Sheet titles in sheet index (primary, most reliable)

Search .construction/index/sheet_index.yaml (or the sheet index you've built) for sheets with "SCHEDULE" in the title. Many important schedules occupy an entire sheet — the sheet title tells you exactly what it is:

  • "DOOR SCHEDULE" → entire sheet is a door schedule
  • "FINISH SCHEDULE" or "ROOM FINISH SCHEDULE" → entire sheet is finishes
  • "WINDOW SCHEDULE" → entire sheet is windows
  • "PANEL SCHEDULE" → electrical panel schedule
  • "FIXTURE SCHEDULE" → plumbing fixtures

For dedicated schedule sheets, the entire page is the extraction target — no need to crop.

Source B — AgentCM's tables (AgentCM mode)

In AgentCM mode (.construction/project.yaml exists; follow ${CLAUDE_PLUGIN_ROOT}/reference/agentcm-mode.md), .construction/INDEX.md's Schedules and legends table lists every table AgentCM found, each in its own .construction/schedules/<sheet>-<n>.tsv. The file's comment line gives the table's box on the sheet (x y w h, 0 to 1 from the top left) and, for a schedule already ingested, its schedule_id (none for a table read from the sheet's text alone). For embedded schedules on non-schedule sheets, that box is where to look: sh .construction/crop.sh <sheet> <x> <y> <w> <h>.

Note: A table read from the text is AgentCM's reading, and its box an estimate: treat both as leads, not definitive boundaries. Always verify with vision.

Source C — Discipline-based heuristics

Schedules appear on specific sheet types:

  • Door schedule → typically on A-0.XX or A-8.XX sheets, or a dedicated sheet
  • Window schedule → same sheets as door schedule, or separate
  • Room finish schedule → A-0.XX or interior sheets
  • Panel schedule → E-X.XX electrical sheets
  • Fixture schedule → P-X.XX plumbing sheets
  • Equipment schedule → M-X.XX mechanical sheets
Source D — Vision scan (fallback)

If no index or graph is available:

bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/rasterize_page.py" "{pdf_path}" {page} --dpi 150 --output ".construction/skills/schedule-extractor/pages/full_sheet.png"

Use vision on the full sheet image: "Identify any tabular schedules on this drawing sheet. Report the approximate bounding box (top-left x,y and bottom-right x,y) as fractions of the image width and height between 0 and 1, the schedule type, and the column headers visible."

Step 2: Isolate the Schedule Region

For dedicated schedule sheets (entire page is a schedule): Skip cropping — use the full page.

For embedded schedules (schedule is one element on a larger sheet):

Crop the identified region with padding. The box is the 0–1 fractions from Step 1, so --normalized is required; without it the script reads the values as pixels and returns an empty crop:

bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/crop_region.py" ".construction/skills/schedule-extractor/pages/full_sheet.png" \
--box {x1},{y1},{x2},{y2} --normalized \
--padding 20 \
--output ".construction/skills/schedule-extractor/pages/schedule_crop.png"

Re-rasterize at higher DPI (300) for the cropped region to improve text clarity. rasterize_page.py --crop takes percentages, so multiply each fraction by 100 (0.62,0.08,0.98,0.45 becomes 62,8,98,45):

bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/rasterize_page.py" "{pdf_path}" {page} \
--dpi 300 \
--crop {x1_pct},{y1_pct},{x2_pct},{y2_pct} \
--output ".construction/skills/schedule-extractor/pages/schedule_hires.png"
Step 3: Extract Structured Data
In AgentCM mode — the table AgentCM read

A table INDEX.md lists under Schedules and legends is already read. Turn its file into the exporter's data with the reader, never with a converter of your own:

bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_SKILL_DIR}/scripts/agentcm_schedule.py" ".construction/schedules/<sheet>-<n>.tsv" \
--type door_schedule --data ".construction/skills/schedule-extractor/<sheet>-<n>.json"

It prints the header row it took and what it left out. A table read from the sheet's text has its title and header rows at the top: when it took the wrong row, give --header-row <y> (the line's position, as the file prints it) and --header-rows <n> for a header on several lines. Then verify the table against the drawing with crop.sh and the box on the file's comment line (Source B). Where the drawing shows a different value, correct that cell in the data JSON with the Edit tool, and record the correction as ${CLAUDE_PLUGIN_ROOT}/reference/agentcm-mode.md says. Methods A to C below are for a table AgentCM did not find.

Otherwise use a try → validate → fallback approach:

Method A — pdfplumber table extraction (try first)

Extract the page's tables with the shared script (its JSON holds text and tables; add --bbox x1,y1,x2,y2 in PDF points to limit it to the schedule region):

bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/extract_text_region.py" "{pdf_path}" {page} --output ".construction/skills/schedule-extractor/tables.json"

If multiple tables are found, select the largest one (most rows with the most columns — schedules are wide). The first row of the selected table contains headers; subsequent rows are data. If no tables are found or results look garbled, fall back to vision (Method B). Do not write pdfplumber code of your own.

Evaluate Method A — Quality Gate

Check these criteria before proceeding:

  1. Row count: Did pdfplumber extract at least 10 data rows? Most schedules have 20-200+ entries.
  2. Column consistency: Do ≥80% of rows have the same number of columns? Inconsistent columns = parsing error.
  3. Non-empty cells: Are >50% of cells non-empty? Mostly-empty extraction = parsing failed.
  4. First column validity: Does the first column contain recognizable IDs (door numbers, room numbers, equipment tags)?

Decision:

  • All 4 checks pass → Method A succeeded, proceed to Step 4
  • Any check fails → Method A failed, use Method B below
QUALITY GATE:
extracted_rows >= 10? YES → check next | NO → use Method B
column_consistency >= 80%? YES → check next | NO → use Method B
non_empty_cells >= 50%? YES → check next | NO → use Method B
first_col_has_valid_ids? YES → use Method A | NO → use Method B
Method B — Vision extraction (fallback)

When pdfplumber fails (common with complex layouts, merged cells, non-standard table lines):

  1. Rasterize the sheet at 150 DPI for overview:
bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/rasterize_page.py" "{pdf_path}" {page} --dpi 150 --output ".construction/skills/schedule-extractor/pages/full_sheet.png"
  1. Use vision on the full sheet image to read the schedule directly:

"This is a construction drawing sheet containing a schedule (tabular data). Extract ALL rows from the schedule as a JSON array of objects. The first row of the table contains column headers — use those as object keys. Each subsequent row is one entry. Preserve exact values including dimensions, abbreviations, and codes. If a cell is empty, use null."

  1. For dense schedules with small text, re-rasterize at 300 DPI and crop to just the schedule region:
bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_PLUGIN_ROOT}/scripts/pdf/rasterize_page.py" "{pdf_path}" {page} --dpi 300 --output ".construction/skills/schedule-extractor/pages/schedule_hires.png"
Method C — Hybrid (for maximum accuracy)

Run both methods and cross-validate:

  • pdfplumber gives exact text positioning and catches every character
  • Vision catches content pdfplumber misses (stamps, handwritten marks, non-standard table layouts)
  • Compare row counts: if they differ by >10%, investigate the discrepancy
  • Use vision results for rows that pdfplumber returned empty or garbled
Step 4: Validate and Clean

After extraction (by either method):

  • Row count check: Compare extracted count against what's visually present. If off by >10%, re-extract using the other method.
  • Column structure: Verify headers match expected schedule type (door schedule has MARK/SIZE/TYPE/FRAME/HARDWARE; finish schedule has RM.NO/NAME/FLOOR/BASE/WALLS/CLG)
  • Merged cell cleanup: Expand merged header cells (e.g., "WALLS" spanning A/B/C/D sub-columns)
  • Normalize dimensions: 3' - 0" → 3'-0" (remove spaces around dashes)
  • Flag revisions: Note any cells within revision clouds or delta markers
  • Cross-reference with AgentCM's identifiers: In AgentCM mode, check each room number and door mark against .construction/tags.tsv (kind room or door; the lines starting with the number and a tab). Not finding one there proves nothing (INDEX.md says when its room list is incomplete): report it as "not in AgentCM's index" and check the plan sheets' .construction/sheets/<sheet>.tsv.
Step 5: Output to Excel
bash
"${CLAUDE_PLUGIN_ROOT}/bin/construction-python" "${CLAUDE_SKILL_DIR}/scripts/schedule_to_xlsx.py" \
--data ".construction/skills/schedule-extractor/<sheet>-<n>.json" \
--type door_schedule \
--project "Project Name" \
--sheet "A-0.01" \
--output "Door_Schedule_A-0.01.xlsx"

The data JSON is working data: write it (with the Write tool, or the reader in AgentCM mode) under .construction/skills/schedule-extractor/, never in the project root or a folder of your own. The workbook is the deliverable: write it in the project folder as the command above shows, never under .construction/. For a table AgentCM has already ingested (schedule_id=<id> on its file's comment line), add --schedule-id <id> --sheet-id <the sheet's id> so the workbook can come back through the round trip.

The script creates a formatted Excel workbook with:

  • Header row with project info and source sheet
  • Auto-sized columns
  • Conditional formatting for empty/flagged cells
  • Source metadata in a separate tab
Step 6: Ingest to AgentCM (AgentCM mode)

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
5

Not refreshed yet.

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
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/dleerdefi/claude-code-construction/schedule-extractor/badge)](https://verified-skill.com/skills/dleerdefi/claude-code-construction/schedule-extractor)

Something wrong with this skill or its page? Tell us.