Automatically rename PDFs and images using a vision-language model (Qwen3.5) running locally. Perfect for organizing document collections without cloud dependencies.
- Local AI Processing: Uses Qwen3.5 directly via
llama.cppfor privacy and offline usage. No external API keys needed. - Auto-Download & Auto-Size: Automatically fetches the right model from HuggingFace based on your machine's memory —
unsloth/Qwen3.5-27B-GGUF(≥30 GB RAM),unsloth/Qwen3.5-9B-GGUF(≥16 GB), orunsloth/Qwen3.5-4B-GGUFotherwise. Override with--model-size. - High Accuracy: Specifically optimized for reading and summarizing invoices, receipts, and forms.
- Smart Formatting: Extracts dates, descriptions, and IDs into consistent filenames (
YYYY-MM-DD_Description_ID.pdf). - Receipt Mode: specialized formatting for thermal receipts.
- Fast Caching: SQLite-backed caching prevents re-analyzing identical files, saving time on subsequent runs.
- Multi-threaded: Processes multiple files simultaneously for significantly better throughput.
- Python 3.12+
- Poppler: Required for converting PDF pages to images.
macOS (Homebrew)
brew install popplerUbuntu/Debian
sudo apt-get install poppler-utilsWindows
Download and extract the latest poppler-windows, and add the bin/ directory to your system PATH.
We recommend installing pdf-renamer globally from your local checkout using uv. This keeps dependencies such as llama-cpp-python isolated from your other Python projects while making the pdf-renamer command available on your PATH.
uv tool install --python 3.12 --editable .The editable installation reflects source-code changes immediately. Reinstall it after changing project dependencies or packaging metadata:
uv tool install --python 3.12 --editable --force .To modify the code, use uv to create and synchronize the project environment:
# Clone the repository
git clone https://github.com/wongws11/pdf-renamer.git
cd pdf-renamer
# Create the environment and install the application and development dependencies
uv sync
# Run the test suite
uv run pytestRun the tool on a single file or a directory of PDFs:
# Dry run on a single file (preview changes)
pdf-renamer document.pdf
# Actually rename the file
pdf-renamer document.pdf -e
# Process an entire directory of PDFs recursively and apply changes
pdf-renamer ./invoices/ -e -rNote: On the first run, it will download the Qwen3.5 model selected for your machine (~4 GB for 4B, ~7 GB for 9B, ~18 GB for 27B).
| Argument | Short | Type | Default | Description |
|---|---|---|---|---|
input_path |
— | Path | — | Required. Input directory or PDF/JPG/PNG file path |
--output |
-o |
Path | Same as input | Output directory for renamed files |
--execute |
-e |
Flag | False | Actually rename files (default is dry-run mode) |
--recursive |
-r |
Flag | False | Recursively process files in subdirectories |
--receipt |
— | Flag | False | Receipt mode: use date_storename_description_id format |
--verbose |
-v |
Flag | False | Enable verbose logging (shows model loading details) |
--delay |
-d |
Float | 0.5 | Delay between file processing in seconds |
--workers |
-w |
Integer | 4 | Number of worker threads for parallel processing |
--save-log |
— | Path | — | Save processing results to JSON file |
--no-cache |
— | Flag | False | Disable cache (re-analyze all PDFs, slower) |
--cache-path |
— | Path | ~/.pdf-renamer/cache.db |
Custom path to cache database |
--cache-stats |
— | Flag | False | Show cache statistics and exit |
--no-image |
— | Flag | False | Exclude JPG and PNG files from processing |
--model-size |
— | Choice | auto |
Built-in vision model size: auto, 27b, 9b, or 4b |
# Process all PDFs in a directory (dry-run)
pdf-renamer ./documents/
# Process and rename files
pdf-renamer ./documents/ -e
# Process recursively with custom output directory
pdf-renamer ./documents/ -e -r -o ./renamed/
# Process receipts with receipt-specific format
pdf-renamer ./receipts/ -e --receipt
# Verbose output with custom delay between files
pdf-renamer ./documents/ -e -v --delay 1.0
# Process with custom number of workers
pdf-renamer ./documents/ -e -w 8
# Save results to JSON and use custom cache location
pdf-renamer ./documents/ -e --save-log results.json --cache-path /tmp/cache.db
# Show cache statistics
pdf-renamer --cache-stats
# Force re-analysis (skip cache)
pdf-renamer ./documents/ -e --no-cache
# Exclude images from processing
pdf-renamer ./mixed_files/ -e --no-image
# Force a specific model size instead of auto-detection
pdf-renamer ./documents/ -e --model-size 9bThe project is structured into modular components:
cli.py&main.py: CLI parsing and program entry pointrenamer.py: Orchestrates the renaming logic and handles cache interactionspdf_utils.py: Contains core utilities including theLLMAnalyzer(managing thellama-cpp-pythonsession) and file operationsstats.py: Tracks success/failure/skip statisticslogger.py: Custom logging utility
ERROR: Model failed to load!
Solution: Ensure you have enough disk space (at least 3GB free) and that your system meets the requirements for running local LLMs. If the download is interrupted, clearing your Hugging Face cache (~/.cache/huggingface/hub/) and retrying may help.
pdf2image.exceptions.PDFInfoNotInstalledError: Unable to get page count.
Solution: This happens when Poppler is not installed or not in your system PATH. See the Prerequisites section above.
- HuggingFace - For model distribution
- llama.cpp & llama-cpp-python - For running local LLMs efficiently
- Qwen - For their incredible open source vision models