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)
  • Tinted background colours on contents and cover pages so they stand out when scrolling (default: legal-pad yellow)
  • 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. A glob that matches a folder — e.g. Comp* matching Comptons extension/ — includes all PDFs inside it. Quote patterns that contain spaces or shell metacharacters.

Customise the tinted backgrounds on contents and cover pages (hex colours, default #f3f2a3):

pdf-concatenator -o submission.pdf \
  --contents-background "#f3f2a3" \
  --cover-background "#f3f2a3" \
  contracts/

Alternating row stripes in the contents are derived from the contents background (5% black overlay), so they stay readable on any colour.

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. Alternating rows are shaded. When summaries are included, a disclaimer appears in the footer.
  2. Cover page per PDF — relative path, optional summary, page number. Both contents and cover pages use a tinted background (legal-pad yellow by default).
  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]
                        [--contents-background color]
                        [--cover-background color]
                        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)
--contents-background Background colour for contents pages (default: #f3f2a3)
--cover-background Background colour for cover pages (default: #f3f2a3)

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.5.tar.gz (27.4 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.5-py3-none-any.whl (20.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pdf_concatenator-1.1.5.tar.gz
  • Upload date:
  • Size: 27.4 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.5.tar.gz
Algorithm Hash digest
SHA256 6c427e1389514fb825b81754d5fec7d0371ff7a404f6aa417b24413aa46ddeea
MD5 08d1952ff691c6bf0aa258722d9fe1f2
BLAKE2b-256 dc7d1a8d92f77abb24a7b57619a41a5b456567bd8dc87e1b0a04c9903eba4c15

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pdf_concatenator-1.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 1e1da24a0ef5875ae564203a03a17f3c5fd253a6cf27b9febfb04928e24b5750
MD5 287948a921fa5e639be0e986ed484892
BLAKE2b-256 4b6afd005a779ec9c62b1414f1f90083bdb141f9822e750b50fef1ada8362c7c

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