本文へ移動
cccskills
無料GitHub で公開

pdf-forms

Fill in a PDF form, annotate or redact a PDF, or add, remove or rotate its pages, when the office_edit tool is not available. Fills fillable and flat forms with the scripts FORMS.md walks through, puts notes and text on a page, blacks out words so they are gone from the file, and inserts, deletes and rotates pages with pypdf, qpdf or pdftk. Merging, splitting, creating, watermarking and encrypting PDFs are the pdf skill's.

日本語の概要は準備中です。原文の説明を表示しています。

インストール方法を見る

含まれるファイル(11)

  • SKILL.md4.9 KB
  • FORMS.md11.6 KB
  • LICENSE.txt1.4 KB
  • scripts/check_bounding_boxes.py2.7 KB
  • scripts/check_fillable_fields.py268 B
  • scripts/convert_pdf_to_images.py1008 B
  • scripts/create_validation_image.py1.2 KB
  • scripts/extract_form_field_info.py4.2 KB
  • scripts/extract_form_structure.py3.9 KB
  • scripts/fill_fillable_fields.py3.7 KB
  • scripts/fill_pdf_form_with_annotations.py3.2 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

PDF Forms, Notes, Redaction and Pages

Changes to an existing PDF, made with scripts. Merging, splitting, creating, watermarking and encrypting are in the pdf skill; reading a PDF is read_file.

Dependencies are pre-installed in the sandbox image — do NOT pip install or npm install anything.

  • Python libraries (always present): pypdf, pdfplumber, pypdfium2, Pillow.
  • CLI tools (present on current sandbox images): pdftoppm (poppler-utils), qpdf, pdftk. If one returns not found, use the pypdf way on this page rather than trying to install it.

Fill in a form

Follow FORMS.md, step by step and in order. It checks whether the PDF has fillable fields, then fills them, or writes the answers onto a flat form as annotations, with the scripts in scripts/.

Add a note or text to a page

from pypdf import PdfWriter
from pypdf.annotations import FreeText, Text

writer = PdfWriter(clone_from="input.pdf")
# A rect is (left, bottom, right, top) in PDF points, from the page's bottom-left corner.
writer.add_annotation(page_number=0, annotation=Text(rect=(50, 742, 70, 762), text="Check this total"))  # a comment icon
writer.add_annotation(page_number=0, annotation=FreeText(
    text="Approved", rect=(50, 700, 200, 720), font_size="12pt", border_color=None, background_color=None,
))  # text shown on the page
writer.write("annotated.pdf")

To put a note beside some words, find them with pdfplumber as the redaction below does: its top and bottom count from the page's top, so a rect's bottom is page.height - bottom.

Redact

A black box drawn over text leaves the text in the file, and anyone can still copy it out. Render the page, black out the words on the image, and put the image in the page's place:

import io
import subprocess

import pdfplumber
from PIL import Image, ImageDraw
from pypdf import PdfReader, PdfWriter

SRC, PAGE, DPI = "input.pdf", 1, 200  # PAGE counts from 1
WORDS = ["Jane Doe", "555-0142"]

with pdfplumber.open(SRC) as pdf:
    found = [hit for word in WORDS for hit in pdf.pages[PAGE - 1].search(word, regex=False)]
print(f"{len(found)} matches")  # 0 means the words are not in the text layer: a scanned page needs OCR first

subprocess.run(["pdftoppm", "-png", "-r", str(DPI), "-f", str(PAGE), "-l", str(PAGE), "-singlefile", SRC, "page"], check=True)
image = Image.open("page.png").convert("RGB")
draw, scale = ImageDraw.Draw(image), DPI / 72
for hit in found:
    draw.rectangle([hit["x0"] * scale - 2, hit["top"] * scale - 2, hit["x1"] * scale + 2, hit["bottom"] * scale + 2], fill="black")
flat = io.BytesIO()
image.save(flat, format="PDF", resolution=DPI)

writer = PdfWriter()
for number, page in enumerate(PdfReader(SRC).pages, start=1):
    writer.add_page(PdfReader(flat).pages[0] if number == PAGE else page)
writer.write("redacted.pdf")

