Skip to main content

megavers

CI PyPI Downloads Python License: MIT

Tools for analyzing and selectively pruning file version history in a MEGA cloud storage account.

Contents

Motivation

MEGA keeps full version history for every file it syncs. Over time this accumulates silently and can consume significant storage quota. MEGA's own web/desktop clients only offer all-or-nothing clearing of previous versions — either per file, or for every file in the account at once — with no way to keep the last few versions, apply an age cutoff, or target files matching a pattern. This toolset fills that gap: see exactly how much space versions are consuming and which files are the worst offenders, then prune selectively — by file/folder pattern, extension, age, or "keep the N most recent" — instead of losing all history or none.

Requirements

  • Python ≥ 3.11 — uses tomllib from the standard library
  • MEGAcmd ≥ 2.5 — official MEGA CLI with version support

No third-party Python packages required.

Install

megavers

pip install megavers
# or, in an isolated environment:
pipx install megavers

MEGAcmd (Ubuntu / Debian)

MEGAcmd is separate from the MEGAsync desktop client and must be installed independently:

sudo apt install megacmd

If the package is not found, add the MEGA repository first:

curl -fsSL https://mega.nz/linux/repo/xUbuntu_$(lsb_release -rs)/Release.key \
  | sudo gpg --dearmor -o /usr/share/keyrings/mega-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/mega-keyring.gpg] \
  https://mega.nz/linux/repo/xUbuntu_$(lsb_release -rs)/ ./" \
  | sudo tee /etc/apt/sources.list.d/megacmd.list
sudo apt update && sudo apt install megacmd

Log in

MEGAcmd maintains its own session, independent of MEGAsync:

mega-login your@email.com
# prompts for password interactively — do not pass the password as an argument,
# as it would be visible in shell history and process listings

Verify with:

mega-whoami

Quickstart

megavers-analyze        # see what's eating your quota
megavers-config-init    # optional: write a filter config you can customize
megavers-prune          # preview what would be deleted (dry-run by default — nothing is deleted yet)
megavers-prune --yes    # actually delete, once you're happy with the preview

megavers-prune uses a handful of broadly-applicable filters out of the box (git internals, OS junk files, Python caches) — the megavers-config-init step above is only needed if you want to add or change filters. The walkthrough below shows a complete example, including how to write your own filters for your own storage patterns.

Walkthrough

A full cleanup example, putting megavers-analyze and megavers-prune together on a real account:

  1. Analyze, and look for patterns — not just individual files. Run a scan and check the three ranked tables for folders or extensions that show up repeatedly, not one-off large files.

    megavers-analyze --top 30 --json results.json   # save so prune can reuse the scan
    

    A snippet from a real scan:

     VER SPACE   VERS    CUR SIZE  PATH
        3.1 GB     46    312.4 MB  /MEGAsync/Backups/project-backup.zip
    ...
      V/DAY   VERS  PATH
       8.62    101  /MEGAsync/code/project/__pycache__/utils.cpython-312.pyc
    

    utils.cpython-312.pyc dominates the version-count and churn-rate tables (101 versions, ~8.6/day — recompiled on every test run) — that's a build artifact, not something worth keeping version history for at all. Backups/project-backup.zip topping the space table is a different pattern: worth keeping some history, but maybe not all 46 copies.

  2. Add or adjust filters in .megavers.toml for what you found. Bootstrap a config first if you don't have one:

    megavers-config-init   # writes ~/.config/megavers/config.toml
    

    The bundled python-bytecode filter already covers .pyc/.pyo churn. For the backups pattern, add your own:

    [[filter]]
    name = "backups"
    description = "Old backup archives — keep a few, not all"
    path_contains = ["/MEGAsync/Backups/"]
    extensions = [".zip"]
    
  3. Preview with megavers-prune before deleting anything. No --yes yet — scope it to just the new filter first, so you can check it matches what you expect without the noise of every other active filter:

    megavers-prune --from-json results.json --filter backups --keep-n 5
    

    Check the dry-run report — files affected, versions to delete, space to recover. Once it looks right, re-run the identical command with --yes appended to actually delete:

    megavers-prune --from-json results.json --filter backups --keep-n 5 --yes
    

    Drop --filter backups (and --from-json, to pick up any changes since the scan) once you're comfortable running all your configured filters together.

  4. Once your filters are dialed in, run megavers-prune --yes periodically to keep version buildup from creeping back — e.g. weekly by hand:

    megavers-prune --yes   # every configured filter, no dry-run
    

    Or via cron:

    # MEGAcmd keeps its login session on disk, so cron doesn't need to log in again
    # Runs every Sunday at 3:00 AM; on failure, prints a clearly-flagged line
    # instead of a normal-looking log entry, so a broken session doesn't go unnoticed
    0 3 * * 0 megavers-prune --yes >> ~/megavers.log 2>&1 || echo "$(date): FAILED - check 'mega-whoami'; session may need 'mega-login' again" >> ~/megavers.log
    

    The login session (~/.megaCmd/session) can be invalidated by an explicit mega-logout, a password change, or MEGA revoking the device — if that happens, the cron job can't recover on its own (mega-login needs an interactive password prompt, and putting a password in the crontab would defeat the point of avoiding shell history exposure). Check the log occasionally, or re-run mega-login interactively if you see a FAILED line.

    No --keep-n/--older-than needed at this point unless you want them — with none set, matched files have all their old versions deleted, keeping only the current one. Re-run without --yes occasionally afterward to sanity-check what the filters are still catching.

