| name | agile:document:combiner |
| description | Combine multiple markdown section files into a single merged document (.md and .pdf). Use when the user wants to merge, combine, consolidate, or generate a single document from sectioned files — for PRDs, design docs, specs, runbooks, or any multi-section markdown project. Triggers on requests to "combine documents", "merge sections", "generate combined doc", "export as single PDF", "merge markdown files", "combine PRD sections", "consolidate doc sections". Works with any directory of markdown section files. Pass the source directory containing section files as the first argument, and optionally the destination directory as the second argument (defaults to same as source). |
| user-invocable | true |
| disable-model-invocation | false |
Agile Document Combiner Skill
Combines multiple markdown section files from a specified directory into a single merged Markdown document and generates a styled PDF via pandoc (markdown → HTML) and WeasyPrint (HTML+CSS → PDF), using the skill's bundled CSS for consistent styling.
Input Parameters
| Parameter | Type | Default | Description |
|---|
sourceDir | string | required (first argument) | Directory containing section .md files |
destDir | string | same as sourceDir (second argument) | Output directory for combined .md and .pdf |
outputName | string | combined-document | Base name for output files (without extension) |
title | string | from index.md or first section | Document title |
pattern | string | section-*.md | Glob pattern to match section files |
indexName | string | index.md | Filename for metadata/index file |
cssPath | string | {skillDir}/styles/markdown-pdf.css | Path to CSS file for PDF styling |
papersize | string | A4 | Paper size (A4, letter, legal) |
margin | string | 10mm | Page margins (all sides) |
toc | bool | true | Generate table of contents |
tocDepth | number | 3 | Table of contents heading depth |
Argument Passing
Arguments are passed via the skill invocation syntax:
/agile-document-combiner /path/to/sections [/path/to/output]
- First argument (required):
sourceDir — the directory containing section markdown files
- Second argument (optional):
destDir — where to write combined .md and .pdf. Defaults to sourceDir if omitted.
Process
Step 1: Resolve Source and Destination Directories
- Use
sourceDir as the first argument — it is required
- Use
destDir as the second argument if provided, otherwise default to sourceDir
- Verify
sourceDir exists and is a directory — error and stop if not found
- If
destDir doesn't exist, attempt to create it
- Resolve
cssPath: if it contains {skillDir}, replace it with the skill's directory path ({skillDir} resolves to .claude/skills/agile-document-combiner relative to the project root). If the resolved path does not exist, error and stop.
Step 2: Discover Section Files
- Find all files matching
{pattern} (default: section-*.md) in sourceDir
- Sort files numerically by extracting the leading sequence of digits from the filename (e.g.,
section-01-executive-summary.md → 1, section-08-glossary.md → 8, section-10-something.md → 10). Do NOT sort alphabetically — string comparison would place section-08 before section-1, which is incorrect. Use a natural/numeric sort: extract the integer prefix from each filename, then sort by that integer ascending.
- Always include
index.md or {indexName} if present — process it first for metadata, then exclude it from content
- If no section files found with the pattern, fall back to: all
*.md files excluding index, or files matching NN-*.md numeric prefix
Step 3: Extract Document Metadata
If index.md (or {indexName}) exists in sourceDir:
- Document title (first h1 heading)
- Version, date, author, status from any info table
- Any classification or important notes
If no index file exists:
- Use
title parameter if provided
- Otherwise extract title from the first section file's h1 heading
- Generate metadata with current date
Step 4: Combine Markdown Files
- Create combined document with a frontmatter-style header
- Include document title as h1
- Include metadata table (title, version, date, status, sections combined)
- Add horizontal rule separator
- Append each section file's content in numeric order
- Section files already have their own headings (e.g.,
## N. Section Title) — preserve them
Output format:
# {Document Title}
| Field | Value |
| -------- | --------- |
| Version | {version} |
| Date | {date} |
| Sections | {count} |
---
{combined section content}
Step 5: Write Combined .md File
- Construct output path:
{destDir}/{outputName}.md
- Write the combined content
- Verify file was written successfully
- Report: file size, section count, source files used
Step 6: Generate PDF
The PDF pipeline is markdown → HTML (via pandoc) → PDF (via WeasyPrint). The CSS file is applied by WeasyPrint, not by pandoc.
Step 6a: Verify Dependencies
-
Verify pandoc is installed:
pandoc --version
-
Verify weasyprint is installed:
weasyprint --version
If WeasyPrint is not installed, report the error with install instructions:
The .md file is already written and delivered — report the PDF error as a warning.
Step 6b: Build WeasyPrint CSS override
The bundled CSS uses VS Code preview variables (e.g., --vscode-*) which are not supported by WeasyPrint. Inject a CSS override after the bundled CSS that maps the VS Code variables to WeasyPrint-compatible values. Write the override to a temporary file (e.g., /tmp/weasyprint-override.css).
Override rules to include:
@page {
size: {papersize};
margin: {margin};
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
font-size: 11pt;
line-height: 1.6;
color: #333;
}
code, pre {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 9pt;
}
pre {
background-color: #f4f4f4 !important;
padding: 12px;
border-radius: 4px;
overflow-x: auto;
}
blockquote {
border-left: 4px solid #ddd;
margin-left: 0;
padding-left: 16px;
color: #666;
}
table {
border-collapse: collapse;
width: 100%;
}
table th,
table td {
border: 1px solid #ddd;
padding: 6px 12px;
text-align: left;
}
table th {
background-color: #f4f4f4;
}
hr {
border: none;
border-top: 2px solid #eee;
margin: 24px 0;
}
h1, h2, h3, h4, h5, h6 {
font-weight: 600;
line-height: 1.25;
}
h1 { font-size: 1.8em; border-bottom: 1px solid #eee; padding-bottom: 0.3em; }
h2 { font-size: 1.4em; }
h3 { font-size: 1.2em; }
a { color: #0066cc; }
Construct the final CSS by concatenating:
- The bundled
{cssPath} CSS content
- The WeasyPrint override CSS
Write the combined CSS to {destDir}/{outputName}.css.
Step 6c: Convert Markdown to HTML via Pandoc
Use pandoc to produce a standalone HTML document (with embedded styles):
pandoc \
"{destDir}/{outputName}.md" \
-o "{destDir}/{outputName}.html" \
--standalone \
--embed-resources \
--metadata title="{documentTitle}" \
--metadata author="{author}" \
--metadata date="{date}" \
--toc={toc} \
--toc-depth={tocDepth}
Note: Do NOT use --pdf-engine or -t latex — this must produce HTML output.
Step 6d: Convert HTML to PDF via WeasyPrint
weasyprint \
"{destDir}/{outputName}.html" \
"{destDir}/{outputName}.pdf" \
--stylesheet="{destDir}/{outputName}.css" \
--uncompressed-pdf
Note: WeasyPrint reads the CSS from {destDir}/{outputName}.css (the combined bundled + override CSS written in Step 6b). Do NOT pass the CSS via WeasyPrint's --stylesheet flag AND also inline it into the HTML — use one or the other.
Step 6e: Verify and Clean Up
- Verify PDF was generated at
{destDir}/{outputName}.pdf
- Optionally remove the intermediate HTML and CSS files to keep the output directory clean, or leave them if explicitly requested.
Output
- Combined .md file at
{destDir}/{outputName}.md
- Generated .pdf file at
{destDir}/{outputName}.pdf
- Summary report:
- Number of sections combined
- List of source files
- Output file sizes
- Any warnings or issues
Error Handling
- If
sourceDir not found or not a directory: error and stop
- If no section files found: error and stop
- If
cssPath not found: error and stop
- If
pandoc is not installed: report error with install instructions (brew install pandoc)
- If
weasyprint is not installed: report error with install instructions; the .md file is still delivered
- If WeasyPrint PDF generation fails: report error and skip PDF; the
.md file is still delivered
- If
destDir doesn't exist: attempt to create it
Example Usage
/agile-document-combiner agile/product/prd
/agile-document-combiner docs/sections
/agile-document-combiner docs/sections docs/output
/agile-document-combiner /Users/me/my-doc/sections /Users/me/my-doc/combined