Rebalance your Google storage across your own accounts — locally, open source.
Got one Google account bursting at 40 GB on a 15 GB free plan while your alt accounts sit empty? Spillover connects all your accounts, shows you exactly what's eating the space, and moves files from full accounts to empty ones — with hash verification, a trash-not-delete safety net, and a permanent local record of what went where.
Everything runs on your PC. No servers, no uploads to third parties, no account credentials ever leaving your machine.
Full walkthrough: connecting accounts, the rebalance wizard, duplicates, and the Photos picker — 7m22s.
Quick run:
- UI:
spillover uiopens http://127.0.0.1:8741 - Demo mode (no sign-in):
spillover ui --demo - Custom port:
spillover ui --port 9000 --no-browser
Accounts page – See all your Google accounts, quotas at a glance. Click to connect or reconnect.
Rebalance wizard – Pick a full account, choose files, dry-run the plan, then execute with hash verification and trash-not-delete safety.
Ledger – Every move recorded locally: filename, size, hash, source → destination. Search by filename to find where something went.
Want a screen capture now? The CLI mirror is identical to what you'd see in the web UI:
# Connect accounts (opens browser windows for OAuth)
spillover auth add --alias main
spillover auth add --alias backup-1
# See quotas at a glance
spillover quota
# Run a rebalance (scan → plan → execute)
spillover scan --alias main
spillover plan --from main
spillover run --plan ~/.spillover/plans/plan-main-*.json --execute- Google Drive: fully supported. Scan, plan, move, verify — all automatic.
- Google Photos: two supported routes. Since March 2025, Google blocks all third-party apps from reading your full photo library and provides no API to delete photos. So for Photos:
- Picker (recommended):
spillover photos create --alias mainprints a Google picker link — select what to move in Google's own UI, and Spillover copies your picks (hash-verified) into your other accounts' Drive storage. Also in the web UI under Takeout → Photos picker. Spillover only ever sees the items you pick. - Takeout: export via Google Takeout (https://takeout.google.com), then
spillover takeout --dir ~/takeout --executedistributes everything. - Either way, you bulk-delete the originals in the Photos UI yourself (Google's rule, not ours — no tool on earth can do this via API in 2026). Spillover writes a deletion checklist to
~/.spillover/photo_manifests/.
- Picker (recommended):
- Gmail: never touched. Spillover doesn't even request Gmail scopes.
One-liner install + one-time setup:
# 1. Clone and install
git clone https://github.com/aashish254/Spillover.git spillover && cd spillover
python3 -m venv .venv
source .venv/bin/activate # macOS/Linux; Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e . # gives you the `spillover` commandSpillover uses your own Google Cloud project (this is how tools like rclone do it):
- Create a Google Cloud project: https://console.cloud.google.com/projectcreate
- Enable APIs: Drive API, Photos Picker API
- Create Credentials → OAuth client ID (Desktop app): https://console.cloud.google.com/apis/credentials
- Download JSON → save as
~/.spillover/client_secret.json:mkdir -p ~/.spillover && cp ~/Downloads/client_secret*.json ~/.spillover/client_secret.json
In testing mode Google expires the login every ~7 days — just re-run
spillover auth reconnect --alias <name>(or hit Reconnect in the web UI). (Publishing the project to "Production" makes tokens long-lived but keeps an "unverified app" warning screen.)
spillover ui # opens http://127.0.0.1:8741 in your browser
spillover ui --demo # try it with fake data, no Google sign-in needed
spillover ui --port 9000 # pick your own port
spillover ui --no-browser # don't auto-open the browserThe UI walks you through: Accounts (quotas at a glance) → Rebalance (pick a full account → scan → choose files → dry-run plan → confirm → live progress) → Takeout (point at an unzipped Google Takeout folder, distribute across accounts) → Duplicates (find duplicates across accounts, keep-one-copy, trash-the-rest) → Ledger (every move, searchable).
Everything still runs locally; the browser page never sends anything anywhere.
# 1. Connect accounts (a browser window opens for each — sign in normally)
spillover auth add --alias main
spillover auth add --alias alt1
spillover auth add --alias alt2
# 2. See all quotas at a glance
spillover quota
# 3. Inventory the full account
spillover scan --alias main
# 4. Propose moves (files ≥50MB; --types mp4,jpg to narrow it)
spillover plan --from main --min-size 50MB
# 5. Preview, then actually move (trash-not-delete, hash-verified)
spillover run --plan ~/.spillover/plans/plan-main-XXXX.json
spillover run --plan ~/.spillover/plans/plan-main-XXXX.json --execute
# Photos via Takeout export
spillover takeout --dir ~/takeout --execute
# Photos via the picker (no export download needed)
spillover photos create --alias main # prints a Google picker link
# open the link, select photos/videos, then:
spillover photos list --alias main --session-id <id> # review your picks
spillover photos transfer --alias main --session-id <id> --to backup-1,backup-2
# Google's Photos API has no delete: a deletion checklist is written to
# ~/.spillover/photo_manifests/ — remove the originals by hand afterwards.
# Resume transfers interrupted by a crash or kill (never re-uploads a
# destination copy that was already uploaded and verified)
spillover resume
spillover resume --from main
# Reconnect an account whose token expired or was revoked
spillover auth reconnect --alias backup-1
# Where did my file go?
spillover find vacation.mp4
spillover history- Dry-run by default.
runonly previews until you pass--execute, and even then asks for confirmation. - Verify-before-trash. A source file is trashed only after the destination copy's SHA-256 matches the downloaded bytes. Mismatch → source untouched, move logged as failed.
- Trash, never delete. Originals sit in the source account's trash for 30 days — full undo window.
- Never fills a destination. 1 GB safety buffer per account, always.
- Shared files are skipped by default. Files shared with other people,
or owned by someone else, are flagged at plan time and skipped at run
time — moving them would break share links or strand collaborators. Pass
--include-shared(CLI) or tick the checkbox (web UI) to move them anyway, explicitly. - Crash-safe transfers. Every file is tracked as a transaction
(
pending → in_progress → done/failedwith the last completed stage). If a run dies mid-way,spillover resume(or the Resume button in the web UI) continues from the first unfinished stage — a destination copy that was already uploaded and verified is never re-uploaded. - Ledger. Every move (done, failed, or skipped) is recorded in
~/.spillover/ledger.db— filename, size, hash, source → destination. - Narrow scopes. Drive scope plus the Photos picker scope only. The picker exposes solely the items you select — never your whole library. No Gmail, no contacts, nothing else.
- Local only. Tokens live in your OS keyring; the ledger and scans live
in
~/.spillover. Nothing is sent anywhere except to Google's APIs.
- Google caps uploads at 750 GB/day per account — big moves are
automatically spread by the retry/backoff engine; just re-run
run. - Moving a file changes its owner; existing share links on moved files
break. Shared files are skipped by default (see above) — use
--include-sharedonly when you mean it. - Google's Photos API cannot delete anything, so picker and Takeout
transfers always leave the originals behind. The transfer writes a
manual-deletion checklist (
~/.spillover/photo_manifests/) — work through it in Google Photos yourself after confirming the copies. - Pooling free accounts to avoid paid storage sits in a gray area of Google's Terms of Service. This tool is for managing your own data across your own accounts; use your judgment.
spillover/
auth.py OAuth per account, tokens in OS keyring, reconnect flow
drive.py Retry-hardened Drive API wrapper
inventory.py Full Drive scan + "what's eating space" summary
planner.py Bin-packing: which files go to which account
transfer.py Download → hash → upload → verify → trash → ledger,
with transaction tracking + resume
sharing.py Shared/not-owned file detection and warnings
photos.py Google Photos Picker API flow + deletion manifests
takeout.py Google Photos Takeout ingest (zip parts + JSON sidecars)
ledger.py SQLite record of every move + transfer transactions
cli.py `spillover` command
MIT — see LICENSE.



