pdf-reader
Use when reading PDF papers, reports, or long documents where text, figures, and tables must all be captured and chunk-summarized without truncation. Converts PDF to a markdown + paper_content.json workspace, extracts figures and tables as standalone files, then delegates to arxiv-latex-reader's progressive two-layer reading (section index + on-demand deep reads). Triggers: "read pdf", "pdf to markdown", "summarize pdf", "pdf paper", "extract figures from pdf", "extract tables from pdf", "marker pdf", "pymupdf", "docling", "paper digest", "pdf reader"
Best use case
pdf-reader is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when reading PDF papers, reports, or long documents where text, figures, and tables must all be captured and chunk-summarized without truncation. Converts PDF to a markdown + paper_content.json workspace, extracts figures and tables as standalone files, then delegates to arxiv-latex-reader's progressive two-layer reading (section index + on-demand deep reads). Triggers: "read pdf", "pdf to markdown", "summarize pdf", "pdf paper", "extract figures from pdf", "extract tables from pdf", "marker pdf", "pymupdf", "docling", "paper digest", "pdf reader"
Teams using pdf-reader should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/pdf-reader/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How pdf-reader Compares
| Feature / Agent | pdf-reader | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when reading PDF papers, reports, or long documents where text, figures, and tables must all be captured and chunk-summarized without truncation. Converts PDF to a markdown + paper_content.json workspace, extracts figures and tables as standalone files, then delegates to arxiv-latex-reader's progressive two-layer reading (section index + on-demand deep reads). Triggers: "read pdf", "pdf to markdown", "summarize pdf", "pdf paper", "extract figures from pdf", "extract tables from pdf", "marker pdf", "pymupdf", "docling", "paper digest", "pdf reader"
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# PDF Reader
## When to Use
- Reading a PDF paper or report (any source — not just arxiv) where figures/tables matter
- Papers with result tables, architecture diagrams, ablation plots that must be preserved
- Long PDFs (20+ pages) that overflow a single `Read` call
- Scanned / image-heavy PDFs where plain `pdftotext` loses structure
- Any workflow where you'd use `arxiv-latex-reader` but the input is a PDF, not LaTeX
For arxiv papers with LaTeX source available, prefer `arxiv-latex-reader` directly — it's cleaner (no conversion loss). Use `pdf-reader` when LaTeX source is unavailable, the PDF is the only artifact, or the document is non-arxiv.
## Architecture
Two stages. Stage 1 is PDF-specific; Stage 2 is identical to `arxiv-latex-reader`.
```
Stage 1 (PDF-specific):
PDF → pdf_to_markdown.py → workspace/<paper_id>/
├── paper_content.json # sections + text
├── paper.md # full markdown
├── figures/ # extracted images + captions
└── tables/ # extracted markdown tables
Stage 2 (delegated to arxiv-latex-reader, unchanged):
workspace/<paper_id>/paper_content.json
→ section_indexer.py → section_index.json (~2k tokens)
→ section_reader.py / paper_navigator.py → on-demand full-section reads
```
The workspace layout is **compatible with `arxiv-latex-reader`**. Once Stage 1 produces `paper_content.json`, every downstream script from `arxiv-latex-reader` works unchanged.
## Stage 1 — Convert PDF to Markdown + Workspace
### Conversion tool fallback chain
PDFs vary wildly — academic LaTeX-rendered, scanned scans, double-column with equations, poster-style layouts. Use the first tool in the chain that installs and produces usable output.
| Tool | Strengths | Weaknesses | Install |
|------|-----------|-----------|---------|
| **marker-pdf** | Best overall: text + figures + tables + equations, preserves structure | Slow (ML models), large download | `pip install marker-pdf` |
| **docling** (IBM) | Excellent tables, layout-aware, LLM-friendly output | Heavy dependencies | `pip install docling` |
| **pymupdf4llm** | Fast, good text + basic tables, Markdown-native | No figure extraction; tables mid-quality | `pip install pymupdf4llm` |
| **pdfplumber** | Best-in-class table extraction with structure | Text only, slower, no figures | `pip install pdfplumber` |
| **pdftotext + pdfimages** (poppler) | Minimal install, fast | No tables, no captions, no structure | `brew install poppler` |
| **Claude Code native `Read`** | Built-in, multimodal, reads figures as images | 20 pages per call; not scriptable | N/A |
**Recommendation:** default to `marker-pdf`. Fallback to `pymupdf4llm` if marker is slow or unavailable. Use `pdfplumber` *in addition* for tables when they're critical.
### The converter script
Run `scripts/pdf_to_markdown.py` to build the workspace:
```bash
python scripts/pdf_to_markdown.py <path-or-url-to.pdf> --paper-id <slug> [--tool marker|pymupdf]
# → workspace/<slug>/paper_content.json
# → workspace/<slug>/paper.md
# → workspace/<slug>/figures/
# → workspace/<slug>/tables/
```
Key behaviors:
- **Never truncate.** The whole PDF is converted, no page cap.
- **Section detection** uses markdown heading levels in the converter output. If the converter emits flat text (no headings), falls back to font-size heuristics (H1 = largest font cluster, H2 = next, etc.) via pymupdf.
- **Figures** are saved as PNG to `figures/fig_<n>.png` with a sidecar `figures/fig_<n>.txt` containing the caption detected below/above the bounding box.
- **Tables** are saved as markdown to `tables/tab_<n>.md` with a first-line `<!-- caption: ... -->` comment. For complex tables, save both `.md` and `.csv`.
- **Math** is kept as LaTeX (`$...$`, `$$...$$`). marker preserves this; pymupdf4llm does not — flag in the log when equations may be lost.
See `scripts/pdf_to_markdown.py` for the implementation. The script writes a `workspace/<paper_id>/conversion.log` with the tool used, page count, figure count, table count, and any dropped content warnings.
### `paper_content.json` schema
Produced by the converter, consumed by `arxiv-latex-reader`:
```json
{
"paper_id": "2404.12345",
"source": "pdf",
"title": "...",
"authors": [...],
"sections": [
{"name": "Abstract", "text": "...", "level": 1},
{"name": "Introduction","text": "...", "level": 1, "figures": ["fig_1"], "tables": []},
{"name": "Method", "text": "...", "level": 1, "figures": ["fig_2","fig_3"], "tables": ["tab_1"]}
],
"figures": [
{"id":"fig_1","path":"figures/fig_1.png","caption":"...","page":2}
],
"tables": [
{"id":"tab_1","path":"tables/tab_1.md", "caption":"...","page":5}
]
}
```
The `figures` and `tables` arrays per-section are what `pdf-reader` adds on top of `arxiv-latex-reader`'s format — they let the reader pull the right figure into context when deep-reading a section.
## Stage 2 — Progressive Reading (delegated)
Once Stage 1 completes, use `arxiv-latex-reader` as-is:
```bash
# Build the ~2k-token section index (one-time per paper)
python ../arxiv-latex-reader/scripts/section_indexer.py <paper_id>
# Overview or on-demand section reads
python ../arxiv-latex-reader/scripts/paper_navigator.py <paper_id> overview
python ../arxiv-latex-reader/scripts/paper_navigator.py <paper_id> read Method Experiments
python ../arxiv-latex-reader/scripts/paper_navigator.py <paper_id> poster
```
Python API is identical:
```python
from paper_navigator import PaperNavigator
nav = PaperNavigator("2404.12345", workspace_dir="workspace")
overview = nav.get_overview()
sections = nav.read_full(["Method", "Experiments"])
```
**Do not re-implement indexing or navigation here.** `pdf-reader` is a converter front-end, nothing more.
## Figure and Table Handling
PDFs encode figures as raster/vector content with captions placed above or below — the converter must pair the two.
### Classification (done during conversion)
Same classes as `blog-reader` and `arxiv-latex-reader`'s figure_extractor:
| Class | Signals | What the reader does |
|-------|---------|----------------------|
| **Key** | Referenced in body ("Fig. 2"), architecture/overview diagrams, main result tables | `Read` the image multimodally when deep-reading its section |
| **Supporting** | Ablation plots, secondary results | `Read` if budget allows |
| **Decorative** | Hero images, logos | Caption-only; skip multimodal Read |
Classification is stored in each figure's sidecar: `figures/fig_1.txt`:
```
caption: Model architecture overview.
class: key
page: 2
referenced_in: §Method
```
### Multimodal figure Read at deep-read time
When `paper_navigator read §Method` is called and §Method has key figures, the caller should:
```python
# After getting section text, also Read key figures for that section
for fig_id in section["figures"]:
if figures[fig_id]["class"] == "key":
# Read via Claude Code's multimodal Read tool
image = read_image(f"workspace/<paper_id>/figures/{fig_id}.png")
# → multimodal interpretation inline with section text
```
This is the main value-add over `arxiv-latex-reader`: figures are already PNGs, so you skip the LaTeX-compile-to-PNG step.
### Table handling
Tables are already markdown — include them verbatim alongside the section text. For numeric result tables, preserve every cell value verbatim (no rounding, no summarization).
## Quick Reference
```bash
# Full pipeline (one paper, end to end)
python pdf-reader/scripts/pdf_to_markdown.py paper.pdf --paper-id mypaper
python arxiv-latex-reader/scripts/section_indexer.py mypaper
python arxiv-latex-reader/scripts/paper_navigator.py mypaper overview
# Batch: convert once, then query many times
for pdf in papers/*.pdf; do
python pdf-reader/scripts/pdf_to_markdown.py "$pdf" --paper-id "$(basename "$pdf" .pdf)"
python arxiv-latex-reader/scripts/section_indexer.py "$(basename "$pdf" .pdf)"
done
```
## Key Principles
1. **PDF → markdown first, always.** Never send raw PDF bytes into a summarization pipeline — you lose structure and table semantics.
2. **Tool fallback, not tool monoculture.** `marker-pdf` fails on some scanned PDFs; `pymupdf4llm` fails on heavy-equation papers. Document which tool produced the output in `conversion.log`.
3. **Figures and tables are load-bearing.** Extract them as first-class artifacts, not inline captions.
4. **Delegate reading.** Stage 2 is `arxiv-latex-reader` unchanged — do not fork or reimplement.
5. **Never truncate.** Same rule as `arxiv-latex-reader`.
## Anti-Patterns
- **Passing the raw PDF to `WebFetch` or an LLM** — silent truncation, no figure extraction, lossy table representation.
- **Relying only on `pdftotext`** — no structure, no tables. Fine as a last-resort fallback, never the default.
- **Using Claude Code's native `Read` on PDFs ≥20 pages without `pages:`** — fails immediately. Chunk or convert instead.
- **Discarding the figure images after caption extraction** — the whole point of going through PDF-conversion is to recover the images. Keep them in `figures/`.
- **Letting the converter "skip" pages that failed to parse** — set `--strict` so any dropped page becomes an explicit error. Silent page-drops produce confidently-wrong summaries.
- **Round-tripping numeric tables through an LLM summarizer** — always include tables verbatim from `tables/tab_N.md`. Never paraphrase cell values.
- **Re-implementing indexing/navigation in `pdf-reader`** — you'll drift from `arxiv-latex-reader`'s semantics. Delegate.
- **Using one giant marker call on a 300-page PDF without checkpointing** — marker can take 10+ min. Use `--max-pages` and resume from `conversion.log` on failure.
## See Also
- `arxiv-latex-reader` — Stage 2 of this pipeline; use directly when LaTeX source is available
- `blog-reader` — Same coverage-test discipline applied to HTML blog posts
- `academic-deep-research` — Paper scoring and surveys; consumes paper metadata, not full textRelated Skills
github-reader
Use when reading a GitHub repository (especially a research code release with an accompanying paper) and producing a faithful digest that covers the implementation logic, the main insight, and the key reported results. Research-first with graceful fallback for non-paper repos. Handles arXiv link detection and delegates paper reading to arxiv-latex-reader / pdf-reader. Triggers: "read repo", "read this github", "analyze github", "digest repo", "github reader", "extract from github", "summarize this codebase", "read this code", "https://github.com/"
blog-reader
Use when reading a long technical blog post (ML research, engineering deep-dives, Distill/Lil'Log-style posts) and producing a faithful, figure-aware summary. Handles context-over-limit via section-based chunking, captures important figures via multimodal Read, and runs a coverage test to catch missing information. Triggers: "read this blog", "summarize this post", "read blog", "digest this article", "long blog post", "read this article", "blog summary", "distill post", "summarize url", "chunk and summarize"
arxiv-latex-reader
Use when reading large arxiv papers without context overflow. Progressive two-layer reading: index all sections (~2k tokens), then deep-read on demand. Never truncates. Triggers: "read paper", "paper sections", "section index", "progressive reading", "paper_content.json", "section summary"
ml-ablation-design
Use when designing ablation studies to compare model components, loss functions, or architectural choices. Covers synthetic data experiments, variant loops, production metrics, and W&B grouping. Triggers: "ablation", "ablation study", "variant comparison", "controlled experiment", "synthetic data experiment"
gpu-training-acceleration
Use when optimizing PyTorch training speed or memory on CUDA GPUs — global flags, torch.compile, fused optimizers, mixed precision, gradient checkpointing, kernel fusion, memory layout, or latent-space training. Applies to any PyTorch training workload. Triggers: "torch.compile", "TF32", "fused optimizer", "mixed precision", "bf16", "fp16", "gradient checkpointing", "Triton kernel", "CUDA flags", "GPU slow", "GPU memory"
genai-evaluation-metrics
Use when evaluating generative models — choosing metrics (FID, IS, KID, sFID, FDD, FVD, PRDC, LPIPS, SSIM, AuthPct, Vendi), setting up online or offline evaluation, feature extractor selection, distributed computation, memory management during sampling. Triggers: "FID", "IS", "KID", "inception score", "frechet", "LPIPS", "SSIM", "evaluation metrics", "generative evaluation", "FVD"
youtube-wiki
Use when reading a YouTube video (especially an AI/ML interview, podcast, or technical talk) and producing a faithful, timestamped wiki entry the user can return to weeks later. Fetches the transcript via yt-dlp, sections by chapters or LLM-detected topics, summarizes per-section with parallel subagents, preserves verbatim quotes with speaker attribution, and runs a coverage test against the raw transcript. Triggers: "youtube wiki", "video wiki", "summarize this youtube", "watch this interview", "read this talk", "digest this video", "https://youtu.be/", "https://www.youtube.com/watch"
insert-wiki
Use when capturing a single URL (X tweet, LinkedIn post, HN thread, short blog, news article, GitHub gist or issue) as a small persistent markdown entry the user can re-read later for motivation or grep across future sessions. Verbatim body + author + tags + a one-line "Why I saved this" hook. Writes to docs/wikis/YYYY-MM-DD-<slug>.md. WebFetch by default; CDP via Playwright MCP for login-walled hosts (x.com, twitter.com, linkedin.com). Redirects YouTube / arXiv / GitHub repo URLs to their specialized skills. Triggers: "insert wiki", "add to wiki", "insert this", "save this tweet", "capture this post", "add this to my wiki", "remember this link", "https://x.com/", "https://twitter.com/", "https://linkedin.com/posts/"
idea-feasibility
Use when evaluating whether a research or product idea is actually feasible — buildable, evaluable, and de-risked by available checkpoints, code, datasets, and GPU budget. Normalizes the idea, gathers primary-source evidence (arXiv, GitHub, project pages, model hosts), scores it against four mandatory hard gates, and emits a verdict + falsifiable MVP. Triggers: "idea feasibility", "is this idea feasible", "feasibility check", "can we do this", "is this practical", "worth pursuing", "评估想法可行性", "可行性分析", "这个 idea 能做吗", "这个想法靠谱吗"
idea-explore
Use when proposing new research ideas grounded in a seed paper or method — surfaces the gaps that the citation cone hasn't filled, the drawbacks the community already complains about in the official repo's GitHub issues, and the adjacent angles the literature suggests. Orchestrates followup-analysis (already-done exclusion), GitHub-issue mining (known drawbacks), and academic-deep-research (adjacent literature) into a ranked candidate-ideas report. Triggers: "idea explore", "idea-explore", "propose ideas", "explore ideas", "new directions", "research gaps", "what's missing", "build on this paper", "探索想法", "提出新想法", "研究空白"
idea-box
Use when promoting an idea from a fleeting thought into a tracked artifact with a lifecycle. Defines a per-idea on-disk directory (./idea_box/<slug>/) and a hard-gated state machine (explored → feasible/blocked → building → built/killed) that the existing reader/evaluator skills (idea-feasibility, ml-ablation-design, academic-deep-research, followup-analysis, arxiv-latex-reader, pdf-reader, github-reader, blog-reader) plug into. Public repo ships only the convention; idea data lives in the user's private idea-box repo. Triggers: "idea box", "idea-box", "new idea", "advance idea", "list ideas", "kill idea", "想法箱", "新想法", "推进想法", "列出想法"
academic-deep-research
Use when evaluating academic papers or surveying a research topic. Gathers venue, citations, GitHub stats, social buzz, reproducibility, and author signals to produce a scored markdown report. Triggers: "evaluate paper", "paper review", "research survey", "literature review", "is this paper good", "find papers on", "compare papers", "paper impact"