Skip to main content

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_to
    • copy_to
    • rename_template
    • stem_safe placeholder support
  • Global and per-rule conflict policies:
    • rename
    • skip
    • overwrite
    • trash
  • Dry-run mode
  • Explain mode
  • Watch mode
  • Run history with list, show, prune, and clear
  • Final summary report
  • Structured logging with INFO and DEBUG
  • 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, or media
  • 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_template only defines the final file name, not folders.
  • move_to and copy_to can 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.


Conflict Policy

Supported values:

  • rename
  • skip
  • overwrite
  • trash

Development

Install development dependencies:

uv sync --extra dev

Run tests:

uv run pytest -q

Status

Current release line: 1.2.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

filemindr-1.2.0.tar.gz (49.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

filemindr-1.2.0-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

File details

Details for the file filemindr-1.2.0.tar.gz.

File metadata

  • Download URL: filemindr-1.2.0.tar.gz
  • Upload date:
  • Size: 49.2 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

Hashes for filemindr-1.2.0.tar.gz
Algorithm Hash digest
SHA256 6f7731c6b90b912f0162230448c9a94ea4e4d1c8a1f1522b94406bfd448a7384
MD5 55c5ee96deed6d2294c3c5e63b66e80e
BLAKE2b-256 47ed73976382c9779d75c0da31836f2efe8454d0b729439e6890b97fb7b4db0a

See more details on using hashes here.

File details

Details for the file filemindr-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: filemindr-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 21.1 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

Hashes for filemindr-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 66f6985ac002c8a8d555154037e2d964c4b574838071dee013c3bd5db8fe29d2
MD5 55efbf1429525825560bdd0cdf845e5b
BLAKE2b-256 8cf04fbeaaea2b9a05f85491a759fde944b383cf96eb52b8e35dcbdff2399811

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