$npx -y skills add dleerdefi/claude-code-construction --skill sheet-splitterSplit a bound drawing set PDF into individual sheet PDFs. Extracts sheet numbers from title blocks via vision, renames files. Triggers: 'split drawings', 'break up the drawing set', 'separate sheets'. Run after /project-setup.
| 1 | # Sheet Splitter |
| 2 | |
| 3 | Splits a bound drawing set PDF into individual page PDFs. Mirrors what spec-splitter does for specifications. |
| 4 | |
| 5 | ## Pipeline Position |
| 6 | Run after `/project-setup` identifies bound drawing sets. Produces split PDFs and `sheet_index.yaml` consumed by `/schedule-extractor` and all drawing analysis skills. |
| 7 | |
| 8 | This is valuable for: |
| 9 | - **Project teams**: Navigate drawings by sheet number instead of scrolling a multi-page PDF |
| 10 | - **Other skills**: `sheet-index-builder`, `drawing-reader`, and all drawing analysis skills work better with individual sheet files |
| 11 | - **AgentCM**: Split files become the basis for per-sheet structured data |
| 12 | |
| 13 | ## Workflow |
| 14 | |
| 15 | ``` |
| 16 | Sheet Split Progress: |
| 17 | - [ ] Step 1: Check if drawings are already split |
| 18 | - [ ] Step 2: Locate the bound drawing set |
| 19 | - [ ] Step 3: Split into individual page PDFs |
| 20 | - [ ] Step 4: Extract sheet numbers from title blocks |
| 21 | - [ ] Step 5: Rename files with sheet number + title |
| 22 | - [ ] Step 6: Update project context |
| 23 | - [ ] Step 7: Write graph entry (AgentCM only) |
| 24 | ``` |
| 25 | |
| 26 | ### Step 1: Check if Drawings Are Already Split |
| 27 | |
| 28 | Look for individual sheet PDFs. Drawings are already split if: |
| 29 | - **AgentCM**: `.construction/index/sheet_index.yaml` exists with individual sheet entries and file paths point to split PDFs |
| 30 | - Multiple PDFs exist with sheet number patterns in filenames (e.g., `A-1.1 - FLOOR PLAN.pdf`) |
| 31 | - A `sheet_index.yaml` exists in the drawings directory |
| 32 | |
| 33 | If already split, report the count and skip. If AgentCM has the sheet index but files haven't been physically split on disk, offer to split using the existing metadata for naming. |
| 34 | |
| 35 | ### Step 2: Find ALL Drawing PDFs |
| 36 | |
| 37 | Search the project directory for ALL PDFs that are drawings. Many projects have multiple drawing PDFs: |
| 38 | - **Multi-part sets**: Part1.pdf, Part2.pdf, Part3.pdf (split by file size) |
| 39 | - **Discipline sets**: Architectural.pdf, Civil.pdf, Electrical.pdf, Mechanical.pdf |
| 40 | - **Single combined**: one large PDF with all sheets |
| 41 | |
| 42 | Search in: |
| 43 | - Folders named `drawings/`, `plans/`, `01 - Drawings/`, or similar (case-insensitive) |
| 44 | - The project root (some projects have no folder structure) |
| 45 | - Look for PDFs > 2MB with keywords: "plan", "drawing", "bid set", "dwg", discipline names |
| 46 | |
| 47 | Process EACH PDF found. All split pages go to the same `sheets/` output directory. |
| 48 | |
| 49 | If the user specifies a single file (`/sheet-splitter path/to/specific.pdf`), process only that file. |
| 50 | |
| 51 | ### Step 3: Split Pages |
| 52 | |
| 53 | Run the split script on each drawing PDF found: |
| 54 | |
| 55 | ```bash |
| 56 | ${CLAUDE_SKILL_DIR}/../../bin/construction-python ${CLAUDE_SKILL_DIR}/scripts/split_drawing_set.py \ |
| 57 | "{drawing_set.pdf}" \ |
| 58 | --output-dir "{drawings_directory}/sheets" |
| 59 | ``` |
| 60 | |
| 61 | The script splits each page into its own PDF: `page_001.pdf`, `page_002.pdf`, etc. It does NOT attempt to read sheet numbers — that's unreliable across different title block formats. |
| 62 | |
| 63 | ### Step 4: Identify Sheets via Vision |
| 64 | |
| 65 | After splitting, read each page to identify sheet numbers and titles: |
| 66 | |
| 67 | 1. Rasterize the title block region of each page: |
| 68 | ```bash |
| 69 | ${CLAUDE_SKILL_DIR}/../../bin/construction-python ${CLAUDE_SKILL_DIR}/../../scripts/pdf/rasterize_page.py page_NNN.pdf 1 --dpi 200 --output tb.png |
| 70 | ``` |
| 71 | |
| 72 | 2. Use vision on the rasterized title block: "Read the title block on this construction drawing. What is the sheet number and sheet title?" |
| 73 | |
| 74 | 3. Rename the file: `page_001.pdf` → `A-1.1 - FLOOR PLAN.pdf` |
| 75 | |
| 76 | 4. Update `sheet_index.yaml` with the identified sheet number, title, and discipline. |
| 77 | |
| 78 | **Title blocks vary significantly across firms** — they can be on the east side, south side, or bottom-center. Some use VA standard forms, some use firm-specific formats. Vision handles all these variations. |
| 79 | |
| 80 | ### Step 5: Write Sheet Index |
| 81 | |
| 82 | After identifying all sheets, write `.construction/index/sheet_index.yaml`. |
| 83 | |
| 84 | ### Output |
| 85 | |
| 86 | ``` |
| 87 | sheets/ |
| 88 | A-1.1 - FLOOR PLAN.pdf ← renamed by Claude via vision |
| 89 | A-2.1 - ELEVATIONS.pdf |
| 90 | S-1.1 - FOUNDATION PLAN.pdf |
| 91 | page_006.pdf ← could not read title block |
| 92 | ... |
| 93 | sheet_index.yaml |
| 94 | ``` |
| 95 | |
| 96 | ### Step 6: Update Project Context |
| 97 | |
| 98 | After splitting and identifying, update `.construction/project_context.yaml` with: |
| 99 | - `documents.drawing_count`: number of sheets |
| 100 | - `documents.disciplines`: list of unique discipline prefixes found |
| 101 | |
| 102 | ### Step 7: Write Graph Entry (AgentCM only) |
| 103 | |
| 104 | If `.construction/` directory exists, write a graph entry: |
| 105 | |
| 106 | ```bash |
| 107 | ${CLAUDE_SKILL_DIR}/../../bin/construction-python ${CLAUDE_SKILL_DIR}/../../scripts/graph/write_finding.py \ |
| 108 | --type "drawings_split" \ |
| 109 | --title "Drawing set split: {N} sheets from {source_pdf}" \ |
| 110 | --data '{"sheet_count": N, "source_pdf": "...", "identified_count": M, "unidentified_count": K, "disc |