PDF Documents (profy-pdf)
PDF work splits into two unrelated paths. Establish which one you are on first — everything else follows from that:Activation
profy-pdf is user_selectable: false — automatically available, nothing to tick.
contracts declares only skills: ["skills/"] and no tools. This plugin ships two skills: builtin/pdf for general processing and builtin/kami for typesetting, covered in its own section below.
Creation path: WeasyPrint is the only option
WeasyPrint’s approach is to write HTML + CSS and render it, so pagination and layout are handled by a CSS layout engine. You get declarative typesetting rather than manual placement.Headers, footers, and pagination
@page rules are a print-specific CSS capability — unusable in a browser, essential here:
counter(page) and counter(pages) are filled in by the renderer after pagination — precisely the thing a coordinate-based approach cannot give you, since it does not know the page count until it has already placed everything.
Design guidance
- Use CSS Grid / Flexbox for complex layouts such as cards and multi-column blocks
- Drive page size, margins, headers, and footers entirely from
@page - Control pagination with
page-break-before/page-break-after - For CJK text use
font-family: 'Noto Sans CJK SC', sans-serif(preinstalled in the sandbox) - For branded reports, set accent colours and use CSS background shapes
When not to use WeasyPrint
Manipulation path: command-line tools
pdftotext (poppler-utils)
-layout matters more than it looks: without it, multi-column layouts come out as interleaved nonsense, because the extractor follows the text stream rather than the visual columns.
qpdf
pdftk (if available)
Form handling
The skill ships a set of form scripts:extract_form_field_info.py, extract_form_structure.py, check_fillable_fields.py, fill_fillable_fields.py, fill_pdf_form_with_annotations.py, plus verification helpers check_bounding_boxes.py, create_validation_image.py, and convert_pdf_to_images.py.
The workflow is probe before filling. Form field naming varies arbitrarily between PDFs, so guessing field names is guaranteed to fail — and to fail silently, since writing to a non-existent field is not an error. Extract the real structure first.
OCR for scanned documents
Scanned PDFs have no text layer, sopdftotext returns nothing. These require pytesseract plus pdf2image to OCR into searchable text.
kami · 紙: the typesetting engine
builtin/kami is the second skill inside the pdf plugin, dedicated to deliverables that need to look designed: warm parchment canvas, ink-blue accent, serif-led hierarchy, tight editorial rhythm.
Nine document types
Selection runs through a decision tree rather than a question. Ask only when two rows genuinely both fit:
Landing Page produces no PDF. It is a screen-first interactive template with a gallery carousel, hero entrance animation, responsive breakpoints at 880px and 480px, and
prefers-reduced-motion support. The deliverable is a ready-to-host .html file.slides-weasy.html (WeasyPrint HTML → PDF); the PPTX-producing variant is used only when the user explicitly needs an editable PowerPoint file.
Fonts
The Chinese fonts are commercial. Before building Chinese documents, run the font recovery script once:
Handling vague feedback
When a user says “looks off”, “too cramped”, or “not elegant”, the skill forbids guessing and requires asking back with the current values. The value of this rule is that it converts a subjective argument into a parameter adjustment: “line-height is currently 1.6, should it go to 1.8?” resolves far faster than “let me try again”.Boundaries and failure modes
- Creation has exactly one supported route, WeasyPrint; coordinate-drawing libraries are explicitly prohibited.
- Scanned documents require OCR, or text extraction returns empty.
- Form fields must be probed first; guessing names fails silently.
- kami’s Chinese fonts are commercial and are not bundled with distributions — they are fetched by
ensure-fonts.sh. - Landing Page has no PDF output. Do not expect to export one.
Troubleshooting
Verify your output
- Convert to images and review every page:
convert_pdf_to_images.py. Layout accidents are invisible in the source. - For Chinese documents, search for box glyphs — the classic signature of a font that never loaded.
- On multi-page documents, jump to the last page and confirm that
of Nshows a real page count rather than literal text.
Related
Office documents overview
How the four document capabilities differ and when to use each
Presentations
When the deliverable is a deck rather than a document
Verified 2026-08-11. Sources:
services/agent-runtime/src/plugins/builtin/pdf/plugin.json, skills/pdf/SKILL.md, skills/kami/SKILL.md, skills/pdf/scripts/, skills/kami/scripts/ensure-fonts.sh.
