Add --status flag, TAB completion with argcomplete, update README, update tests
mirro
mirro is a tiny safety-first editing wrapper for text files. You edit a temporary file, mirro detects whether anything changed, and if it did, it saves a backup of the original before writing your changes.
Why mirro?
Well... have you ever been in the “ugh, I forgot to back this up first” situation?
No?
Stop lying... 🥸
mirro gives you a built-in safety net:
-
never edits the real file directly
-
detects whether the edit actually changed content
-
creates a timestamped backup only when changes occurred
-
clearly labels backups so you know exactly what they came from
-
respects the user’s
$EDITORwhen possible -
requires
sudoonly when actually needed -
accepts most of your favourite editor's flags
It’s simple, predictable, and hard to misuse.
I mean... the only thing you need to remember is to use it.
How it works
mirro reads the original file (or pre-populates new files with a friendly message).
It writes that content into a temporary file.
It launches your $EDITOR to edit the temp file.
When the editor closes, mirro compares old vs new.
If nothing changed:
file hasn't changed
If changed:
file changed; original backed up at: ~/.local/share/mirro/ (or /root/.local/share/mirro/ under sudo)
Backed up files include a header:
# ---------------------------------------------
# mirro backup
# Original file: /path/to/whatever.conf
# Timestamp: 2025-11-10 17:44:00 UTC
# ---------------------------------------------
So you never lose track of the original location.
Backup directory
By default all the backups will be stored at:
~/.local/share/mirro/
so under sudo:
/root/.local/share/mirro/
Backups are named like:
filename.ext.orig.20251110T174400
Functionalities
List all backup files stored in your backup directory.
mirro --list
Output includes permissions, owner/group, timestamps, and backup filenames.
Restore the most recent backup for a given file.
mirro --restore-last ~/.config/myapp/config.ini
This:
-
finds the newest backup matching the filename,
-
strips the mirro header from it,
-
and overwrites the target file with its original contents.
Remove old backup files.
mirro --prune-backups
This removes backups older than the number of days set in MIRRO_BACKUPS_LIFE.
Remove backups older than N days
mirro --prune-backups=14
This keeps the last 14 days of backups and removes everything older.
Remove all backups
mirro --prune-backups=all
This deletes every backup in the backup directory.
Environment Variable
MIRRO_BACKUPS_LIFE controls the default number of days to keep when using mirro --prune-backups.
Its default value is 30 if not set otherwise.
export MIRRO_BACKUPS_LIFE=7
Backups older than 7 days will be removed.
Invalid or non-numeric values fall back to 30 days.
Note: a value of 0 is invalid.
Built-in diff
This shows a git-like diff of the current file version and any of that file backups.
mirro --diff file file.orig.20251121T163121
Shows current directory's history
Shows which files in the current directory have edit history recorded by mirro. For each file, it prints how many revisions exist and when the latest one was saved.
mirro --status
Files with history in /foo/bar:
baz.conf (3 revisions, latest: 2025-01-12 14:03 UTC)
Installation
From package manager
This is the preferred method of installation.
Ubuntu 22.04 and 24.04
sudo add-apt-repository ppa:mdaleo/mirro
sudo apt update
sudo apt install mirro
Fedora 41, 42, 43
sudo dnf copr enable mdaleo/mirro
sudo dnf install mirro
From PyPI
NOTE: To use mirro with sudo, the path to mirro must be in the $PATH seen by root.
Either:
- install
mirroasroot, or - add the path to
mirroto thesecure_pathparameter in/etc/sudoers. For example, where/home/user/.local/binis wheremirrois:
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/user/.local/bin"
Install with:
pip install mirro
From this repository
git clone https://github.com/guardutils/mirro.git
cd mirro/
poetry install
TAB completion
Add this to your .bashrc
eval "$(register-python-argcomplete mirro)"
And then
source ~/.bashrc
How to run the tests
-
Clone this repository
-
Ensure you have Poetry installed
-
Run
poetry run pytest -vvvv --cov=mirro --cov-report=term-missing --disable-warnings
pre-commit
This project uses pre-commit to run automatic formatting and security checks before each commit (Black, Bandit, and various safety checks).
To enable it:
poetry install
poetry run pre-commit install
This ensures consistent formatting, catches common issues early, and keeps the codebase clean.