Skip to main content

PDF Toolkit

Documents skill, available on Zeplik

PDF Toolkit is a ready-to-run documents skill on Zeplik. You do it in the sandbox and never hand the user a script. Ask in plain language and Zeplik applies the skill's method for you inside the conversation, on whichever AI model you prefer.

The PDF Toolkit skill loads automatically when your request matches it, or you can invoke it directly by typing /pdf-processing in any chat. It works with attachments, connectors, and any model that supports the task, so you get the same expert method every time without setting anything up.

What the PDF Toolkit skill can do

Try these prompts on Zeplik

Pick a prompt to open it in the Zeplik app. If you are not signed in yet, your prompt is waiting for you the moment you do.

How the PDF Toolkit skill works

PDF Operations (perform, do not advise)

You OPERATE on PDFs directly. Every PDF the user uploaded in this conversation is already staged in the sandbox working directory under its (sanitized) filename: characters outside A-Za-z0-9._- become _, so Q3 report (final).pdf is staged as Q3_report__final_.pdf. List the directory if unsure:

import os; print(sorted(os.listdir(".")))

The canonical workflow for EVERY operation:

  1. code_execution (python) - operate on the staged file with the preinstalled toolchain: pymupdf (fitz), pikepdf, pypdf, pdfplumber, pytesseract (+ tesseract binary), reportlab, Pillow, pandas, openpyxl.
  2. Verify your own output in the same run (page count, non-zero size, a text probe) and print the evidence.
  3. export_file with the output path to hand the user a download card.

The sandbox has NO internet: never try pip install; everything you need is preinstalled. Never paste a script for the user to run locally, never paste raw PDF bytes into chat, and never claim an operation is impossible before trying fitz AND pikepdf.

Recipes (all verified against the preinstalled versions)

Inspect / validate (always do this first on "is this file ok?" or any failure)

import fitz, pikepdf
report = {}
try:
    doc = fitz.open("input.pdf")
    report.update(pages=doc.page_count, encrypted=doc.needs_pass,
                  meta=doc.metadata, toc_entries=len(doc.get_toc()))
    text_pages = sum(1 for p in doc if p.get_text().strip())
    report["pages_with_text"] = text_pages   # 0 => scanned, needs OCR
except Exception as e:
    report["fitz_error"] = str(e)
print(report)

Repair a damaged/corrupted PDF

pikepdf (qpdf) recovers broken xref tables, bad object streams, and truncated trailers; fitz's loader is also tolerant. Try in this order, then re-validate:

import pikepdf
with pikepdf.open("broken.pdf") as pdf:      # qpdf auto-recovers on open
    pdf.save("repaired.pdf")                 # rewritten with a clean xref
# fallback if pikepdf cannot open it:
# import fitz; d = fitz.open("broken.pdf"); d.save("repaired.pdf", garbage=4, clean=True)

Encrypted with a user password: ask the user for the password, then pikepdf.open("f.pdf", password=...) and save an unlocked copy. Never guess or brute-force; if they do not have it, say the file cannot be opened.

Split / extract a page range (user page numbers are 1-based; fitz is 0-based)

import fitz
src = fitz.open("input.pdf")
out = fitz.open()
out.insert_pdf(src, from_page=9, to_page=19)   # pages 10-20 inclusive
out.save("pages-10-20.pdf")