Commands

megavers-analyze — Space analyzer

Scans your MEGA account via MEGAcmd and produces a ranked report of versioning space usage.

usage: megavers-analyze [-h] [--version] [--top N] [--json FILE] [--raw-dump FILE]
                         [-v | -q] [path]

positional arguments:
  path           Cloud path to analyze, absolute (default: /)

options:
  --version      Show version and exit
  --top N        Number of top files to display (default: 20)
  --json FILE    Save full results as JSON
  --raw-dump FILE  Save raw mega-ls output for debugging
  -v, --verbose  Show debug output (e.g. the mega-* commands being run)
  -q, --quiet    Suppress progress messages; only warnings/errors and the report
                 are shown

The report has three ranked tables:

  1. By version space — which files consume the most quota through old versions
  2. By version count — which files have the most historical snapshots
  3. By churn rate — which files change most frequently (versions/day), useful for spotting files that should be excluded from sync entirely

Examples:

# Analyze entire account
megavers-analyze

# Analyze a specific subfolder, show top 30, save JSON
megavers-analyze /MEGAsync/MyFolder --top 30 --json results.json

# Debug: inspect raw mega-ls output
megavers-analyze --raw-dump raw.txt

Example output:

============================================================================
MEGA VERSIONING SPACE REPORT
============================================================================
  Files with old versions:         1204
  Total old version count:         8731
  Space used by old versions:      12.7 GB
  Overhead vs. current file size:  26.3%

TOP 20 FILES BY VERSION SPACE
----------------------------------------------------------------------------
 VER SPACE   VERS    CUR SIZE  PATH
----------------------------------------------------------------------------
    3.1 GB     46    312.4 MB  /MEGAsync/Backups/project-backup.zip
                   oldest:     2025-04-12 09:15 UTC
...

TOP 20 FILES BY VERSION COUNT
----------------------------------------------------------------------------
 VERS   VER SPACE    CUR SIZE  PATH
----------------------------------------------------------------------------
  101      4.1 MB     41.0 KB  /MEGAsync/code/project/__pycache__/utils.cpython-312.pyc
...

TOP 20 FILES BY CHURN RATE (versions/day)
----------------------------------------------------------------------------
  V/DAY   VERS         SINCE  PATH
----------------------------------------------------------------------------
   8.62    101  2026-07-16 14:20 UTC  /MEGAsync/code/project/__pycache__/utils.cpython-312.pyc
   2.20     44  2026-07-08 12:36 UTC  /MEGAsync/code/script.py
