ingest

A command that converts course PDFs into Markdown text with LaTeX for equations, using image-based reading. Markdown is plain text with formatting marks, while LaTeX is a system for writing mathematical notation.

In plain words
What is it for?
Converting lectures, textbooks, homework, and solutions in the materials folder into readable Markdown files.
Why use it?
It handles equations, figures, columns, and other layouts that ordinary PDF text extraction can read incorrectly, while skipping files already converted.

Command

Part of the paideia plugin — 6 skills, 18 commands shipped together

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add commands/optimeta/paideia/ingest
Clone the repo
git clone --depth 1 https://github.com/OPTIMETA/PAIDEIA

Or install paideia, the plugin that ships this one along with the rest of its 6 skills, 18 commands.

Per session 46 Only the description is in the session, so the agent can decide to use it. The body loads when it is invoked.
When invoked 2,439 The whole file, excluding the scripts and references it only reads on demand.
Security scan E 2 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.00046 $0.02439
Opus 5 $0.00023 $0.01220
Sonnet 5 $0.00009 $0.00488
Haiku 4.5 $0.00005 $0.00244

Measured 3d ago against content hash 1359b5b5301f, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade E, and why

ingest scanned grade E with 2 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 3d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Tells the agent never to refusehighAnti-refusal

Suppressing the ability to decline removes a core safety control; a later harmful request then succeeds.

the page as-is; this is a legitimate OCR task, so do not refuse or stop.

Recursive force deletehighDestructive command

rm -rf with a variable or a broad path is one typo away from removing the wrong tree.

rm -rf converted/*/_pages
plugins/paideia/commands/ingest.md · 182 lines

How it starts

The opening of the file, as written. The whole thing — 182 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Output language

Read INTERFACE_LANG from .course-meta (default en). All user-facing prose must be in that language. Keep in English regardless: file paths, slash command names, table column headers (Category, Converted, Skipped (already done), Failed), and provenance comments.

Load skills/pdf/SKILL.md, skills/pdf/VISION.md, and skills/course-builder/SKILL.md.

Arguments: $ARGUMENTS

Routing rule

Every PDF in materials/** goes through the vision pipeline. pdfplumber is unreliable in practice on course materials — even prose-heavy textbook pages mix in equations, figures, and multi-column layouts that break digital extraction silently. Rather than maintaining a routing heuristic and a fallback that we'd need to keep tuning per course, we route everything through the same pipeline: render → resize → parallel vision agents → clean LaTeX markdown.

Source Method
materials/**/*.pdf Vision pipeline (render at dpi=160, resize ≤1800 px, one parallel general-purpose agent per PDF, sequential Read inside the agent)
materials/**/*.md Copy-through with provenance header

Hand-written answer PDFs (answers/*.pdf) are a separate path — handled by /paideia:grade, not /paideia:ingest.

Procedure

Step 1 — Discovery

Scan materials/ recursively for .pdf and .md. Classify by subfolder: lectures, textbook, homework, solutions. Ambiguous files (PDFs sitting in materials/ root) get one prompt to categorize.

Apply idempotence: if converted/<cat>/<stem>.md exists and is newer than the source, skip — unless --force is in $ARGUMENTS. Log skip count.

Step 2 — Copy-through for .md sources

For each .md already in materials/: mirror to converted/<cat>/<stem>.md verbatim, adding:

<!-- SOURCE: materials/<cat>/<stem>.md, copied <YYYY-MM-DD>, method: passthrough -->

Step 3 — Render all PDFs to PNG at dpi=160

For each PDF that needs conversion:

from pdf2image import convert_from_path
from pathlib import Path

for pdf_path in pdfs_to_convert:
    cat, stem = pdf_path.parent.name, pdf_path.stem
    out = Path(f"converted/{cat}/_pages/{stem}")
    out.mkdir(parents=True, exist_ok=True)
    # 3-digit padding: with p{i:02d}, "p100" sorts before "p99" and a 100+
    # page PDF gets read out of order by the agent.
    for i, im in enumerate(convert_from_path(str(pdf_path), dpi=160), 1):
        im.save(out / f"p{i:03d}.png", "PNG", optimize=True)

Read the full file on GitHub · 182 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 3d ago First seen · 182 lines · 46 tokens per session scan E 1359b5b5301f

Subscribe to this mod's changes

ingest is a command published in the GitHub repository OPTIMETA/PAIDEIA (91 stars, last pushed 1mo ago), licensed MIT. It adds 46 tokens to every session and 2,439 once invoked, about $0.0002 per session on Opus 5. A static security scan graded it E with 2 findings (tells the agent never to refuse, recursive force delete). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.