Merge (preserve the user's stated order)

import fitz
out = fitz.open()
for name in ["a.pdf", "b.pdf", "c.pdf"]:
    with fitz.open(name) as part: out.insert_pdf(part)
out.save("merged.pdf")

Crop (trim margins or to a region; box in points, origin top-left)

import fitz
doc = fitz.open("input.pdf")
for page in doc:
    r = page.rect
    page.set_cropbox(fitz.Rect(r.x0+36, r.y0+36, r.x1-36, r.y1-36))  # 0.5in off each side
doc.save("cropped.pdf")

Rotate / reorder / delete pages

import fitz
doc = fitz.open("input.pdf")
doc[0].set_rotation(90)                 # rotate page 1
doc.select([2, 0, 1])                   # keep+reorder: pages 3,1,2 (deletes the rest)
doc.save("reordered.pdf")

Compress

import pikepdf
with pikepdf.open("input.pdf") as pdf:
    pdf.save("compressed.pdf", compress_streams=True,
             recompress_flate=True,
             object_stream_mode=pikepdf.ObjectStreamMode.generate)

Report before/after sizes. If images dominate, downsample via fitz (rebuild pages with page.get_pixmap(dpi=110) into a new doc) and say the trade-off.

Extract tables (deliver as .xlsx or .csv, not ascii art)

import pdfplumber, pandas as pd
frames = []
with pdfplumber.open("report.pdf") as pdf:
    for i, page in enumerate(pdf.pages, 1):
        for t in page.extract_tables():
            df = pd.DataFrame(t[1:], columns=t[0])
            df.insert(0, "page", i); frames.append(df)
pd.concat(frames).to_excel("tables.xlsx", index=False)

fitz page.find_tables() is the fallback when pdfplumber finds none.

Extract images

import fitz
doc = fitz.open("input.pdf")
n = 0
for page in doc:
    for xref, *_ in page.get_images(full=True):
        pix = fitz.Pixmap(doc, xref)
        if pix.n > 4: pix = fitz.Pixmap(fitz.csRGB, pix)
        n += 1; pix.save(f"img-{n:03d}.png")
print(n, "images")

Zip them (shutil.make_archive) and export one archive when there are many.

OCR a scanned PDF (also the path to a searchable copy)

import fitz, pytesseract
from PIL import Image
import io
doc = fitz.open("scan.pdf")
for i, page in enumerate(doc, 1):
    pix = page.get_pixmap(dpi=200)
    img = Image.open(io.BytesIO(pix.tobytes("png")))
    print(f"### Page {i}/{doc.page_count}\n{pytesseract.image_to_string(img)}")

OCR output is imperfect: say so, and quote OCR text as "the scan reads".

Generate a styled PDF document (house template)

import pathlib, subprocess
md = """# Findings

Body text in GitHub-flavored Markdown. Tables, lists, fenced code and
images (SVG charts) all render; a blockquote becomes a key-finding callout.
"""
pathlib.Path("doc.md").write_text(md)
print(subprocess.run(["zeplik-doc", "doc.md", "-o", "report.pdf",
                      "--title", "Quarterly Findings",
                      "--author", "Zeplik", "--date", "July 25, 2026"],
                     capture_output=True, text=True).stdout)

zeplik-doc compiles the Markdown with the Zeplik house template (cover page, dot-leader contents, running headers, "Page X of Y", styled tables, callouts) and verifies its own output. Charts: matplotlib + plt.style.use('/usr/local/share/zeplik/zeplik.mplstyle'), save as .svg, reference from the Markdown as an image. Prefer this over hand-built reportlab for ANY document-like deliverable; reportlab remains for edits of existing PDFs and exotic layouts. Optional visual check: pdftoppm -png -r 80 -f 1 -l 2 report.pdf page then open the PNGs.

Grounding rules (non-negotiable)

  • Answers about a PDF's contents cite the page: "(p. 12)". If the fact is not in the extracted/OCR text you actually saw, say it is not present - never infer numbers, dates, names, or clause text.
  • After every operation, verify the artifact (open it again, print page count and byte size) BEFORE export_file. If verification fails, fix it or report honestly; never export a file you did not verify.
  • Multi-step jobs (e.g. "repair, then split, then compress") run as one pipeline; deliver only the final file(s) unless the user asked for intermediates.

Zeplik output presentation

Lead with the deliverable: the download card(s) plus one line of what was done ("Repaired the xref table and split pages 10-20; 11 pages, 412 KB"). Keep process commentary to a single short line; no tool-by-tool narration. If multiple files were produced, end with a compact list, one line of purpose each.

How to use the PDF Toolkit skill

  1. Sign in to Zeplik

    Create a free Zeplik account or sign in. New accounts start with free credits, so you can try the PDF Toolkit skill right away.

  2. Describe your documents task

    Ask in plain language, or type /pdf-processing to invoke the skill directly. Zeplik recognizes the PDF Toolkit skill and applies its method.

  3. Review and refine the result

    Zeplik returns a clear, structured answer. Ask follow-ups in the same chat to refine it or take the next step.

Source and credit

Author
zeplik (operational rewrite; originally adapted from davila7/claude-code-templates, MIT)
License
MIT

Adapted from the open-source davila7/claude-code-templates project and tuned to run natively on Zeplik. View source on GitHub.

Frequently asked questions

What is the PDF Toolkit skill?
PDF Toolkit is a ready-to-run documents skill on Zeplik. You do it in the sandbox and never hand the user a script. Ask in plain language and Zeplik applies the skill's method for you inside the conversation, on whichever AI model you prefer.
How do I use PDF Toolkit on Zeplik?
Sign in to Zeplik and ask in plain language, or type /pdf-processing in any chat to invoke it directly. The skill applies its method and returns a result you can refine in the same conversation.
Which AI model does the PDF Toolkit skill use?
Any model you choose. Zeplik works across every model in one chat, so the PDF Toolkit skill runs on your preferred model for the task.
Where does the PDF Toolkit skill come from?
The PDF Toolkit skill is adapted from the open-source davila7/claude-code-templates project (MIT) and tuned to run natively on Zeplik. The original source is linked on this page.
How much does the PDF Toolkit skill cost?
Using the skill is free to start. You only spend Zeplik credits when the assistant runs, and new accounts begin with free credits.

Related documents skills

More on Zeplik

Try PDF Toolkit on Zeplik

Every model, one chat. Bring the PDF Toolkit skill into your next conversation and let the assistant do the work.

Browse all skills
PDF Toolkit - Documents skill for Zeplik AI | Zeplik Chat