Back to Brain Lab Skill · PDF to Markdown · pdf-to-markdown/
Skill Claude

PDF to Markdown

pdf-to-markdown/

3 views 0 downloads

Convert PDFs and Office files (Word, PowerPoint, Excel) into clean Markdown with Microsoft's markitdown, from inside Claude Code.

PDF to Markdown: Brain Lab skill for Claude Code

Convert PDFs and Office files (Word, PowerPoint, Excel) into clean Markdown with Microsoft's markitdown, from inside Claude Code.

What it does

  • Converts PDF, Word (.docx), PowerPoint (.pptx) and Excel (.xlsx) files to Markdown with Microsoft markitdown.
  • Keeps headings, lists and tables, which plain text extraction loses.
  • Tells you when a PDF is a scan with no text layer, instead of returning an empty file. It does not do OCR.

Needs Python. The skill installs markitdown on first use: pip install "markitdown[pdf,docx,pptx,xlsx]".

Use

Ask Claude: "convert this PDF to markdown", "extract the tables from this spreadsheet" or "turn these slides into notes".

Install

Download this skill and copy the pdf-to-markdown folder to .claude/skills/pdf-to-markdown/ in your project, or to ~/.claude/skills/pdf-to-markdown/ to use it in every project. Claude Code finds it on its own; you can also call it with /pdf-to-markdown.

Source: endorphin-ai/hasbrains-agent-kit. License: MIT.

Files (5)

Files

#!/usr/bin/env python3
"""Convert PDFs and Office docs to Markdown using Microsoft markitdown.

Usage:
    python convert.py file1.pdf file2.docx           # write .md next to each source
    python convert.py ./docs -o ./markdown           # convert a whole directory
    python convert.py report.pdf --stdout            # print to stdout instead

Supported inputs: .pdf .docx .pptx .xlsx (text-based; no OCR for scanned PDFs).
"""
import argparse
import sys
from pathlib import Path

SUPPORTED = {".pdf", ".docx", ".pptx", ".xlsx"}


def collect(paths):
    files = []
    for p in paths:
        path = Path(p)
        if path.is_dir():
            files.extend(sorted(f for f in path.rglob("*") if f.suffix.lower() in SUPPORTED))
        elif path.suffix.lower() in SUPPORTED:
            files.append(path)
        else:
            print(f"warning: skipping unsupported or missing file: {p}", file=sys.stderr)
    return files


def main():
    ap = argparse.ArgumentParser(description="Convert documents to Markdown with markitdown.")
    ap.add_argument("inputs", nargs="+", help="Files or directories to convert")
    ap.add_argument("-o", "--output-dir", help="Directory to write .md files into")
    ap.add_argument("--stdout", action="store_true", help="Print Markdown to stdout instead of writing files")
    args = ap.parse_args()

    try:
        from markitdown import MarkItDown
    except ImportError:
        sys.exit('markitdown not installed. Run: pip install "markitdown[pdf,docx,pptx,xlsx]"')

    md = MarkItDown()
    files = collect(args.inputs)
    if not files:
        sys.exit("No supported files found (.pdf .docx .pptx .xlsx).")

    out_dir = Path(args.output_dir) if args.output_dir else None
    if out_dir:
        out_dir.mkdir(parents=True, exist_ok=True)

    exit_code = 0
    for f in files:
        try:
            text = md.convert(str(f)).text_content or ""
        except Exception as e:
            print(f"error: failed to convert {f}: {e}", file=sys.stderr)
            exit_code = 1
            continue

        if args.stdout:
            print(text)
            continue

        target_dir = out_dir if out_dir else f.parent
        target = target_dir / (f.stem + ".md")
        # Avoid clobbering when two inputs share a stem (e.g. report.pdf + report.docx)
        if target.exists():
            target = target_dir / f"{f.stem}-{f.suffix.lstrip('.')}.md"
        target.write_text(text, encoding="utf-8")

        if len(text.strip()) < 20:
            print(f"WARNING: {target} is nearly empty — {f.name} may be a scanned/image PDF (no OCR).", file=sys.stderr)
            exit_code = 1
        print(f"wrote {target}")

    sys.exit(exit_code)


if __name__ == "__main__":
    main()