The redacted page becomes a picture: its text can no longer be selected or searched. pdftotext -f 1 -l 1 redacted.pdf - (with your page number) must not print the words. The same words may also be on other pages, in the metadata (PdfReader(SRC).metadata), in form fields or in annotations.

Add, remove and rotate pages

pypdf

from pypdf import PdfReader, PdfWriter

writer = PdfWriter(clone_from="input.pdf")
writer.pages[0].rotate(90)  # Rotate page 1 by 90 degrees clockwise
del writer.pages[2]  # Remove page 3
writer.insert_page(PdfReader("cover.pdf").pages[0], index=0)  # cover.pdf's first page becomes page 1
writer.insert_blank_page(index=2)  # A blank page at position 3, the size of the last page
writer.write("output.pdf")

Page indexes count from 0, and each insert or removal moves the pages after it.

qpdf

qpdf input.pdf output.pdf --rotate=+90:1  # Rotate page 1 by 90 degrees
qpdf input.pdf --pages . 1-2,4-z -- output.pdf  # Remove page 3
qpdf input.pdf --pages . 1 cover.pdf 1 . 2-z -- output.pdf  # cover.pdf's first page after page 1

pdftk

pdftk input.pdf rotate 1east output rotated.pdf  # Rotate page 1; the other pages stay as they are
pdftk input.pdf cat 1-2 4-end output output.pdf  # Remove page 3
pdftk A=input.pdf B=cover.pdf cat A1 B1 A2-end output output.pdf  # cover.pdf's first page after page 1

Check what you changed

pdftoppm -png -r 80 output.pdf page && ls -1 "$PWD"/page-*.png

Ask vision_analyze about each page image once: a filled field, a note or a black box where it belongs, pages the right way up and in order.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

The Arbor research-coordinator protocol: the OBSERVE -> IDEATE -> SELECT -> DISPATCH -> DECIDE cycle over a durable Idea Tree. Preloaded automatically on /auto-research sessions. The coordinator never edits code or runs commands — executors do that in isolated worktrees; the coordinator steers the tree with idea_tree / dispatch_experiments / merge_experiment.

日本語の概要は準備中です。原文の説明を表示しています。

invergent-ai/surogates282026年10月19日 更新

The Arbor executor workflow: clone the repo from the git bundle your brief hands you, implement and evaluate exactly ONE hypothesis with the file tools, then report structured results via worker_complete. Preloaded automatically on arbor-executor task workers. Never touch the held-out test split.

日本語の概要は準備中です。原文の説明を表示しています。

invergent-ai/surogates282026年10月19日 更新

Hard-gated ideation for an Arbor research run. Load at the START of every IDEATE round, before drafting any hypothesis. Enforces the PI mindset (mechanism over knob), the four-question first-principles probe, the kill-filter, and the four-line hypothesis format. Ported from Arbor's idea_drafting + first_principles_probe.

日本語の概要は準備中です。原文の説明を表示しています。

invergent-ai/surogates282026年10月19日 更新

DECIDE-phase doctrine for an Arbor research run: when to merge, prune, combine, or finalize; how the held-out merge gate works; and the rule that the final report uses TEST scores. Load before deciding what to do with completed experiments.

日本語の概要は準備中です。原文の説明を表示しています。

invergent-ai/surogates282026年10月19日 更新

Intake for an autonomous research run (Arbor). Use when the user wants to optimize a metric in a repo over many isolated experiments — 'optimize this benchmark', 'improve the model F1 overnight', 'beat the leaderboard'. Discovers the repo/eval/splits, measures the baseline, confirms a Research Contract, then emits a ready-to-send /auto-research command. Does NOT start the run itself.

日本語の概要は準備中です。原文の説明を表示しています。

invergent-ai/surogates282026年10月19日 更新

You MUST use this before any creative work — creating features, building components, drafting documents, designing workflows, or modifying behavior. Explores your human partner's intent, requirements, and design before any implementation begins.

日本語の概要は準備中です。原文の説明を表示しています。

invergent-ai/surogates282026年10月19日 更新

invergent-ai のスキルをすべて見る

このスキルの問題を報告する