skills/do.pdf-to-markdown/SKILL.md
Convert PDF documents to high-fidelity Markdown with guaranteed completeness. Uses page-by-page sequential processing with structural verification to prevent paragraph loss. Triggers: "PDF to markdown", "convert PDF", "extract PDF text", "PDF to md", "read this PDF"
npx skillsauth add dull-bird/deeporbit do.pdf-to-markdownInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Convert PDF documents into structured Markdown while ensuring zero paragraph loss and perfect formula/table preservation. This skill uses a rigorous multi-pass workflow: first build a structural map of the entire document, then convert page-by-page with continuous verification.
PyMuPDF, fitz.get_text(), pdfplumber) to blindly extract text. Python text extraction destroys LaTeX math formulas, breaks tables, and ruins multi-column layouts.read_file tool directly on the PDF. This passes the PDF to you visually, allowing you to correctly perceive and transcribe LaTeX math, tables, and complex layouts.pip install PyMuPDF
(PyMuPDF is ONLY for the extract_images.py script, NOT for text extraction!)
Before converting any content, you MUST build a complete map of the document.
read_file tool to visually inspect the document and get a global overview.## Structure Manifest: <filename>
- Total pages: N
- Sections discovered:
- [ ] Title / Cover Page (p.1)
- [ ] Abstract (p.1-2)
- [ ] Section 1: Introduction (p.2-4)
- [ ] Section 2: Related Work (p.4-7)
- [ ] ...
- [ ] References (p.N-1 - N)
- [ ] Appendix (p.N)
- Tables: T (list page numbers)
- Figures: F (list page numbers)
- Footnotes: estimated count
<filename>_manifest.md in the same directory as the PDF. This is your completeness checklist — every item must be checked off by the end. Do not proceed to Phase 2 until this file is written.[!IMPORTANT] If the PDF has a Table of Contents, use it as the primary source for the manifest. If not, scan page-by-page headers to build one.
python {skill_path}/scripts/extract_images.py <input.pdf>
This will:
<filename>_assets/ directory alongside the PDFpage3_img1.pngNote the image count in the manifest — it will be verified in Phase 3.
CRITICAL: Each section is converted in a separate Ralph iteration. Do NOT attempt to convert multiple sections in one agent turn.
Step 1: After Phase 1 is done (manifest + images extracted), launch the Ralph loop:
/ralph:loop "You are running do.pdf-to-markdown Phase 2. The manifest is at '<filename>_manifest.md'. Your job in THIS iteration: 1) Read the manifest. 2) Find the FIRST section still marked '- [ ]'. 3) Read that section's pages from the PDF using read_file. 4) Convert to Markdown and APPEND to '<filename>.md'. 5) Update the manifest: '- [ ]' to '- [x]'. 6) If ALL sections are now [x], run Phase 3 verification and output '<promise>CONVERSION_COMPLETE</promise>'. Otherwise, just finish this turn." --completion-promise "CONVERSION_COMPLETE" --max-iterations 30
Step 2: Each Ralph iteration does the following for ONE section:
[ ] section.read_file.#, ##, ###)$inline$ or $$block$$). You must visually transcribe the math into LaTeX.[^1] using extracted images<filename>.md immediately.- [ ] → - [x].flowchart TD
A["Phase 1 done: manifest + images"] --> B["/ralph:loop"]
B --> C["Iteration N: Read manifest"]
C --> D{"Find next [ ] section"}
D -->|Found| E["read_file: visually read pages"]
E --> F["Convert to Markdown"]
F --> G["Append to output + check off [x]"]
G --> H["Turn ends"]
H --> C
D -->|All [x]| I["Phase 3: Verification"]
I --> J["CONVERSION_COMPLETE"]
[!IMPORTANT] Set
--max-iterationsto roughly 2× the number of sections. If Ralph stops mid-way, just re-run — it picks up from the first unchecked[ ].
Only after all sections are [x] does the loop proceed to Phase 3.
After all sections are converted, run a final verification pass:
Manifest check: Open the manifest — every [ ] must now be [x]. If any remain unchecked, go back and convert those sections.
Page coverage check: Verify that every page of the PDF is accounted for.
Section boundary check: Ensure no section headers from the manifest are missing in the output. Search the output for each section title.
Table/Figure count: Verify the number of tables and figures matches the manifest counts.
Report the verification results:
## Conversion Report
- Source: <filename>.pdf (<N> pages)
- Output: <filename>.md (<word count> words)
- Sections: <M>/<M> verified ✅
- Tables: <T>/<T> converted ✅
- Figures: <F>/<F> extracted ✅
- Images saved to: `<filename>_assets/` (<count> files)
- Estimated completeness: ~XX%
<filename>.md---
type: note
title: "<Document Title>"
source: "[[<filename>.pdf]]"
created: YYYY-MM-DD
tags: [pdf-conversion]
---
[[wikilinks]] to 40_Wiki if applicable$E = mc^2$$$\int_0^1 f(x)dx$$<table> as fallback<filename>_assets/| Ralph Feature | How PDF-to-Markdown Uses It |
|---|---|
| Persistent state via files | Manifest (_manifest.md) tracks progress across turns |
| Fresh context each turn | Each chapter gets full context window — no overflow |
| Completion promise | CONVERSION_COMPLETE triggers when all [ ] become [x] |
| Max iterations safety | Prevents infinite loops if a section fails repeatedly |
| Self-correction | Each turn reads current state, can fix issues from previous turns |
deeporbit.json for language settings. The output Markdown must preserve the original language of the PDF verbatim. The Obsidian folder paths themselves will ALWAYS remain in English.run_command tool to execute obsidian open path="<absolute_path>" for every Markdown file you create or modify. See the do.obsidian-open skill for details.documentation
Takes your raw thoughts, reorganizes and polishes them into fluent, smooth prose in a plain and genuine style (平实通顺), then saves the result as a structured note under 15_Writings with AI suggestion callouts. Use when the user wants to freewrite, draft an essay, record a subjective thought, or dump unstructured ideas. Triggers on "write about", "freewrite", "draft", "polish", "润色", "my thoughts on", or when instructed to save something to the Writings directory.
documentation
Translate documents smartly. Accepts a URL or a PDF file as input. Detects if it is an arXiv URL or paper. If yes, runs do.arxiv-translator. If it is a standard PDF, runs do.pdf-to-markdown followed by do.translate-markdown.
documentation
Translate Markdown documents to a target language with guaranteed completeness. Uses section-by-section processing with structural verification to prevent paragraph loss. Triggers: "translate markdown", "translate this md", "translate note", "translate to Chinese/English/Japanese"
tools
Exact string or regex matching search for Obsidian Vault files