| name | pdf-ocr |
| description | Convert text-layer or scanned PDF files to clean Markdown and extracted images with MinerU, then run deterministic quality checks and optional LLM-assisted formula review. Use when a user asks to OCR a PDF, extract a PDF to Markdown, preserve formulas or tables from a PDF, or prepare a PDF for translation. |
PDF OCR
Convert a PDF to <output>/full.md and <output>/images/. Default to MinerU's cloud vlm API. Keep the source PDF unchanged.
Privacy and authorization gate
Before the first network call for each input document:
- State that selected PDF pages will be uploaded to MinerU for processing.
- State the input path, selected page range, and output directory.
- If the document may be confidential, contain personal data, or the user's authorization is unclear, obtain confirmation before uploading. A request that explicitly names MinerU and the exact document can count as confirmation when no sensitivity is apparent.
- Never ask the user to paste an API token into chat. Never print, log, or write the token into the workspace.
Preflight
- Locate this skill directory from the loaded
SKILL.md; do not assume it is under ~/.codex or any other platform-specific root.
- Inspect the PDF with
pdfinfo when available. Sample pdftotext output when deciding whether --method ocr is useful.
- Require Python 3.9+. Prefer
uv: the cloud entry script declares requests and pypdf with PEP 723, so uv run creates an isolated cached environment automatically.
- If
uv is unavailable, require requests and pypdf in the selected Python environment. Install requirements.txt only with the user's approval; it also includes optional httpx for external LLM review.
- Check only whether
MINERU_API_TOKEN exists. If absent, stop before uploading and direct the user to MinerU's current API management documentation. Do not claim a fixed token lifetime, quota, or price.
- MinerU cloud API requests, presigned uploads, polling, and result downloads use a direct HTTP session by default. Proxy environment variables are intentionally ignored for this workflow.
- Default to a small page sample for a large or uncertain document, then inspect quality before processing the full file.
Run OCR
From the skill root, run cloud OCR with isolated, automatically resolved dependencies:
uv run scripts/ocr.py --input <pdf> [--output <dir>]
[--backend cloud-vlm|cloud-pipeline|vlm-auto-engine|hybrid-auto-engine|pipeline|vlm-http-client]
[--lang ch|en] [--method auto|txt|ocr]
[--chunk-pages 200] [--start N --end N] [--url <server-url>]
start and end are zero-based and inclusive. Keep each cloud chunk within the provider's current limits; the script rejects values above 600 pages per chunk. Provider limits may change, so provider errors and current documentation are authoritative.
For local backends, require a working mineru executable on PATH. The local path can use python3 scripts/ocr.py ... because it does not need the cloud Python packages. Do not install MinerU or download models without the user's approval.
Fallback when uv is unavailable and the user authorizes installing into their selected Python environment:
python3 -m pip install -r requirements.txt
python3 scripts/ocr.py --input <pdf> [options]
Quality control
scripts/ocr.py automatically runs scripts/qc.py in report mode after OCR. Treat missing images as blocking. Review the report for:
- broken Markdown or HTML image references;
- spaced digits and suspicious formula patterns;
- degraded mathematical tables;
[Unreadable] markers;
- domain-incongruent hallucination markers.
Apply deterministic fixes only after inspecting the report:
python3 scripts/qc.py <full.md-or-directory> --fix --promote-display --tables-to-markdown
Use --fix-hallucination only after confirming the flagged language is inconsistent with the document's domain.
Optional LLM formula review
Default to host review: use the current agent to inspect flagged formulas and nearby context without an external LLM call. Keep this optional layer separate from deterministic QC, review changes before writing, and do not claim a complete mathematical proof check.
For automated batch review, the user may explicitly choose openai-chat, openai-responses, or anthropic-messages. Before that external call, disclose the selected context scope, protocol, model, and endpoint host; require LLM_API_KEY and LLM_MODEL; never expose the key. These are wire protocols, not a provider catalog.
uv run scripts/llm_fix.py repair <full.md-or-directory> --protocol openai-chat
uv run scripts/llm_fix.py repair <full.md-or-directory> --protocol openai-responses --apply
uv run scripts/llm_fix.py audit <full.md-or-directory> --protocol anthropic-messages --key 30 --random 30
Run repair without --apply first. The script only auto-applies small edits and creates .bak files plus _llm_fix_log.md when writing.
Handoff to translation
If the user also requests translation, pass <output>/full.md to the md-translate skill only after OCR QC. Do not translate inside this skill.
Report
Report the backend, exact output paths, processed page range, Markdown line/word counts, image count, QC findings, and whether LLM review was run. Distinguish NOT-RUN from a successful check.