CLI tool that renames local files using AI-powered metadata extraction
Project description
renamr
AI-powered CLI that renames files based on their content.
What it does
Scanned documents, downloads, and exported files often arrive with useless names like scan_001.pdf or IMG_5847.jpg. renamr reads each file — extracting text from PDFs, rendering pages as images for vision models, or encoding photos directly — sends a preview to an LLM, and renames the file to a structured format based on the content it actually finds.
scan_001.pdf -> 240115_ACME_Rechnung.pdf
IMG_5847.jpg -> 241203_DeutschePost_Zustellbenachrichtigung.jpg
invoice_download.pdf -> 250110_Amazon_Bestellbestaetigung.pdf
Only the filename changes. Files are never modified.
Features
- Content-aware renaming via any LiteLLM-supported provider (OpenAI, OpenRouter, Anthropic, local models)
- PDF text extraction for text-based documents
- Vision model support for scanned PDFs and image files
- iCloud evicted file handling — triggers download via
brctlbefore processing (macOS) - Dry-run mode to preview renames without touching files
- Undo the last run with a single command
- Configurable output template (
{date}_{sender}_{subject}), file extensions, and system prompt - Optional in-place PDF compression after renaming
Installation
Requires Python 3.12 or newer.
pip install renamr
uv tool install renamr
Quick Start
# Create config.toml and data/ in the current directory
renamr init
# Set your API key
export OPENAI_API_KEY="your-key"
# Preview renames without touching any files
renamr run --dry-run
# Rename files
renamr run
# Undo the last run
renamr undo
Override the inbox without editing config:
renamr run --inbox ~/Documents/inbox --dry-run
Configuration
renamr init creates a config.toml in the current directory. The full set of options:
inbox_path = "."
file_extensions = [".pdf", ".jpg", ".jpeg", ".png", ".txt"]
recursive = false
filename_template = "{date}_{sender}_{subject}"
# rename_prompt = "..." # override the system prompt sent to the model
[llm]
model = "gpt-4o-mini"
api_base = "" # leave empty for direct OpenAI; set for OpenRouter or local endpoints
temperature = 0.2
max_retries = 2
timeout = 60
[compress]
enabled = false # re-render PDFs at lower DPI after renaming
dpi = 150
jpeg_quality = 80
[logging]
level = "INFO"
json_logs = false
filename_template supports three placeholders: {date}, {sender}, {subject}. The date is extracted from document content when available, falling back to the file's creation timestamp.
data/undo.json is stored relative to the config file. Always run renamr run and renamr undo with the same --config path, or from the same directory when using the default.
Switching providers. Change model and set api_base. For OpenRouter:
[llm]
model = "openrouter/openai/gpt-4o-mini"
api_base = "https://openrouter.ai/api/v1"
Then set OPENROUTER_API_KEY instead of OPENAI_API_KEY. Any provider supported by LiteLLM works without code changes.
Customizing the prompt. The default system prompt extracts sender, subject, and date from documents and handles German and English. To override, uncomment rename_prompt in config.toml and replace it with your own. The full default is in src/renamr/models.py.
Privacy & Security
[!WARNING] renamr sends file content to an external LLM API.
Depending on your configuration, this includes:
- Extracted text from PDF and
.txtfiles- Rendered page images from scanned PDFs
- Raw image data from
.jpg,.png, and other supported image files- Original filenames and file timestamps
This data is transmitted to your configured LLM provider and may be processed on remote servers. Do not run renamr on sensitive or confidential files unless you have reviewed and accepted your provider's data handling policy.
Run
renamr run --dry-runfirst to confirm which files will be processed.
Additional notes:
- Always use an
https://endpoint forapi_base. Anhttp://URL sends file content unencrypted. - Keep
data/undo.jsonprivate on shared systems — it contains the file paths from the last run. - Avoid sharing verbose log output publicly; failed auth responses may include API key fragments.
Maintenance
This tool is maintained for personal use and published as-is. Bug reports welcome via Issues. No guaranteed response time. PRs accepted if they align with the project's scope.
See CONTRIBUTING.md for development setup.
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
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 renamr-1.0.1.tar.gz.
File metadata
- Download URL: renamr-1.0.1.tar.gz
- Upload date:
- Size: 159.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afce64ffd4c9a4c61b71e5cb3827206535c98a000f50fe29c489726087394b4f
|
|
| MD5 |
43c8675f08f2698fd5e376f8c4fe2b4d
|
|
| BLAKE2b-256 |
4400bdf7ecb4f291eeb3fe541aa15ba720592af8047b4642461626d74b9b8cc8
|
Provenance
The following attestation bundles were made for renamr-1.0.1.tar.gz:
Publisher:
release.yml on spignotti/renamr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
renamr-1.0.1.tar.gz -
Subject digest:
afce64ffd4c9a4c61b71e5cb3827206535c98a000f50fe29c489726087394b4f - Sigstore transparency entry: 1096017629
- Sigstore integration time:
-
Permalink:
spignotti/renamr@c2c08600a0beedb112d99f3e6d12ba73803529d8 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/spignotti
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c2c08600a0beedb112d99f3e6d12ba73803529d8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file renamr-1.0.1-py3-none-any.whl.
File metadata
- Download URL: renamr-1.0.1-py3-none-any.whl
- Upload date:
- Size: 18.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7bdeb04b50a5308ce147cc897bf48f83823193dcfa5394d2b0ce8a046233946
|
|
| MD5 |
b642b884f7d02169827222adf0bc695a
|
|
| BLAKE2b-256 |
9c64c7d84ca906dab1cb09d24a89d669576650174ac56641cda913fd98aa4af9
|
Provenance
The following attestation bundles were made for renamr-1.0.1-py3-none-any.whl:
Publisher:
release.yml on spignotti/renamr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
renamr-1.0.1-py3-none-any.whl -
Subject digest:
f7bdeb04b50a5308ce147cc897bf48f83823193dcfa5394d2b0ce8a046233946 - Sigstore transparency entry: 1096017644
- Sigstore integration time:
-
Permalink:
spignotti/renamr@c2c08600a0beedb112d99f3e6d12ba73803529d8 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/spignotti
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c2c08600a0beedb112d99f3e6d12ba73803529d8 -
Trigger Event:
push
-
Statement type: