pdfxz
Safe, fast, and intelligent PDF compression from your terminal.
pdfxz is a dual-mode PDF compression tool powered by Ghostscript. It offers a beautiful, keyboard-driven Terminal UI (TUI) for everyday use, and a robust Command-Line Interface (CLI) for scripts, batch processing, and automation.
Interactive Terminal UI (TUI)
✨ Features
- Dual-Mode Interface: Use the interactive TUI for visual workflows or the CLI for headless automation.
- Smart & Safe Defaults: Original files are never touched. Output collisions are automatically resolved. Partial files are cleaned up on failure.
- Batch Processing: Compress a single file or recursively process entire directory trees while preserving folder structures.
- Explicit Quality Profiles: Five carefully tuned compression profiles (from archival to maximum compression) using explicit Ghostscript parameters, ensuring consistent results across different Ghostscript versions.
- Parallel Execution: Speed up large batch jobs using multi-threaded Ghostscript workers (
--jobs). - Intelligent Validation: Verifies the
%PDF-magic header before processing, skipping corrupted or fake PDFs gracefully. - Cross-Platform: Fully supported on Linux, macOS, and Windows.
📦 Installation
pdfxz requires Python 3.10+ and a working installation of Ghostscript.
1. Install Ghostscript
Ghostscript is the engine that powers the compression. It must be installed on your system first.
macOS (Homebrew):
brew install ghostscript
Ubuntu / Debian:
sudo apt update && sudo apt install ghostscript
Fedora:
sudo dnf install ghostscript
Arch Linux:
sudo pacman -S ghostscript
Windows:
Download the official AGPL/GPL installer from ghostscript.com. Ensure the installation directory (e.g., C:\Program Files\gs\bin) is added to your system PATH.
Verify installation:
gs --version # macOS/Linux
gswin64c --version # Windows
2. Install pdfxz
From PyPI (Recommended):
pip install pdfxz
From Source:
git clone [https://github.com/amyrhexa/pdfxz.git](https://github.com/amyrhexa/pdfxz.git)
cd pdfxz
pip install .
🚀 Quick Start
Interactive TUI
Simply run pdfxz without any arguments to launch the interactive interface:
pdfxz
┌──────────────────────────────────────────────────────────┐
│ P D F X Z │
│ PDF Compression Utility │
├──────────────────────────────────────────────────────────┤
│ INPUT │
│ [ ~/Documents/papers ] [ Browse... ] │
│ │
│ OUTPUT │
│ [ ~/Documents/compressed ] [ Browse... ] │
│ │
│ QUALITY │
│ ▰▰▰▯▯ Balanced │
│ │
│ [ Compress PDFs ] │
└──────────────────────────────────────────────────────────┘
TUI Highlights:
- Use
Tabto navigate andEnterto select. - Built-in directory browser (
Browse...) eliminates manual path typing. - Live progress tracking, ETA, and per-file status reporting.
- Press
Escat any time to safely cancel a running batch.
Command-Line Interface (CLI)
For scripts and quick tasks, pass the input path directly:
# Compress a single file (creates paper_compressed.pdf)
pdfxz paper.pdf
# Compress a directory recursively
pdfxz ~/Documents/papers -o ~/Documents/compressed -r
📖 CLI Usage Guide
Basic Operations
| Goal | Command |
|---|---|
| Compress one file | pdfxz input.pdf |
| Specify output file | pdfxz input.pdf -o output.pdf |
| Compress a folder | pdfxz ./papers -o ./compressed |
| Recursive folder scan | pdfxz ./papers -o ./compressed -r |
| Force create missing dirs | pdfxz input.pdf -o ./new/dir/out.pdf -p |
Advanced Operations
Parallel Processing: Speed up large batches by running multiple Ghostscript instances concurrently.
pdfxz ./huge_archive -o ./compressed -r --jobs 4
Strict Scripting Mode:
Prevent the TUI from accidentally launching in automated environments (e.g., cron jobs, CI/CD). If INPUT is missing, it will exit with an error instead of opening the UI.
pdfxz --no-tui input.pdf -o output.pdf
Debugging: Enable verbose logging to troubleshoot Ghostscript errors.
pdfxz input.pdf --debug
Full CLI Reference
usage: pdfxz [INPUT] [OUTPUT] [options]
Positional:
INPUT A PDF file or a directory containing PDFs.
OUTPUT Output PDF file or directory (optional).
Options:
-o, --output PATH Output PDF file or directory.
-p, --parents Create missing output directories (like mkdir -p).
-q, --quality LEVEL Compression profile (default: balanced).
-r, --recursive Recurse into subdirectories.
--overwrite Allow overwriting an existing output file.
--jobs N Number of parallel Ghostscript jobs to run (default: 1).
--no-tui Never launch the interactive TUI.
--debug Enable verbose debug logging.
--version Show version and exit.
🎚️ Compression Profiles
pdfxz avoids Ghostscript's vague /screen or /ebook presets. Instead, it uses explicit, version-independent parameters for predictable results.
| Profile | Key | Best For | Image Downsampling |
|---|---|---|---|
| Maximum Quality | maximum |
Archival, print-ready documents | Minimal (300+ DPI) |
| High Quality | high |
High-res screen viewing, good print | Moderate (200 DPI) |
| Balanced (Default) | balanced |
Everyday sharing, email attachments | Standard (150 DPI) |
| Strong | strong |
Mobile viewing, saving space | Aggressive (120 DPI) |
| Maximum Compression | maximum-compression |
Strict file-size limits, drafts | Extreme (72 DPI) |
Note: Actual compression ratios depend heavily on the PDF's content. Scanned image-heavy PDFs will shrink dramatically, while text-only PDFs may see minimal changes.
🛡️ Safety & Reliability Guarantees
pdfxz is engineered to be strictly non-destructive.
- Input Immutability: Your original PDF files are never modified, moved, or deleted.
- Collision Avoidance:
- In the TUI, if an output file exists,
pdfxzautomatically generates a unique name (e.g.,report_compressed (2).pdf). - In the CLI, existing outputs are protected. You must explicitly pass
--overwriteto replace them.
- In the TUI, if an output file exists,
- Same-Path Rejection: The engine will refuse to run if the input and output paths resolve to the exact same file.
- Atomic Cleanup: If Ghostscript crashes, times out, or the user cancels the operation, any partially written output file is immediately deleted.
- Structure Preservation: When compressing directories recursively, the output mirrors the input's folder structure. This prevents files with identical names in different subfolders from overwriting each other.
- Signature Validation: Files are checked for the
%PDF-magic header. Corrupted files or text files mistakenly named.pdfare skipped and reported, rather than causing the batch to crash.
⚙️ Configuration & Environment Variables
| Variable | Description |
|---|---|
PDFXZ_GS_PATH |
Explicit path to the Ghostscript executable. Bypasses automatic PATH discovery. |
PDFXZ_CONFIG_DIR |
Override the default configuration directory (used for saving TUI themes). |
Default Config Locations:
- Linux/macOS:
~/.config/pdfxz/config.json - Windows:
%APPDATA%\pdfxz\config.json
🛠️ Development & Testing
We welcome contributions! The test suite uses a mock Ghostscript executable, meaning you can run tests without having Ghostscript installed on your development machine.
Setup
git clone [https://github.com/amyrhexa/pdfxz.git](https://github.com/amyrhexa/pdfxz.git)
cd pdfxz
# Create and activate virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
Running Tests
The project uses pytest and pytest-asyncio (for TUI testing via Textual's pilot).
# Run all tests
pytest
# Run with coverage
pytest --cov=pdfxz
# Run only CLI tests
pytest tests/test_cli.py
Project Architecture
pdfxz/
├── src/pdfxz/
│ ├── app.py # Textual TUI screens and widgets
│ ├── cli.py # Argparse CLI entry point
│ ├── compressor.py # Ghostscript subprocess wrapper & safety logic
│ ├── workers.py # ThreadPoolExecutor batch orchestration
│ ├── scanner.py # File discovery and %PDF- header validation
│ ├── profiles.py # Explicit Ghostscript parameter definitions
│ ├── models.py # Dataclasses for Results and State
│ ├── formatting.py # Pure functions for UI/CLI text rendering
│ └── utils.py # Path resolution and GS discovery
├── tests/
│ ├── fixtures/ # fake_gs.py (Mock Ghostscript binary)
│ ├── test_app.py # Async TUI integration tests
│ └── test_*.py # Unit tests for all modules
└── pyproject.toml # Project metadata and dependencies
📄 License
This project is licensed under the MIT License. See the LICENSE file for details.
Disclaimer: pdfxz is an independent tool and is not affiliated with or endorsed by Artifex Software, Inc. (the developers of Ghostscript).
Metadata
Release files for pdfxz 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pdfxz-1.0.0.tar.gz | 40.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pdfxz-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.3 kB
Release files / pdfxz-1.0.0.tar.gz
| Download URL | pdfxz-1.0.0.tar.gz |
|---|---|
| Size | 40.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c51241ff908f432c39db228a40a806c617495f6a548dc14f4eb3e5c019e949e
|
|
BLAKE2b-256 checksum How to use checksums |
6eb1da65b465c9a82c93f444b9adafbbbe0c0526892f8d09449daf137b4066ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency logRelease files / pdfxz-1.0.0-py3-none-any.whl
| Download URL | pdfxz-1.0.0-py3-none-any.whl |
|---|---|
| Size | 35.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6ab54207e9f28a72bad2b12c9f3d25f8c18bf9f71f8858f16d88c2aa1ef3a9c3
|
|
BLAKE2b-256 checksum How to use checksums |
d1eb1944483a5fbc0202e88e23cc67700f4341a464caa31b9e82133f95cd6baa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.
Transparency log