🚀 retentions 1.3: Smarter Retention, Fewer Surprises

With retentions 1.3, the tool grows up another notch.

The core idea hasn’t changed:
explicit, deterministic retention rules for plain files — no magic, no guessing.

But version 1.3 adds a few very practical features that solve real-world annoyances many backup setups quietly suffer from.


🧰 What’s New in retentions 1.3 (since 1.0)

🧨 Delete companion files (--delete-companions)

This is the big one.

retentions can now delete companion files automatically when a primary file is deleted — based on prefix or suffix rules.

Typical examples:

  • checksums (.sha256, .md5)
  • signatures
  • metadata files
  • sidecar formats created by backup tools

Rules are explicit and safe:

  • companions are only deleted together with their primary file
  • protected or retained files are never touched
  • integrity checks ensure companions cannot accidentally delete kept files

🧹 Skip tiny files early (--skip-by-filesize)

Another very pragmatic addition.

Files smaller than a given size can now be skipped – and directly marked for deletion – before retention buckets are even built.

This is useful for:

  • aborted backups
  • zero-byte or near-zero files
  • placeholder artifacts

📁 Folder Mode (retention for backup directories)

Folder mode allows retentions to treat directories as retention units, instead of individual files.

This is useful for:

  • snapshot-style backups
  • tools that create one folder per backup run
  • backup sets that should be deleted atomically

The folder’s “age” is derived explicitly (e.g. from the youngest file inside).
Deletion removes the entire folder, not individual files.

Folder mode is deliberately incompatible with companion deletion and filesize skipping — it operates on complete backup sets.


🧠 Retention logic stays explicit

All the 1.0 fundamentals still apply:

  • time buckets: hours, days, weeks, months, quarters, 13-week blocks, years
  • optional --last N
  • post-retention filters (--max-files, --max-size, --max-age)
  • dry-run, list-only, lock-file safety
  • detailed decision logging

Nothing became implicit.
Nothing became “smart” behind your back.


🧪 Four Real-World Examples

1) Delete backups and their checksum files (dry-run)

Bash
retentions /data/backups '*.tar.gz' -d 7 -w 4 --delete-companions 'suffix:tar.gz:sha256,md5' -X -V info

When a backup.tar.gz is deleted, backup.tar.gz.sha256 and backup.tar.gz.md5 go with it – and only then.


2) Keep the newest backups, but clean up companions too

Bash
retentions /data/backups '*.sql.gz' -l 5 --delete-companions 'suffix:.sql.gz:.sig' -V info

Newest backups are pinned by --last 5. Older ones are removed – including their .sig files.

Retained files keep their companions implicitly.


3) Ignore broken tiny files before retention kicks in

Bash
retentions /data/backups '*.zst' -d 10 -w 6 --skip-by-filesize 2K -V info

Any backup smaller than 2 KB is skipped and deleted early – before it can steal a retention bucket.

This avoids retaining garbage files and deleting valid ones later.


4) Retention for directory-based backups (folder mode)

Bash
retentions /data/backups 'backup-*' --folder-mode youngest-file -d 7 -w 4 -m 6 -V info

Each backup-* directory is treated as one retention unit.
Retention decisions are based on the newest file inside each folder.

Deletion removes the entire backup directory in one step.


🧭 Why 1.3 Matters

retentions 1.3 doesn’t add complexity —
it removes mental overhead.

You no longer need:

  • custom scripts for sidecar files
  • pre-cleanup jobs for broken backups
  • post-mortem reasoning about “why this tiny file survived”

Retention decisions stay:

  • explicit
  • explainable
  • reproducible

And now they finally handle the messy details that real backup directories always contain.