Agent skill
pdf-generation
This skill should be used when the user asks to "generate a PDF from markdown", "create a printable book", "convert documentation to PDF", or "export chapters as a PDF". Automatically activates when producing a PDF from a directory of ordered markdown chapters using pandoc and weasyprint. Not for single-file markdown-to-PDF conversion or non-documentation use cases.
Install this agent skill to your Project
npx add-skill https://github.com/sjungling/sjungling-claude-plugins/tree/main/plugins/technical-writer/skills/pdf-generation
SKILL.md
PDF Book Generation
Overview
Converts a directory of ordered markdown chapters into a single, styled PDF book with table of contents, page numbers, and resolved inter-chapter links.
Core principle: The markdown files are the source of truth. The PDF is a derived artifact -- never edit the PDF directly.
When to Use
Automatically activates when:
- A request to generate a PDF from markdown chapters is made
- A
technical-overviewor similar multi-chapter doc set is ready for export - A printable or shareable version of documentation is needed
Prerequisites
Three tools must be installed before generation can proceed:
| Tool | Install command | Purpose |
|---|---|---|
pandoc |
brew install pandoc |
Markdown to HTML conversion |
weasyprint |
uv tool install weasyprint |
HTML to PDF rendering |
pango |
brew install pango |
Text layout (weasyprint dependency) |
Before running the script, verify availability:
command -v pandoc >/dev/null 2>&1 || echo "Missing: pandoc (brew install pandoc)"
command -v weasyprint >/dev/null 2>&1 || echo "Missing: weasyprint (uv tool install weasyprint)"
If either tool is missing, install it and retry. The script itself checks for dependencies and exits with a clear error message.
How It Works
The generation pipeline has four stages:
- Collect -- Gather markdown files in order:
README.mdfirst, then00-*.mdthrough99-*.md, thenappendix-*.md - Convert -- Pandoc stitches all files into a single HTML document with a generated table of contents
- Fix links -- Inter-chapter
.mdlinks (e.g.,[architecture](01-architecture.md)) are rewritten to internal#anchorlinks so they work within the single document - Render -- Weasyprint converts the styled HTML to PDF with print-optimized CSS
Usage
Run the generation script using $CLAUDE_PLUGIN_ROOT:
${CLAUDE_PLUGIN_ROOT}/skills/pdf-generation/scripts/generate-pdf.sh <input-dir> [output.pdf]
input-dir-- Directory containing the ordered markdown chaptersoutput.pdf-- Optional output path (defaults to<input-dir>/technical-overview.pdf)
Handling Missing CLAUDE_PLUGIN_ROOT
If $CLAUDE_PLUGIN_ROOT is not set (e.g., running outside a plugin context), locate the script manually:
# Fallback: find the script in the plugin installation directory
SCRIPT_PATH=$(find ~/.claude/plugins -path "*/pdf-generation/scripts/generate-pdf.sh" 2>/dev/null | head -1)
if [ -z "$SCRIPT_PATH" ]; then
echo "Error: generate-pdf.sh not found. Ensure the technical-writer plugin is installed."
exit 1
fi
"$SCRIPT_PATH" <input-dir> [output.pdf]
Expected Directory Structure
The input directory must contain ordered markdown files following this naming convention:
docs/technical-overview/
├── README.md # Title page and introduction (always first)
├── 00-getting-started.md # Numbered chapters in sequence
├── 01-architecture.md
├── 02-data-model.md
├── 03-api-reference.md
├── 04-deployment.md
├── appendix-a-glossary.md # Appendices after numbered chapters
└── appendix-b-faq.md
Expected output:
docs/technical-overview/
├── ... (source files unchanged)
└── technical-overview.pdf # Generated PDF (default output location)
The PDF includes:
- A title derived from the first
#heading inREADME.md(or the directory name as fallback) - A generated table of contents with depth 2 (h1 and h2 headings)
- Page numbers centered at the bottom of each page
- Chapter breaks (each h1 starts on a new page)
- Resolved inter-chapter links as internal anchors
Inter-Document Linking Requirements
For the PDF to have working internal links, the source markdown must follow these rules:
- Use relative links between chapters:
[architecture overview](01-architecture.md) - Section links with anchors work too:
[the store layer](03-data-layer.md#store) - Every chapter should have exactly one
#heading -- this is used to resolve link targets - The script warns about any
.mdlinks it cannot resolve
Common linking mistakes:
| Mistake | Fix |
|---|---|
Absolute paths (/docs/01-arch.md) |
Use relative paths (01-arch.md) |
Missing # heading in chapter |
Add exactly one h1 heading per chapter |
| Link to file not in input directory | Ensure all linked files are in the same directory |
Styling and Customization
The script embeds a print-optimized CSS stylesheet with sensible defaults:
- Page size: US Letter with 1-inch top/bottom margins
- Fonts: System font stack (Apple system fonts, Segoe UI, Helvetica, Arial)
- Code blocks: Light gray background with monospace font at 9pt
- Tables: Bordered with alternating row colors
- Chapter breaks: Each h1 heading starts on a new page
For detailed CSS customization options (fonts, colors, page sizes, themes), see ./references/css-customization.md.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| "Error: 'pandoc' is not installed" | Missing dependency | brew install pandoc |
| "Error: 'weasyprint' is not installed" | Missing dependency | uv tool install weasyprint && brew install pango |
Warning about unresolved .md links |
Chapter heading does not match filename pattern | Ensure each chapter has a # heading and the link target filename is correct |
| PDF renders but fonts look wrong | Missing system fonts | weasyprint uses system fonts; install desired fonts via Font Book |
| Empty PDF or no chapters found | Files not matching naming convention | Verify files follow README.md, 00-*.md through 99-*.md, appendix-*.md pattern |
CLAUDE_PLUGIN_ROOT is empty |
Running outside plugin context | Use the fallback script discovery method described above |
| Long code blocks overflow margins | Default CSS handles this | Verify overflow-wrap: break-word and white-space: pre-wrap in CSS |
Additional Resources
./references/css-customization.md-- Detailed CSS customization options for fonts, page sizes, colors, and themes./scripts/generate-pdf.sh-- The generation script (inspect for advanced modification)
Didn't find tool you were looking for?