pdfnative-cli
v0.2.0
Published
Official CLI for pdfnative — render JSON to PDF, sign, inspect, and verify. Zero extra runtime dependencies.
Maintainers
Readme
pdfnative-cli
Official CLI for the pdfnative library — render JSON to PDF, apply digital signatures, verify them, and inspect PDF conformance, directly from the terminal. Zero extra runtime dependencies.
What's new in v0.2.0 — full coverage of the
pdfnativev1.0.5 surface: encryption, watermarks, headers/footers with placeholders, PDF/A-3 attachments, multilingual fonts, table-variant rendering, signing metadata + cert chains,inspect --verbose / --pages / --check, and a brand-newverifycommand. 100 % backward-compatible with v0.1.0 — see release notes.
Highlights
render— pipe a JSON document into a production-ready PDF. Encryption (AES-128/256), watermarks (text + image), page templates, PDF/A archival, multilingual fonts, streaming, and a hybridflags + --layout file.jsonmodel for the fullPdfLayoutOptionssurface.sign— CMS/PKCS#7 digital signatures with full metadata (--reason,--name,--location,--contact,--signing-time) and intermediate CA chains via--cert-chain(repeatable). Keys loaded from env vars or files; never logged.inspect— PDF version, page count, encryption, PDF/A conformance, signature count, metadata.--verbose,--pages, and--check pdfa|signed|encryptedfor CI assertions.verify(new in v0.2.0) — verify integrity, certificate chains, and trust roots of every CMS/PKCS#7 signature embedded in a PDF. JSON & text output,--strictmode.- Zero extra dependencies —
pdfnativeis the sole runtime dependency. - Stdin / stdout by default — every command is shell-pipeline friendly.
- Secret-safe — signing keys, certs, encryption passwords never appear in error
output or stderr. PEM material redacted; layout-file
attachments[].datainjection blocked. - ESM-first, TypeScript strict — built with tsup, typed declarations included.
- NPM provenance — signed builds via GitHub Actions OIDC.
Supported Features
| Feature | Status | Notes |
|---------|--------|-------|
| Commands | | |
| render JSON → PDF | ✅ | Streaming, hybrid layout model, multilingual fonts |
| sign digital signatures | ✅ | RSA (CMS/PKCS#7), metadata fields, cert chains |
| inspect PDF metadata | ✅ | --verbose, --pages, --check pdfa\|signed\|encrypted |
| verify signature verification (v0.2.0) | ✅ | Integrity + chain + trust; --strict, --trust |
| Document Blocks | | |
| Headings, paragraphs, lists | ✅ | Full text styling support |
| Tables | ✅ | Headers, rows, multi-page |
| Barcodes | ✅ | QR, Code 128, EAN-13, Data Matrix, PDF417 |
| Hyperlinks | ✅ | URL validation, blue underlined text |
| Form fields | ✅ | Text, checkbox, radio, dropdown, listbox |
| Page breaks, spacers | ✅ | Explicit pagination control |
| Table of contents | ✅ | Auto-generated with /GoTo links |
| Advanced Layouts (v0.2.0) | | |
| PDF/A archival (1b, 2b, 2u, 3b) | ✅ | --tagged pdfa<level> (preferred) or --conformance (deprecated) |
| Streaming output | ✅ | --stream for large documents |
| Compression | ✅ | --compress flag |
| Encryption (AES-128/256) | ✅ | --encrypt-* flags + env-var precedence |
| Watermarks (text + image) | ✅ | --watermark-text, --watermark-image, --watermark-position |
| Headers / footers with placeholders | ✅ | --header-{l,c,r}, --footer-{l,c,r}, {page}/{pages}/{date}/{title} |
| Custom page sizes | ✅ | --page-size A4\|Letter\|… or WxH in points |
| Custom margins | ✅ | --margin <N> or --margin <t,r,b,l> |
| PDF/A-3 attachments | ✅ | --attachment <path>:<mime>:<rel>:<desc> (repeatable) |
| Multilingual fonts | ✅ | --lang th,ja,ar (requires registerFontLoader() in wrapper; Latin built-in) |
| Table-centric variant (PdfParams) | ✅ | --variant table |
| Full PdfLayoutOptions | ✅ | --layout <file.json> |
| Signing (v0.2.0) | | |
| RSA signatures (rsa-sha256) | ✅ | Default algorithm |
| ECDSA signatures | ⚠️ | --algorithm ecdsa-sha256 parsed; stub error pending pdfnative parseEcPrivateKey (v0.3.0) |
| Signature metadata | ✅ | --reason, --name, --location, --contact, --signing-time |
| Cert chains (intermediate CAs) | ✅ | --cert-chain <pem> (repeatable) or PDFNATIVE_SIGN_CHAIN env |
| Verification (v0.2.0) | | |
| Byte-range integrity (SHA-256) | ✅ | Recomputed and compared with CMS messageDigest attribute |
| Certificate chain verification | ✅ | Via pdfnative verifyCertSignature |
| Trust roots | ✅ | --trust <root.pem> (repeatable) + self-signed acceptance |
| Full CMS signature-value | ⚠️ | Deferred to v0.3.0 (pending pdfnative API) |
| OCSP / CRL revocation | ⚠️ | Deferred to v0.3.0+ |
| RFC 3161 timestamps | ⚠️ | Deferred to v0.3.0+ |
Note: features marked ⚠️ are tracked in ROADMAP.md. Everything else works today.
Installation
npm install --global pdfnative-cliOr run without installing:
npx pdfnative-cli render --input doc.json --output report.pdfRequirements: Node.js ≥ 20 | Bun | Deno (node dist/cli.cjs)
Documentation
- 📘 Quick Start (below) — Get rendering in 5 minutes
- 🏛️ KNOWLEDGE_BASE.md — Full CLI reference, architecture, integration patterns
- 📚 samples/README.md — 22 sample files organized by feature
- 🔧 pdfnative library — Underlying PDF engine docs
- ❓ FAQ — Common questions & troubleshooting
Quick Start
Render a PDF from JSON
# From a file
pdfnative render --input document.json --output report.pdf
# From stdin
cat document.json | pdfnative render --output report.pdf
# Streaming (large documents)
pdfnative render --input big-doc.json --output report.pdf --stream
# PDF/A conformance
pdfnative render --input document.json --output archived.pdf --conformance 2bdocument.json is a DocumentParams object:
{
"title": "Monthly Report",
"blocks": [
{ "type": "heading", "text": "Monthly Report", "level": 1 },
{ "type": "paragraph", "text": "Summary for April 2026." },
{ "type": "list", "style": "bullet", "items": ["Revenue: +18%", "NPS: 72"] }
],
"footerText": "Confidential",
"metadata": { "author": "Finance Team", "subject": "April 2026 Report" }
}Sign a PDF
# Keys from environment variables (recommended for CI/CD)
export PDFNATIVE_SIGN_KEY="$(cat private.pem)"
export PDFNATIVE_SIGN_CERT="$(cat cert.pem)"
pdfnative sign --input document.pdf --output signed.pdf
# Keys from files
pdfnative sign --input document.pdf --output signed.pdf \
--key private.pem --cert cert.pemInspect a PDF
# JSON output (default)
pdfnative inspect --input report.pdf
# Human-readable
pdfnative inspect --input report.pdf --format text
# From stdin
cat report.pdf | pdfnative inspectExample output:
{
"version": "1.7",
"pageCount": 3,
"encrypted": false,
"pdfaConformance": "2b",
"signatures": 1,
"metadata": {
"title": "Monthly Report",
"author": "Nizoka",
"creationDate": "2026-04-27T12:00:00+00:00"
}
}Examples
Ready-to-run examples are in samples/, organized by feature category:
| Category | Examples | Description |
|----------|----------|-------------|
| render/document/ | 5 files | Minimal, report, all-blocks reference, invoice, technical spec |
| render/table/ | 2 files | Project status, financial summary |
| render/barcode/ | 3 files | QR code, Code 128 shipping label, EAN-13 product |
| render/form/ | 2 files | Contact form, survey |
| render/toc/ | 1 file | Document with auto-generated table of contents |
| render/link/ | 1 file | Resource directory with hyperlinks |
| render/watermark/ | 2 files | Draft watermark, confidential watermark |
| render/layout/ | 3 files | US Letter, A5 portrait, A4 landscape |
| render/pdfa/ | 3 files | PDF/A-1b, PDF/A-2b, PDF/A-3b archival conformance |
| sign/ | 2 scripts | Digital signature (Bash + PowerShell) |
| inspect/ | 4 scripts | JSON & text inspection (Bash + PowerShell) |
| streaming/ | 1 script | 200-section document via streaming render |
Render all samples at once:
node samples/run-all.jsSee samples/README.md for full descriptions, block type reference, and integration patterns (GitHub Actions, Docker, TypeScript).
Command Reference
pdfnative render
| Flag | Default | Description |
|------|---------|-------------|
| --input <file> | stdin | Path to a JSON file (DocumentParams or PdfParams if --variant table) |
| --output <file> | stdout | Output PDF path |
| --stream | false | Use streaming output (AsyncGenerator) |
| --variant <kind> | document | document (default) or table (selects buildPDFBytes) |
| --layout <file.json> | — | Load a Partial<PdfLayoutOptions> (CLI flags override) |
| --page-size <size> | from layout file or pdfnative default | Named (a4, letter, legal, a3, tabloid, a5) or WxH in points |
| --margin <N> or --margin <t,r,b,l> | from layout / default | Page margins in points |
| --compress | false | Enable FlateDecode compression |
| --tagged <level> | none | PDF/A: none, pdfa1b, pdfa2b, pdfa2u, pdfa3b |
| --conformance <1b\|2b\|3b> | — | Deprecated — use --tagged pdfa<level> |
| --watermark-text <s> / --watermark-image <path> | — | Text or image watermark |
| --watermark-opacity <0-1> / --angle <deg> / --color <#hex> / --font-size <pt> | — | Watermark styling |
| --watermark-position background\|foreground | background | Render order |
| --header-{left,center,right} <tpl> | — | Header template; placeholders {page}, {pages}, {date}, {title} |
| --footer-{left,center,right} <tpl> | — | Footer template; same placeholders |
| --encrypt-owner-pass <s> | $PDFNATIVE_ENCRYPT_OWNER_PASS | Owner password (required for any --encrypt-*) |
| --encrypt-user-pass <s> | $PDFNATIVE_ENCRYPT_USER_PASS | Optional user password |
| --encrypt-algorithm aes128\|aes256 | aes128 | Encryption algorithm |
| --encrypt-permissions <list> | all denied | Comma list: print,copy,modify,extractText |
| --attachment <path>[:mime[:rel[:desc]]] (repeatable) | — | PDF/A-3 file attachment |
| --lang <code,code> | — | Activate registered font loaders for non-Latin scripts (th, ja, ar, …); Latin is built-in |
See samples/render/ for a working example of every category.
pdfnative sign
| Flag | Default | Description |
|------|---------|-------------|
| --input <file> | — (required) | Path to the input PDF |
| --output <file> | stdout | Output signed PDF path |
| --key <file> | $PDFNATIVE_SIGN_KEY | Path to PEM private key (env var takes precedence) |
| --cert <file> | $PDFNATIVE_SIGN_CERT | Path to PEM certificate (env var takes precedence) |
| --cert-chain <file> (repeatable) | $PDFNATIVE_SIGN_CHAIN | Intermediate CA PEMs |
| --algorithm rsa-sha256\|ecdsa-sha256 | rsa-sha256 | Signature algorithm. ECDSA stubbed in v0.2.0; tracked for v0.3.0. |
| --reason <s> | — | Reason for signing (PDF metadata) |
| --name <s> | — | Signer name (PDF metadata) |
| --location <s> | — | Signing location (PDF metadata) |
| --contact <s> | — | Signer contact (PDF metadata) |
| --signing-time <ISO 8601> | now | Explicit signing timestamp |
pdfnative inspect
| Flag | Default | Description |
|------|---------|-------------|
| --input <file> | stdin | Path to the PDF to inspect |
| --output <file> | stdout | Output report path |
| --format json\|text | json | Output format |
| --verbose | false | Add trailer keys, catalog keys, object count, XMP |
| --pages | false | Add per-page metadata array |
| --check pdfa\|signed\|encrypted (repeatable) | — | CI-friendly assertion; sets exit code (0 = pass, 1 = fail) |
pdfnative verify (new in v0.2.0)
| Flag | Default | Description |
|------|---------|-------------|
| --input <file> | stdin | Path to the (possibly signed) PDF |
| --format json\|text | json | Output format |
| --strict | false | Exit 1 on any failure or zero signatures (CI-friendly) |
| --trust <root.pem> (repeatable) | self-signed only | Trusted root certificates (PEM) |
Scope (v0.2.0): integrity (byte-range SHA-256) + certificate chain signatures + trust evaluation. Full CMS-signature-value verification, OCSP/CRL revocation, and RFC 3161 timestamp validation are deferred — see ROADMAP.md.
Security
- Signing keys are never logged — not in error messages, not in debug output.
- Path traversal protection — all file path arguments are validated against
../sequences. - JSON size cap — input is capped at 50 MB before parsing to prevent memory exhaustion.
- Signed builds with NPM provenance — verify at npmjs.com or with
npm audit signatures.
See SECURITY.md for the full security policy and vulnerability disclosure procedure.
Getting Help
Have a question?
- 📖 Check the FAQ first
- 🔍 Search the samples:
grep -r "your-keyword" samples/ - 📚 Read KNOWLEDGE_BASE.md for technical details
- 💬 Open a discussion: GitHub Discussions
Found a bug?
- 🐛 Open an issue: GitHub Issues
- 🔐 Security issue? See SECURITY.md for responsible disclosure
Want to contribute?
- 🤝 See CONTRIBUTING.md
- 📝 All PRs add value — tests, docs, translations, samples
Related Projects
pdfnative— the core PDF generation librarypdfnative-mcp— Model Context Protocol server for AI clients- pdfnative.dev — documentation, live demos, benchmarks
Citation
If you use pdfnative-cli in research or academic pipelines, please cite it:
@software{pdfnative_cli_2026,
title = {pdfnative-cli: Official CLI for the pdfnative PDF generation library},
author = {Nizoka},
year = {2026},
url = {https://github.com/Nizoka/pdfnative-cli},
license = {MIT}
}See CITATION.cff for the full metadata (auto-detected by GitHub and Zenodo).
License
MIT — see LICENSE.
