Metadata-Version: 2.4
Name: pdf2md-claude
Version: 0.1.0
Summary: Convert PDF documents to Markdown using Claude's native PDF API
Author-email: Pavel Sokolov <pavel@sokolov.me>
License-Expression: MIT
Project-URL: Homepage, https://github.com/hacker-cb/pdf2md-claude
Project-URL: Repository, https://github.com/hacker-cb/pdf2md-claude
Project-URL: Issues, https://github.com/hacker-cb/pdf2md-claude/issues
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Text Processing :: Markup :: Markdown
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: anthropic>=0.40
Requires-Dist: pymupdf>=1.24
Requires-Dist: colorlog>=6.0
Requires-Dist: httpx[socks]>=0.27
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Dynamic: license-file

# pdf2md-claude

[![CI](https://github.com/hacker-cb/pdf2md-claude/actions/workflows/ci.yml/badge.svg)](https://github.com/hacker-cb/pdf2md-claude/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/pdf2md-claude)](https://pypi.org/project/pdf2md-claude/)
[![Python](https://img.shields.io/pypi/pyversions/pdf2md-claude)](https://pypi.org/project/pdf2md-claude/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

Convert PDF documents to high-quality Markdown using Claude's native PDF API.
Handles large documents via chunked conversion with context passing, deterministic
merging, and output validation. Preserves tables, formulas, figures, and document structure.

## Installation

Requires Python 3.11+.

```bash
pip install pdf2md-claude
```

Or install from source:

```bash
pip install git+https://github.com/hacker-cb/pdf2md-claude.git
```

## Quick Start

```bash
# Set API key
export ANTHROPIC_API_KEY="your-key-here"

# Convert a single PDF (output: document.md next to the PDF)
pdf2md-claude document.pdf

# Convert multiple PDFs
pdf2md-claude doc1.pdf doc2.pdf

# Convert all PDFs in a directory (shell glob)
pdf2md-claude *.pdf
pdf2md-claude docs/*.pdf

# Custom output directory
pdf2md-claude *.pdf -o output/

# Also works via python -m
python -m pdf2md_claude document.pdf
```

## Output

By default, Markdown files are written next to the source PDF:

| Input | Output |
|---|---|
| `docs/document.pdf` | `docs/document.md` |
| `docs/document.pdf --max-pages 5` | `docs/document_first5.md` |

With `-o DIR`, all output goes to the specified directory.

## Conversion Pipeline

Chunked conversion with context passing, deterministic merging, and validation:

1. Split PDF into disjoint chunks
2. Convert each chunk with context from the previous chunk's tail
3. Merge chunks by page markers (deterministic, no LLM)
4. Merge continued tables across page boundaries (deterministic, no LLM)
5. Extract and inject images from bounding-box markers (deterministic, no LLM)
6. Validate output (page markers, tables, heading gaps, binary sequences, fabrication detection)

## CLI Options

```
pdf2md-claude [OPTIONS] PDF [PDF ...]

Positional:
  PDF                  One or more PDF files to convert (supports shell globs)

Options:
  -o, --output-dir DIR Output directory (default: same directory as each PDF)
  -v, --verbose        Enable verbose logging
  -f, --force          Force reconversion even if output exists
  --max-pages N        Convert only first N pages (useful for debugging)
  --cache              Enable prompt caching (1h TTL, reduces re-run cost)
  --pages-per-chunk N  Pages per conversion chunk (default: 10)
  --no-images          Skip image extraction from bounding-box markers
  --remerge            Re-merge from cached chunks (no API calls needed)
```

Run without arguments to display help.

## Environment

| Variable | Description |
|---|---|
| `ANTHROPIC_API_KEY` | Anthropic API key (required) |

## File Structure

```
pdf2md-claude/
├── pdf2md_claude/              # Main package
│   ├── __init__.py             # Package exports (lazy imports)
│   ├── __main__.py             # python -m pdf2md_claude entry point
│   ├── cli.py                  # CLI argument parsing and orchestration
│   ├── client.py               # Anthropic API client setup
│   ├── converter.py            # Core PDF→Markdown conversion logic
│   ├── images.py               # Image extraction, rendering, and injection (pymupdf)
│   ├── markers.py              # Centralized marker definitions (MarkerDef)
│   ├── merger.py               # Deterministic page-marker merge + table continuation merging
│   ├── models.py               # Model configurations, pricing, usage tracking
│   ├── pipeline.py             # Single-document orchestration (convert → merge → validate → write)
│   ├── prompt.py               # Prompts for Claude PDF conversion
│   ├── validator.py            # Content validation (page markers, tables, fabrication, etc.)
│   └── workdir.py              # Chunk persistence, resume, and work directory management
├── tests/                      # Unit tests
│   ├── __init__.py
│   ├── test_converter.py
│   ├── test_images.py
│   ├── test_markers.py
│   ├── test_table_merger.py
│   ├── test_validator.py
│   └── test_workdir.py
├── scripts/
│   └── setup-dev.sh            # Dev environment setup (.venv + hooks)
├── .githooks/
│   └── pre-commit              # Runs tests before commit
├── pyproject.toml              # Project metadata and dependencies
├── .gitignore
└── README.md
```

## Development

### Setup

One command sets up everything (.venv, dependencies, git hooks):

```bash
git clone https://github.com/hacker-cb/pdf2md-claude.git
cd pdf2md-claude
bash scripts/setup-dev.sh
```

To recreate the .venv from scratch:

```bash
bash scripts/setup-dev.sh --force
```

### Running Tests

```bash
pytest tests/ -v
```

### Debugging

Enable verbose logging:

```bash
pdf2md-claude -v document.pdf
```

Use `--cache` to avoid re-paying for PDF content on repeated runs during
prompt/pipeline development:

```bash
pdf2md-claude --cache document.pdf --max-pages 5
```