...

"Overhead vs. current file size" is the ratio of old-version space to current-file space, computed only over files that have old versions — it does not include files with a single version.

megavers-config-init — Write a starting config

Writes a copy of the bundled default filter config to disk, as a starting point to customize. Refuses to overwrite an existing file.

usage: megavers-config-init [-h] [--version] [-v | -q] [PATH]

positional arguments:
  PATH           Destination path (default: ~/.config/megavers/config.toml)

options:
  --version      Show version and exit
  -v, --verbose  Show debug output
  -q, --quiet    Suppress progress messages; only warnings/errors are shown

Examples:

# Write to the default location (~/.config/megavers/config.toml)
megavers-config-init

# Write to a project-local config instead
megavers-config-init .megavers.toml

# Passing an existing directory writes .megavers.toml inside it
megavers-config-init .

.megavers.toml — Filter definitions

Filters are defined in a config file. Each filter has a name and at least one of: a list of path substrings (path_contains, case-sensitive, matching MEGA's own path semantics) or a list of extensions. If both are set, both must match (AND). Across filters, any match selects the file (OR). A filter with neither path_contains nor extensions is rejected at startup, since it would otherwise match every file in the account.

Syntax, shown using two of the bundled filters plus a commented-out custom one:

[[filter]]
name = "os-junk"
description = "OS-generated metadata files (macOS Finder, Windows Explorer)"
path_contains = ["/.DS_Store", "/Thumbs.db", "/desktop.ini"]

[[filter]]
name = "python-bytecode"
description = "Compiled Python bytecode and JIT cache files"
extensions = [".pyc", ".pyo"]

# [[filter]]
# name = "results"
# description = "Binary output files under result/sandbox directories"
# path_contains = ["/results/", "/sandbox/", "/outputs/"]
# extensions = [".pkl", ".gz", ".png", ".csv"]   # etc.

Add, remove, or modify filters freely — the tool has no hardcoded logic.

The bundled default. The snippet above is only a syntax sample, not the full file — see megavers/config.toml for the real thing. It ships with more filters active than shown above — broadly applicable ones regardless of your workflow: common OS/editor junk files (.DS_Store, Thumbs.db, desktop.ini, Vim swap files, Office lock files), Python caches (__pycache__, .pytest_cache, .pyc/.pyo, etc.), and git internals — plus the results filter above included commented out as a more workflow-specific example.

Default retention policy. An optional [defaults] table sets keep_n/older_than values that megavers-prune falls back to whenever the corresponding CLI flag isn't given — the CLI flag always wins when both are set. Useful for unattended/cron runs, so a bare megavers-prune --yes doesn't delete every old version of every matched file:

[defaults]
keep_n = 5
older_than = 90

Commented out in the bundled default (see above) — most users want to review what a policy would delete before it runs unattended on a schedule.

Creating your own. Run megavers-config-init to copy the bundled default to ~/.config/megavers/config.toml as a starting point (pass a path to write it elsewhere; it refuses to overwrite an existing file). Or write ./.megavers.toml / ~/.config/megavers/config.toml from scratch, using the syntax above. For one-off needs without any config file at all, use --path-contains / --ext on the command line instead.

Listing what's active. Run megavers-config-list to see the full current list of filters in effect (bundled default, or your own config if you've created one).

megavers-config-list — List active filters

Prints the filters currently in effect — the bundled default, or your own config if you've created one — and exits.

usage: megavers-config-list [-h] [--config FILE] [--version] [-v | -q]

options:
  --config FILE  Config file path (default: ./.megavers.toml → ~/.config/megavers/config.toml → bundled)
  --version      Show version and exit
  -v, --verbose  Show debug output
  -q, --quiet    Suppress progress messages; only warnings/errors are shown

Examples:

# List filters from the active config (auto-discovered)
megavers-config-list

# List filters from an explicit config file
megavers-config-list --config ./my-filters.toml

megavers-prune — Version pruner

