PDF Generation pack
Claude Skill
Form Filler
Fills a fillable PDF form (W-9, expense, intake) from structured data. Handles checkboxes and multi-page.
What it does
Given a fillable PDF (AcroForm or XFA) and structured input data, this skill maps fields, fills them, handles checkboxes and radio groups, drops a signature placeholder image, and outputs a flattened PDF ready to submit. Audits unfilled required fields.
When to use
- ✓You have a recurring form (W-9, vendor onboarding, expense report) and the same data each time
- ✓Bulk-filling forms for many recipients (e.g., 50 W-9s for contractors)
- ✓You're sick of clicking through 30 fields in a form every month
When not to use
- ✗Form is a scanned image, not a fillable PDF — needs OCR + overlay, different problem
- ✗Form requires e-signature with audit trail — use DocuSign / HelloSign / Dropbox Sign
- ✗Form involves regulated submission (tax, healthcare) where the agency wants their portal
Install
Download the .zip, then unzip into your Claude skills folder.
mkdir -p ~/.claude/skills
unzip ~/Downloads/form-filler.zip -d ~/.claude/skills/
# Restart Claude Code session.
# Skill is now available — Claude will use it when relevant.SKILL.md
SKILL.md
---
name: form-filler
description: Use when filling a fillable PDF form (W-9, expense form, intake form, vendor setup) from structured data. Triggers on "fill this PDF form", "fill out the W-9", "auto-fill this form".
---
# Form Filler
Fill AcroForm / XFA PDF fields from structured input. Output a flattened PDF (no editable fields) ready to send. Most form-filling failures are field-name mismatches and forgotten checkboxes — handle both deliberately.
## Required inputs
1. **The fillable PDF** — must be a real fillable PDF, not a scanned image
2. **Structured data** — JSON / CSV / dict mapping form field names to values
3. **Signature handling** — placeholder image, "wet sign later" leave-blank, or skip
4. **Output mode** — flatten (recommended) or keep editable
If the PDF is a scanned image, stop and tell the user: "This form isn't fillable. Either get a fillable version or use OCR + manual placement (different skill)."
## Approach
**Python**: `pypdf` (formerly PyPDF2) for AcroForm via `update_page_form_field_values`, then flatten. For complex forms with XFA, `pdfrw` or the commercial `pikepdf` handle more edge cases.
**Node**: `pdf-lib` is the cleanest API. Supports field detection, filling, and flattening.
**CLI**: `pdftk` (or `pdftk-java`) for batch — `pdftk input.pdf fill_form data.fdf output filled.pdf flatten`. Reliable for old IRS-style forms.
**XFA forms** (older Adobe LiveCycle, e.g. some government forms): special-cased. Most libraries can't fill these. Fallback: open in Adobe Reader → fill manually OR convert XFA → AcroForm via Adobe (no good open-source path).
## Process
1. **Discover field names**: enumerate form fields from the PDF and print the list. Don't guess names from labels — labels and field names often diverge.
2. **Map input to fields**: produce a mapping table; flag any input keys with no matching field, and any required fields with no matching input.
3. **Fill**: text fields take strings; checkboxes take `/Yes` or the field's actual export value (often `/On`); radio groups take the group's selected option name.
4. **Signature**: if requested, embed a PNG of the signature on the signature field's coordinates. If "wet sign later," leave blank.
5. **Flatten**: convert filled fields to static text so the recipient can't edit. Skip flattening only if explicitly requested.
6. **Verify**: re-open the output and read field values back to confirm. Print an audit.
## Style guidance
- **Don't change page geometry** — never resize, rotate, or re-render the original PDF pages
- **Match the form's font** if visible. Most government forms use Helvetica or Arial — `pypdf` defaults usually work.
- **Field overflow**: long text in a small field. Options: shrink font, allow multi-line if the field permits, or flag the value as too long. Don't silently truncate.
- **Date formatting**: match the form's expected format (US: MM/DD/YYYY, EU: DD/MM/YYYY). Read the form's hint text or ask.
## Checkboxes and radios
The #1 form-filling bug: a checkbox needs the *export value*, not `true`. Inspect the field with your library:
```python
field = reader.get_form_text_fields() # text only
fields = reader.get_fields() # all, including checkbox export values
# A checkbox might expect "/Yes" or "/1" or "/On" — varies per form
```
For radio groups, set the group field name to the option's name. Setting the option directly silently fails.
## Common pitfalls
- **Field name mismatches**: `Customer Name` vs `customer_name` vs `CustomerName1` — case-sensitive and exact. Always discover first.
- **Required fields silently skipped**: some forms require fields the user didn't supply. Fail loudly: list them in the audit.
- **Checkbox not toggling**: wrong export value (see above). Inspect, don't guess.
- **Forgotten flatten**: editable PDFs sent to the IRS get rejected. Always flatten unless told not to.
- **Multi-page forms**: fields on page 2 share names with page 1 (`name_2`). Don't assume one field per logical input.
- **Encrypted PDFs**: some forms ship password-protected. Decrypt first, or fail with a clear message.
## Output
The flattened PDF + a field audit:
```
Form: w9.pdf
Fields filled: 12 / 14
Skipped: 2 (signature, signature_date — leave-blank requested)
Required missing: 0
Output: w9_filled_acme_2026-04-29.pdf (flattened)
```
For batch fills, output one PDF per input row + a CSV log of which row produced which file and any failures.
Example prompts
Once installed, try these prompts in Claude:
- Fill this W-9 with my LLC info: [data]. Output a flat PDF.
- I have 30 contractor W-9s to send. Here's the CSV. Pre-fill the company info on each.