Skip to main content

Licence Gitea Release pre-commit

mirro

mirro logo

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 $EDITOR when possible

  • requires sudo only 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:

  1. finds the newest backup matching the filename,

  2. strips the mirro header from it,

  3. and overwrites the target file with its original contents.

Restore ANY backup

mirro --restore filename.ext.orig.20251110T174400
Restored /path/to/filename.ext from backup filename.ext.orig.20251110T174400

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 GuardUtils package repo

This is the preferred method of installation.

Debian/Ubuntu

1) Import the GPG key

sudo mkdir -p /usr/share/keyrings
curl -fsSL https://repo.sysmd.uk/guardutils/guardutils.gpg | sudo gpg --dearmor -o /usr/share/keyrings/guardutils.gpg

The GPG fingerprint is 0032C71FA6A11EF9567D4434C5C06BD4603C28B1.

2) Add the APT source

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/guardutils.gpg] https://repo.sysmd.uk/guardutils/debian stable main" | sudo tee /etc/apt/sources.list.d/guardutils.list

3) Update and install

sudo apt update
sudo apt install mirro

Fedora/RHEL

1) Import the GPG key

sudo rpm --import https://repo.sysmd.uk/guardutils/guardutils.gpg

2) Add the repository configuration

sudo tee /etc/yum.repos.d/guardutils.repo > /dev/null << 'EOF'
[guardutils]
name=GuardUtils Repository
baseurl=https://repo.sysmd.uk/guardutils/rpm/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://repo.sysmd.uk/guardutils/guardutils.gpg
EOF

4) Update and install

sudo dnf upgrade --refresh
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 mirro as root, or
  • add the path to mirro to the secure_path parameter in /etc/sudoers. For example, where /home/user/.local/bin is where mirro is:
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://git.sysmd.uk/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.

Support

If you find mirro useful, consider supporting its development:

Support me on Ko-fi

Metadata

Release files for mirro 0.6.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mirro 0.6.4
File Size Uploaded Provenance Actions
mirro-0.6.4.tar.gz 19.8 kB Without provenance Details for mirro-0.6.4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mirro 0.6.4
File Interpreter ABI Platform Actions
mirro-0.6.4-py3-none-any.whl Python 3 none any Details for mirro-0.6.4-py3-none-any.whl

Total release size: 40.8 kB

Release files / mirro-0.6.4.tar.gz

Download URL mirro-0.6.4.tar.gz
Size 19.8 kB
Tags Source
SHA-256 checksum
How to use checksums
94d4968da9ab10b43c83b4b7494c33ade9ddfd22db4f7a35a1dba0c49970f1bb
BLAKE2b-256 checksum
How to use checksums
fe81aa3ec1951e42b6d1ca2a8373e333c7e2d4b74a299704ad5adacb22f32cca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.0 CPython/3.14.7 Linux/7.2.8-100.fc43.x86_64

Release files / mirro-0.6.4-py3-none-any.whl

Download URL mirro-0.6.4-py3-none-any.whl
Size 20.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eca5d6b0ee62bc165e0705f64e352a5fc16bee21290ea457af187939d92898aa
BLAKE2b-256 checksum
How to use checksums
79094e2b9ea96bf43718e580fc93647cdff58af8e136a3e6497936d1736fb4d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.0 CPython/3.14.7 Linux/7.2.8-100.fc43.x86_64

Security for mirro 0.6.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page