Skip to main content

Concatenate PDFs with table of contents, cover pages, and optional LLM summaries

Project description

pdf-concatenator

Bundle many PDFs into a single submission-ready document.

This tool was built to pull together a large set of PDFs for a contract submission: one combined file with a table of contents, cover pages, and optional short summaries so reviewers can navigate the bundle easily.

Features

  • Recursively discover PDFs from a directory or glob pattern
  • Sort files by path and concatenate them into one output PDF
  • Generate a table of contents with folder structure, page numbers, and alternating row shading
  • Insert a cover page before each source PDF (path, optional summary, page number)
  • Optionally generate LLM summaries via a sidecar file per PDF (*.pdf.sidecar.json)
  • Regenerate sidecars without concatenating (--regenerate-summaries)
  • Exclude specific files or patterns (--exclude)
  • Progress bar while summaries are processed

Installation

With pipx (recommended):

pipx install pdf-concatenator

With pip:

pip install pdf-concatenator

For development:

git clone https://github.com/lorenzowood/pdf-concatenator.git
cd pdf-concatenator
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Quick start

Concatenate all PDFs under a folder:

pdf-concatenator -o submission.pdf contracts/

With summaries (requires LLM config — see below):

pdf-concatenator -o submission.pdf --include-summaries contracts/

Regenerate sidecar summaries only:

pdf-concatenator --regenerate-summaries contracts/

Exclude files:

pdf-concatenator -o submission.pdf \
  --exclude "drafts/*" \
  --exclude "broken.pdf" \
  contracts/

Patterns can be a directory (all PDFs beneath it) or a glob, e.g. contracts/**/*.pdf.

LLM configuration

When using --include-summaries or --regenerate-summaries, create ~/.config/pdf-concatenator:

LLM_API=open_ai
LLM_SERVER=127.0.0.1:28911
LLM_API_KEY=your-api-key
LLM_MODEL=your-model-id
LLM_PROMPT_TITLE_AND_SUMMARY=Your prompt here

The server should expose an OpenAI-compatible /v1/chat/completions endpoint. The whole PDF is sent to the model. If the prompt key is missing but everything else is valid, a default prompt is written to the config file.

Summaries are stored beside each PDF as document.pdf.sidecar.json and reused when the file hash matches.

Output structure

  1. Contents — tree of folders and files; page numbers point to each document's cover page. When summaries are included, a disclaimer appears in the footer.
  2. Cover page per PDF — relative path, optional summary, page number.
  3. Original PDF pages — unchanged (no added page numbers).

If any PDF cannot be read, or summary generation fails when required, the run aborts and no output file is produced.

Splitting large outputs

Upload limits (e.g. 50 MB) can be handled by splitting:

pdf-concatenator -o submission.pdf --max-output-size 50M contracts/

This produces submission_part_1.pdf, submission_part_2.pdf, and so on. Each part stays under the limit. Every part includes the full table of contents; entries in other parts are labelled Part 2, Part 3, etc. Under the Contents heading, each part also notes:

This archive is split into n parts. This is part m.

If everything fits in one file, the original output name is used with no _part_ suffix.

Options

usage: pdf-concatenator [-h] [-o filename] [--include-summaries]
                        [--regenerate-summaries] [--exclude pattern]
                        [--config CONFIG] [--verbose]
                        [--max-output-size SIZE]
                        pattern
Option Description
-o, --output Output PDF path (required unless --regenerate-summaries)
--include-summaries Include summaries in contents and cover pages
--regenerate-summaries Regenerate sidecar files only; do not concatenate
--exclude Glob pattern to exclude (repeatable)
--config Path to LLM config (default: ~/.config/pdf-concatenator)
--verbose Show library warnings while reading/merging PDFs
--max-output-size Split output into parts under this size (e.g. 50M, 2G)

Development

pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pdf_concatenator-1.1.1.tar.gz (23.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pdf_concatenator-1.1.1-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file pdf_concatenator-1.1.1.tar.gz.

File metadata

  • Download URL: pdf_concatenator-1.1.1.tar.gz
  • Upload date:
  • Size: 23.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for pdf_concatenator-1.1.1.tar.gz
Algorithm Hash digest
SHA256 6a26c6222d46a7b3164ca7114bbaa2b3ce4788688e963f5cfe17c3191a5536bb
MD5 d72946355730d8fd98b842f2decd7d9c
BLAKE2b-256 8f6317636c3936baf325ae1aef4994e8e36eaf55c8f137a557a8bd3ba07f0992

See more details on using hashes here.

File details

Details for the file pdf_concatenator-1.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pdf_concatenator-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a39219534614891905c95a82433b361b95ca02680ee6dd0042f97439674cb7eb
MD5 660156a932c7c2b2abac80e1317ff9ae
BLAKE2b-256 a92cb524cf84b10de10d6202f4d883c9538e642fd1fa526ffc5c168a768ae5eb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page