Agent skill
Use when tasks involve reading, creating, reviewing, filling, or signing PDF/Word documents. Covers rendering (Poppler), generation (reportlab), extraction (pdfplumber, pypdf), form filling (pymupdf), and e-signature placement. Also trigger on: fill this form, sign this document, complete this PDF.
Install this agent skill to your Project
npx add-skill https://github.com/jjeremycai/claudekit/tree/main/skills/pdf
SKILL.md
PDF Skill
When to use
- Read or review PDF content where layout and visuals matter.
- Create PDFs programmatically with reliable formatting.
- Validate final rendering before delivery.
Workflow
- Prefer visual review: render PDF pages to PNGs and inspect them.
- Use
pdftoppmif available. - If unavailable, install Poppler or ask the user to review the output locally.
- Use
- Use
reportlabto generate PDFs when creating new documents. - Use
pdfplumber(orpypdf) for text extraction and quick checks; do not rely on it for layout fidelity. - After each meaningful update, re-render pages and verify alignment, spacing, and legibility.
Temp and output conventions
- Use
tmp/pdfs/for intermediate files; delete when done. - Write final artifacts under
output/pdf/when working in this repo. - Keep filenames stable and descriptive.
Dependencies (install if missing)
Prefer uv for dependency management.
Python packages:
uv pip install reportlab pdfplumber pypdf
If uv is unavailable:
python3 -m pip install reportlab pdfplumber pypdf
System tools (for rendering):
# macOS (Homebrew)
brew install poppler
# Ubuntu/Debian
sudo apt-get install -y poppler-utils
If installation isn't possible in this environment, tell the user which dependency is missing and how to install it locally.
Environment
No required environment variables.
Rendering command
pdftoppm -png $INPUT_PDF $OUTPUT_PREFIX
Quality expectations
- Maintain polished visual design: consistent typography, spacing, margins, and section hierarchy.
- Avoid rendering issues: clipped text, overlapping elements, broken tables, black squares, or unreadable glyphs.
- Charts, tables, and images must be sharp, aligned, and clearly labeled.
- Use ASCII hyphens only. Avoid U+2011 (non-breaking hyphen) and other Unicode dashes.
- Citations and references must be human-readable; never leave tool tokens or placeholder strings.
Final checks
- Do not deliver until the latest PNG inspection shows zero visual or formatting defects.
- Confirm headers/footers, page numbering, and section transitions look polished.
- Keep intermediate files organized or remove them after final approval.
Filling non-fillable PDFs
Use PyMuPDF (fitz) to insert text and images at precise positions on PDFs that lack interactive form fields.
Additional dependency
uv pip install pymupdf
Workflow
- Analyze structure — Extract text positions to map form layout:
import fitz
doc = fitz.open(pdf_path)
for page in doc:
text_dict = page.get_text("dict")
for block in text_dict["blocks"]:
if "lines" in block:
for line in block["lines"]:
for span in line["spans"]:
text = span["text"].strip()
if text:
bbox = span["bbox"] # (x0, y0, x1, y1)
print(f"'{text}' at y={bbox[1]:.1f} x={bbox[0]:.1f}")
-
Calculate fill positions — Form boxes are typically 18-25pt below their labels. PDF coordinates: origin top-left, 72 pts/inch, Y increases downward. US Letter = 612x792pt.
-
Insert text:
page.insert_text((x, y), "value", fontsize=11, color=(0, 0, 0))
- Insert images (signatures):
page.insert_image(fitz.Rect(x0, y0, x1, y1), filename="signature.png")
Use PNG with transparent background. Maintain aspect ratio.
Troubleshooting
| Issue | Fix |
|---|---|
| Text in wrong position | Re-run analysis, add 18-25pt to label y for input box |
| Text too large/small | Default 11pt; use 7-8pt for dense tables |
| Signature doesn't fit | Check aspect ratio matches rect proportions |
| Text overlaps content | Reduce fontsize, verify inserting in box not on label |
Why PyMuPDF over other libraries
PyPDF2/fillpdf only work with fillable forms. reportlab creates new PDFs (can't overlay). PyMuPDF inserts text/images at any position on existing PDFs.
Signing and filling documents
Complete workflow for filling forms and adding e-signatures to PDF and Word documents.
Scripts location: ~/.claude/scripts/sign-document/
Signature assets: ~/.claude/scripts/sign-document/assets/
Additional dependencies
pip install pypdf reportlab pdf2image python-docx cairosvg pillow
brew install poppler # Required for pdf2image on macOS
Decision tree
Input document?
├── PDF
│ ├── Has fillable fields? → Fillable PDF Workflow
│ └── No fillable fields? → Annotation-Based Workflow
└── Word (.docx) → Word Document Workflow
All workflows end with → Add Signature → Export as PDF
Step 1: Detect document type
file "$DOCUMENT_PATH"
Step 2: Check for fillable fields (PDF only)
python ~/.claude/scripts/sign-document/check_fillable_fields.py "$INPUT_PDF"
Fillable PDF workflow
# Extract field info
python ~/.claude/scripts/sign-document/extract_form_field_info.py "$INPUT_PDF" field_info.json
# Convert to images for visual reference
python ~/.claude/scripts/sign-document/convert_pdf_to_images.py "$INPUT_PDF" form_images/
# Fill the form (create field_values.json first)
python ~/.claude/scripts/sign-document/fill_fillable_fields.py "$INPUT_PDF" field_values.json filled.pdf
field_values.json format:
[
{"field_id": "last_name", "description": "Last name", "page": 1, "value": "Cai"},
{"field_id": "agree_checkbox", "description": "Agreement", "page": 2, "value": "/On"}
]
Value formats: Text → string, Checkbox → "/On" or "/Yes", Radio → value from radio_options, Dropdown → value from choice_options.
Annotation-based workflow (non-fillable PDFs)
# Convert to images, analyze layout, create fields.json
python ~/.claude/scripts/sign-document/convert_pdf_to_images.py "$INPUT_PDF" form_images/
# Validate bounding boxes
python ~/.claude/scripts/sign-document/check_bounding_boxes.py fields.json
python ~/.claude/scripts/sign-document/create_validation_image.py 1 fields.json form_images/page_1.png validation.png
# Fill
python ~/.claude/scripts/sign-document/fill_pdf_form_with_annotations.py "$INPUT_PDF" fields.json filled.pdf
Bounding box format: [left, top, right, bottom] in pixels. Label and entry boxes MUST NOT overlap.
Word document workflow
from docx import Document
doc = Document('template.docx')
replacements = {'{{name}}': 'Jeremy Cai', '{{date}}': 'January 13, 2026'}
for paragraph in doc.paragraphs:
for key, value in replacements.items():
if key in paragraph.text:
for run in paragraph.runs:
if key in run.text:
run.text = run.text.replace(key, value)
doc.save('filled.docx')
Add signature and export (final step)
python ~/.claude/scripts/sign-document/add_signature_and_export.py filled.pdf output.pdf
| Option | Default | Description |
|---|---|---|
--position |
bottom-right |
bottom-left, bottom-right, bottom-center |
--margin |
50 |
Points from page edge |
--width |
200 |
Signature width in points |
--page |
-1 (last) |
Page to sign (0-indexed, -1=last) |
--no-signature |
false | Convert to PDF without signature |
User data reference
When filling documents for Jeremy Cai:
- Full Name: Jeremy Cai
- DOB: April 21, 1995
- Height: 182cm / 6'0"
- Locations: Park City UT, Chicago IL, Los Angeles CA
- Occupation: Serial Entrepreneur & Angel Investor
- Companies: Fountain, Italic, Carbon (acquired by Perplexity), Blemish, Courtly
- Spouse: Katherine (Kati) Holland Cai (b. Mar 23, 1994)
- Parents: Emily Chen (b. Apr 16, 1963), James Cai (b. Nov 10, 1963)
- Sister: Jillian Cai (b. Mar 7, 1998)
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
himalaya
Use when the user asks to read, send, search, or manage email from the terminal. Himalaya is a CLI email client supporting IMAP, Maildir, Notmuch, SMTP, and Sendmail backends. Trigger on: email, inbox, send email, check mail, reply to email, forward email, email folders.
gh-fix-ci
Use when a user asks to debug or fix failing GitHub PR checks that run in GitHub Actions; use `gh` to inspect checks and logs, summarize failure context, draft a fix plan, and implement only after explicit approval. Treat external providers (for example Buildkite) as out of scope and report only the details URL.
yeet
Use only when the user explicitly asks to stage, commit, push, and open a GitHub pull request in one flow using the GitHub CLI (`gh`).
ashby
This skill should be used when the user asks about "Ashby API", "how to use Ashby tools", "Ashby authentication", "recruiting workflows", "candidate pipeline", "interview scheduling", "hiring process", "move candidate through pipeline", "schedule an interview", "manage applications", "track hiring progress", "source candidates", or "advance to next stage". Provides complete API reference and recruiting workflow guidance for the Ashby ATS integration.
skill-installer
Install Codex skills into $CODEX_HOME/skills from a curated list or a GitHub repo path. Use when a user asks to list installable skills, install a curated skill, or install a skill from another repo (including private repos).
skill-creator
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflows, or tool integrations.
Didn't find tool you were looking for?