Declarative local file pipelines in Python
Project description
Filemindr
Declarative local file automation using profiles.
Filemindr lets you describe what should happen to your files, not how.
You define rule pipelines in YAML, group them into profiles, and run them safely through a clean CLI.
Built as a learning and portfolio project with strong focus on:
- predictable behavior
- safety by default
- excellent CLI DX
Features
- Profile-based configuration in
~/.filemindr - Declarative YAML rules
- Rule engine with priority, where the highest match wins
- Match by:
- file extension
- filename regex
- file age with
older_than_days
- Actions:
move_tocopy_torename_templatestem_safeplaceholder support
- Global and per-rule conflict policies:
renameskipoverwritetrash
- Dry-run mode
- Explain mode
- Watch mode
- Run history with
list,show,prune, andclear - Final summary report
- Structured logging with
INFOandDEBUG - Cross-platform support for Windows, macOS, and Linux
Installation
pipx install filemindr
or
pip install filemindr
Development setup:
uv sync --extra dev
Profiles
Instead of a single global YAML, Filemindr uses profiles.
Each profile lives in:
~/.filemindr/rules/<profile>/rules.yaml
And all profiles are registered in:
~/.filemindr/profiles.yaml
This allows:
- multiple setups such as
home,work, ormedia - explicit selection via CLI
- zero ambiguity about which config is running
Quick Start
Create your first profile:
filemindr profile init home
This creates:
~/.filemindr/
|-- profiles.yaml
`-- rules/
`-- home/
`-- rules.yaml
Open and edit the rules:
filemindr profile open home
Example rules.yaml:
source: ~/Downloads
default_target: ~/Downloads/others
conflict_policy: rename
rules:
- name: invoices
priority: 100
match:
extensions: ["pdf"]
regex: "(?i)invoice|nota|nf"
action:
move_to: ~/Downloads/finance/invoices
- name: dated-pdfs
priority: 70
match:
extensions: ["pdf"]
action:
move_to: ~/Downloads/archive/{yyyy}/{mm}
rename_template: "{stem}_{yyyy}-{mm}{suffix}"
- name: images
priority: 40
match:
extensions: ["jpg", "png", "webp"]
action:
move_to: ~/Downloads/images
Important notes:
- Rule priority matters. If two rules match the same file, the higher priority wins.
rename_templateonly defines the final file name, not folders.move_toandcopy_tocan use templates in the destination path.
Supported template fields:
{name}{stem}{stem_safe}{suffix}{ext}{parent}{yyyy}{mm}{dd}
Preview:
filemindr run -p home --dry-run
Verbose preview:
filemindr run -p home --dry-run --log-level DEBUG
Run:
filemindr run -p home
Profile Commands
Create:
filemindr profile init home
List:
filemindr profile list
Show path:
filemindr profile show home
Open in editor:
filemindr profile open home
Remove completely:
filemindr profile remove home
Watch Mode
Continuous:
filemindr watch -p home
Single batch:
filemindr watch -p home --once
Explain Mode
Explain a directory:
filemindr explain -p home ~/Downloads
Explain a single file with spaces in the path:
filemindr explain -p home "C:\Users\you\Downloads\Day Trade-2025.pdf"
Explain with more detail about matched rules, templates, and rendered names:
filemindr explain -p home "C:\Users\you\Downloads\Day Trade-2025.pdf" --verbose
Example output:
Day Trade-2025.pdf -> C:\Users\you\Downloads\archive\2026\03\day-trade-2025_2026-03.pdf [MOVE] rule=dated-pdfs prio=70 policy=rename (source=C:\Users\you\Downloads ext=.pdf matched_rule=dated-pdfs matched_candidates=dated-pdfs(prio=70) target_template=~/Downloads/archive/{yyyy}/{mm} rename_template={stem_safe}_{yyyy}-{mm}{suffix} rendered_name=day-trade-2025_2026-03.pdf dest_exists=NO conflict=none)
Example of a normalized file name:
rename_template: "{stem_safe}_{yyyy}-{mm}{suffix}"
Validate
filemindr validate -p home
Doctor
filemindr doctor
History
List recent runs:
filemindr history list
Include legacy/internal entries too:
filemindr history list --all
Inspect one run:
filemindr history show <run_id>
Example output:
run_id: 5ffb71382410
command: run
profile: home
status: completed
dry_run: True
started_at: 2026-03-13T16:54:18.073692+00:00
finished_at: 2026-03-13T16:54:18.115000+00:00
source: C:\Users\you\Downloads
config_path: C:\Users\you\.filemindr\rules\home\rules.yaml
counts:
planned_move: 55
events:
- planned_move: C:\Users\you\Downloads\Day Trade-2025.pdf -> C:\Users\you\Downloads\archive\2026\03\day-trade-2025_2026-03.pdf
Prune old history entries:
filemindr history prune --days 7
Clear all stored history:
filemindr history clear --yes
Filemindr also prunes old history automatically on pipeline runs, keeping the last 7 days by default.
Undo
Undo one recorded run:
filemindr undo <run_id>
Undo v1 only reverts recorded move operations. It does not restore trash, overwrite, or copy events.
Example workflow:
filemindr run -p home
filemindr history list
filemindr undo <run_id>
Conflict Policy
Supported values:
renameskipoverwritetrash
Development
Install development dependencies:
uv sync --extra dev
Run tests:
uv run pytest -q
Release notes are versioned in the repository under release-notes/ and consumed automatically by the publish workflow.
Status
Current release line: 1.3.x
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 filemindr-1.3.0.tar.gz.
File metadata
- Download URL: filemindr-1.3.0.tar.gz
- Upload date:
- Size: 50.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97fd9340de37a29de522c8ebe53fde0931c10ef798a18b1e55aaa8ffcaeb94ab
|
|
| MD5 |
0f8ff72a2f4280805fac78c0604f043e
|
|
| BLAKE2b-256 |
870aa2dc75300f23913b0ffe06fe620da81350892577b83855f46ad42cca689f
|
File details
Details for the file filemindr-1.3.0-py3-none-any.whl.
File metadata
- Download URL: filemindr-1.3.0-py3-none-any.whl
- Upload date:
- Size: 21.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c74446d13afbd40f1385057dea0788ae0f122e50169641d19fece7ee5539d00
|
|
| MD5 |
85a404f784c9035547ffdd9d28ea4321
|
|
| BLAKE2b-256 |
da9a3cf3076fd2062c7b757f4c518a5abb94ea9a2581f25594f37ca618dad1d5
|