Standalone PDF book-to-Markdown extraction CLI with cleanup and chapter splitting
Project description
pdf-book2md
pdf-book2md turns PDF books and manuals into cleaned Markdown organized as
chapter files. It is built for long-form, structured PDFs where you want a
repeatable output tree for reading, search, indexing, or downstream processing.
Quick Start
Install from PyPI:
python -m pip install pdf-book2md
Extract one book:
pdf-book2md extract ./manual.pdf --output-dir ./out/manual/chapters
Batch-process a directory:
pdf-book2md batch ./pdfs --output-root ./out
What It Produces
When chapter headings are detected, pdf-book2md writes numbered chapter files
and preserves the source text as full_document.md:
out/
manual/
chapters/
00_frontmatter.md
01_Chapter_1_Overview.md
02_Chapter_2_Setup.md
03_Appendix_A_Reference.md
full_document.md
If no chapter split is detected, the command writes a single full_document.md.
Features
- Extract one PDF into cleaned Markdown.
- Batch-process PDFs into per-document output directories.
- Split book/manual-style documents into deterministic chapter files.
- Preserve frontmatter separately when introductory material exists before the first detected chapter.
- Skip already-processed batch outputs unless
--forceis supplied. - Print JSON summaries for automation with
--json. - Lazy-load
pymupdf4llm, so tests and CLI help work without the runtime extraction dependency installed.
Usage
Single PDF
pdf-book2md extract ./manual.pdf --output-dir ./out/manual/chapters
Use --skip-full-document when you only want chapter files and do not need the
combined Markdown copy:
pdf-book2md extract ./manual.pdf --output-dir ./out/manual/chapters --skip-full-document
Batch Directory
pdf-book2md batch ./pdfs --output-root ./out
Batch mode writes each input PDF under OUTPUT_ROOT/<pdf-stem>/chapters/.
Existing outputs are skipped when the target chapters/ directory already
contains Markdown files.
Reprocess existing outputs:
pdf-book2md batch ./pdfs --output-root ./out --force
Select PDFs with a custom glob:
pdf-book2md batch ./pdfs --output-root ./out --pattern "*guide*.pdf"
JSON Output
pdf-book2md batch ./pdfs --output-root ./out --json
The JSON summary includes absolute input and output paths, processed documents, and skipped documents:
{
"input_dir": "/path/to/pdfs",
"output_root": "/path/to/out",
"processed": [],
"skipped": ["/path/to/pdfs/manual.pdf"]
}
Common runtime failures are printed to stderr as error: ... and exit with
status code 1. Argument parsing errors exit with status code 2.
Library API
from pathlib import Path
from pdf_extract_cli import extract_pdf
result = extract_pdf(Path("manual.pdf"), Path("out/manual/chapters"))
print(result.chapter_count)
Development
Install from source:
python3 -m pip install -e . --no-deps
Run tests:
python3 -m unittest discover -s tests -v
Smoke-test the CLI:
pdf-book2md --help
Releases are managed with Python Semantic Release. Conventional commits on
main determine whether a release is created; release builds publish to PyPI
using trusted publishing for .github/workflows/release.yml on the main
branch.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pdf_book2md-1.0.0.tar.gz.
File metadata
- Download URL: pdf_book2md-1.0.0.tar.gz
- Upload date:
- Size: 9.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6d0b00cf3ed3531d289eddd255c1c5bca2e2d1eb5c9be2871ad64f33dca664b
|
|
| MD5 |
2da404ab6a5881984aa0c0b4ef17424a
|
|
| BLAKE2b-256 |
b3d88436a79ad3d6d3baf9db800f7be799d2c00a5cc97dd606c4a2a65ed8d940
|
Provenance
The following attestation bundles were made for pdf_book2md-1.0.0.tar.gz:
Publisher:
release.yml on jrepp/pdf-book2md
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_book2md-1.0.0.tar.gz -
Subject digest:
a6d0b00cf3ed3531d289eddd255c1c5bca2e2d1eb5c9be2871ad64f33dca664b - Sigstore transparency entry: 1633889127
- Sigstore integration time:
-
Permalink:
jrepp/pdf-book2md@7cd807a4097a9f34e70996b161d0cec42a8ff45e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jrepp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7cd807a4097a9f34e70996b161d0cec42a8ff45e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pdf_book2md-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pdf_book2md-1.0.0-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7fa7dd96623f501b8b1bacbbc9300a7d753a3be9b08aac9fa964ddb023efe5d
|
|
| MD5 |
d3ed4ed2ea8c515cf351ffd0a680ddb2
|
|
| BLAKE2b-256 |
272dca6a6ffd8c9d83eded7c5699486717dc82dcdeb298c3e85782148e9c930f
|
Provenance
The following attestation bundles were made for pdf_book2md-1.0.0-py3-none-any.whl:
Publisher:
release.yml on jrepp/pdf-book2md
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pdf_book2md-1.0.0-py3-none-any.whl -
Subject digest:
c7fa7dd96623f501b8b1bacbbc9300a7d753a3be9b08aac9fa964ddb023efe5d - Sigstore transparency entry: 1633889163
- Sigstore integration time:
-
Permalink:
jrepp/pdf-book2md@7cd807a4097a9f34e70996b161d0cec42a8ff45e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/jrepp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7cd807a4097a9f34e70996b161d0cec42a8ff45e -
Trigger Event:
workflow_dispatch
-
Statement type: