pdf — professional PDFs

SkillDocs & knowledge

The pdf skill lets an agent create and edit PDF files to a professional standard. It can generate documents from content, fill and create AcroForm fields, merge, split, rotate, stamp, watermark, encrypt, and extract text. It also supports vector layouts and custom fonts, including CJK and Unicode.

Then ask your AI: use the pdf skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Confirm the agent has the pdf skill available and can run its make_document and edit_document tools.

What your AI can do with it

  • Generate a simple content PDF with title, headings, paragraphs, and an image
  • Fill existing AcroForm fields by name, including text, checkbox, and dropdown
  • Merge, split, add, or remove pages in an existing PDF
  • Stamp text or add a 45 degree translucent watermark
  • Create form fields, draw vector layouts, and embed custom fonts with @cantoo/pdf-lib
  • Encrypt PDFs and extract text using unpdf

Getting started

  1. Confirm the agent has the pdf skill available and can run its make_document and edit_document tools.
  2. For simple content PDFs, call make_document with format set to pdf and provide title, pages, headings, paragraphs, and any image path.
  3. For existing PDFs, call edit_document to fill form fields, merge, split, stamp, or watermark.
  4. For form-field creation, vector drawing, custom fonts, or encryption, write a gen.cjs script using @cantoo/pdf-lib and run it with brigade exec-node.
  5. Reopen the finished PDF and read back form values to verify the output before delivering it.

What this skill tells your AI

The instructions your AI receives, as published by spinabot/brigade in skills/pdf/SKILL.md and read by Ahel’s review.

NeedPath
Simple content PDF (title, headings, paragraphs, image)Path 1 — make_document tool
Fill an existing form, merge/split/stamp/watermarkPath 2 — edit_document tool
Form-field CREATION, vector drawing, embedded fonts (bold/CJK), precise layout, encryption, page surgeryPath 3 — script @cantoo/pdf-lib via brigade exec-node
Pixel-perfect, brand-styled layout from HTML/CSSPath 4 — HTML→PDF (optional binary)

Note: PDF is a final format with no reflow engine. If the recipient must edit, deliver the editable source (.docx/.xlsx) and the PDF.


Path 1 — quick content PDF (make_document tool)

make_document(format="pdf", content={ title, pages:[{ heading, paragraphs, image:{path} }] })

Flow layout, US-Letter, single column, word-wrapped. Good for reports/summaries/letters. For forms, precise layout, or custom fonts → Path 3.

Path 2 — edit an existing PDF (edit_document tool)

  • fill_form {fields} — fill existing AcroForm fields by name (text/checkbox/dropdown).
  • merge {pdfs} / add_pages {pdfs} · split {pages} · remove_pages {pages}.
  • stamp {text} · watermark {text} (45° translucent).

Form decision: first detect whether the PDF has real fillable fields. If it does → fill them (clean, type-validated). If it's a flat/scanned form (no fields) → you must draw text at coordinates instead (Path 3, annotations) — never assume fields exist.

Path 3 — full power: script @cantoo/pdf-lib

Brigade bundles @cantoo/pdf-lib (a maintained pdf-lib fork — note the scoped name) plus @pdf-lib/fontkit (custom-font embedding) and unpdf (text extraction). write a gen.cjs, run brigade exec-node gen.cjs:

// gen.cjs — illustrative
const fs = require("node:fs");
const { PDFDocument, StandardFonts, rgb } = require("@cantoo/pdf-lib");

(async () => {
  const pdf = await PDFDocument.create();

  // embed a custom font (real bold / CJK / Unicode) — requires fontkit
  // const fontkit = require("@pdf-lib/fontkit"); pdf.registerFontkit(fontkit);
  // const font = await pdf.embedFont(fs.readFileSync("Brand-Bold.ttf"));
  const font = await pdf.embedFont(StandardFonts.HelveticaBold);

  const page = pdf.addPage([612, 792]);                 // US Letter; origin is BOTTOM-LEFT, y-up
  page.drawText("Invoice", { x: 54, y: 720, size: 22, font, color: rgb(0.1, 0.1, 0.1) });
  page.drawRectangle({ x: 54, y: 700, width: 504, height: 1, color: rgb(0.8, 0.8, 0.8) }); // vector rule

  // CREATE fillable form fields
  const form = pdf.getForm();
  const name = form.createTextField("client.name");
  name.addToPage(page, { x: 120, y: 640, width: 300, height: 18 });
  const agree = form.createCheckBox("agree");
  agree.addToPage(page, { x: 54, y: 600, width: 14, height: 14 });
  // form.flatten();                                     // bake fields into static content if no further filling

  fs.writeFileSync(process.argv[2] || "out.pdf", await pdf.save());
  console.log("wrote");
})();

@cantoo/pdf-lib covers: draw text/lines/rects/ellipses/SVG paths/images; embed custom TTF/OTF fonts (subset, full Unicode); create AND fill AcroForm text/checkbox/radio/dropdown/option-list fields; flatten; copy/merge/split/rotate pages; metadata; password encryption (the reason this fork is bundled). Extract text/structure with unpdf.

Coordinate gotcha: pdf-lib origin is bottom-left, y-up. If you author field positions from a top-left image/spec, convert: y_pdf = pageHeight - y_top - height. One coordinate convention per script.

Path 4 — pixel-perfect / branded PDF from HTML+CSS (optional)

pdf-lib has no HTML/CSS layout engine — for a designed, brand-styled document, render HTML→PDF. Use whatever is present (detect first):

command -v soffice >/dev/null 2>&1 && soffice --headless --convert-to pdf brand.html      # LibreOffice route

A headless browser (Puppeteer/Playwright page.pdf()) is the higher-fidelity alternative if installed. Prefer Path 1/3 unless the brand design genuinely requires CSS.

Conventions

  • Use real AcroForm fields when filling a fillable PDF; only fall back to drawn-text annotations for flat/scanned forms.
  • Embed a font for anything beyond basic Latin — standard PDF fonts lack bold-as-a-face and all CJK/emoji (missing glyphs render as boxes).
  • Keep ≥0.5" margins; align to a grid; don't rely on text reflowing (there's no engine — you place it).

Verify (required)

Confirm the output exists and opens. For filled/created forms, re-open and read back the field values (or render to an image with soffice/a viewer and look at placement) before declaring done — never fill or place blind.

Signals

GitHub stars
11k
Forks
70
Last commit
Oct 2026

Questions

Can it create and fill AcroForm fields?
Yes. It can create AcroForm fields including text, checkbox, radio, and dropdown, and it can fill existing fields by name. If a form is flat or scanned with no fields, text must be drawn at coordinates instead.
Can it embed custom fonts, including CJK or Unicode?
Yes. Using @cantoo/pdf-lib with @pdf-lib/fontkit, it can embed custom fonts such as real bold or CJK and Unicode fonts.
Advanced
Item type
skill
Key
pdf-spinabot
Source
github.com/spinabot/brigade