Deletes old version histories for files matched by filters in .megavers.toml using MEGAcmd. Only previews by default — pass --yes to actually delete. The current (latest) version of every file is always kept.

Warning: deletion is permanent. MEGA does not keep a recycle bin for pruned versions — once deleted with --yes, old versions cannot be recovered. Always run without --yes first (or with --dry-run) to review what would be deleted.

usage: megavers-prune [-h] [--from-json FILE] [--config FILE]
                         [--filter NAME] [--path-contains STR] [--ext EXT]
                         [--min-version-size SIZE] [--keep-n N] [--older-than DAYS]
                         [--yes] [--dry-run] [--version] [-v | -q] [path]

source:
  path                  Cloud path to scan, absolute (default: /)
  --from-json FILE      Load from megavers-analyze --json output (skips re-scanning)
  --config FILE         Config file path (default: ./.megavers.toml → ~/.config/megavers/config.toml → bundled)

filters:
  --filter NAME         Activate only this config filter by name (repeatable;
                        default: all filters in config)
  --path-contains STR   Ad-hoc: select files whose path contains STR (repeatable)
  --ext EXT             Ad-hoc: select files with this extension (repeatable)
  --min-version-size SIZE  Only select files where version space >= SIZE (e.g. 10MB)

version selection (applied after filters):
  --keep-n N            Keep the N most recent old versions; delete the rest
                        (overrides [defaults].keep_n in the config, if set)
  --older-than DAYS     Delete old versions whose age exceeds DAYS days
                        (overrides [defaults].older_than in the config, if set)

mode:
  --yes                 Actually delete. Without this flag, only a preview is shown.
  --dry-run             Preview what would be deleted (the default; this flag mainly
                        exists to make an already-explicit preview clearer).
  --version             Show version and exit
  -v, --verbose         Show debug output (e.g. the mega-* commands being run)
  -q, --quiet           Suppress progress messages; only warnings/errors and the
                        report are shown

See also: megavers-config-init to bootstrap a config, megavers-config-list to see what's active.

Old-version dates from MEGA are in UTC; --older-than cutoffs are computed in UTC too, regardless of your local timezone.

Examples:

# Preview what would be deleted (default — nothing is deleted without --yes)
megavers-prune

# Actually delete, using all filters from .megavers.toml
megavers-prune --yes

# Run only the 'python-bytecode' filter
megavers-prune --filter python-bytecode --yes

# Preview keeping only the 3 most recent old versions per matched file
megavers-prune --keep-n 3

# Delete versions older than 90 days (all filters)
megavers-prune --older-than 90 --yes

# Ad-hoc: any file whose path contains 'backup'
megavers-prune --path-contains backup --yes

# Reuse a previously saved scan
megavers-prune --from-json results.json

Contributing

Bug reports, feature requests, and pull requests are welcome — see CONTRIBUTING.md for setup, tests, and PR expectations.

Release files for megavers 0.2.0

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

Source distribution (sdist)

Source distribution for megavers 0.2.0
File Size Uploaded
megavers-0.2.0.tar.gz 38.0 kB Details

Built distribution (wheel)

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

Total release size: 63.8 kB

Release files / megavers-0.2.0.tar.gz

Download URL megavers-0.2.0.tar.gz
Size 38.0 kB
Tags Source
SHA-256 checksum
How to use checksums
444f003a0aa5c27e8c34ee9f406fc9712318dd003eef4ea7e991a54bcb2ad3d4
BLAKE2b-256 checksum
How to use checksums
8b2e1d697dbd23422030373592b01f912b9528876cc472977ec0021e171c935c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Release files / megavers-0.2.0-py3-none-any.whl

Download URL megavers-0.2.0-py3-none-any.whl
Size 25.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
72b53f5b73336835f49de461de4cafc3c881f6aaa63016d9a1c6688f561e95d9
BLAKE2b-256 checksum
How to use checksums
2e3b3824c24f16a68f583028e5eab673609f2ce7f9380bc750b8487e475c7ecb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

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