Open source · Offline-first · No subscription

Your unified bank ledger,
on your computer

Import files from all your banks. Spendify merges them, eliminates double-counting, classifies every transaction — and your data never leaves your disk.

▶ Install now View on GitHub

Python · Streamlit · SQLite · Ollama · no account required

🔒 Data only on your computer
🔁 Idempotent SHA-256 import
🏦 Multi-bank, multi-format
🤖 Local or cloud AI with PII redaction
🧪 199 tests, zero external dependencies

Three banks, three files, one mess

Every month: download, open Excel, paste, fix the signs, find the duplicates. And every time something doesn't add up.

😩 The monthly routine everyone hates

Three bank statements from three different banking portals, incompatible CSV formats, dates in different formats, amounts with random signs. Merging them by hand takes hours and always produces errors.

🔴 The problem of all problems: double-counting

The supermarket purchase appears in the credit card statement and in the current account as a monthly aggregate charge. Adding everything up, your expenses look double what they actually are. No common tool solves this automatically.

🔄 Internal transfers that distort your balance

A wire transfer to a savings account is not an expense. But if you import both accounts, the same transaction appears twice — as an outflow from the current account and as an inflow on the savings account.

📋 The categorisation that never ends

Classifying 300 transactions per month by hand is a job. Cloud apps do it, but they send your banking data to their servers and charge you a monthly subscription.


Three steps, no black magic

No banking integrations, no account, no per-file configuration.

Download files from your bank

Export bank statements as CSV or XLSX from your bank's portal. Works with any bank — Spendify automatically detects the format with no manual configuration.

Drag them into Spendify and click Process

Select all files at once, even from different banks, even from different years. Spendify detects the document type, corrects signs, eliminates double-counting between card and account, and classifies every transaction.

See where your money goes

The unified ledger shows everything in one place: charts, filters, export, and the certainty that every euro is counted exactly once.


Algorithms that solve real problems

This is not a generic budgeting app. It is designed around the specific problems of people with multiple bank accounts.

RF-03

Credit card–current account reconciliation

When the credit card charges the monthly amount to the current account, Spendify recognises the relationship and removes the double-counting automatically.

Time window ±45 days · 3 matching phases: sliding window → subset sum for split amounts → partial reconciliation

RF-04

Internal transfer detection

A wire transfer from a current account to a savings account is neither an expense nor income: it is an internal transfer. Spendify recognises it by comparing amounts, dates, and account holder names in the descriptions — even if the two files were imported at different times.

Dedup

Idempotent deduplication

Every transaction has a unique ID calculated from its content (SHA-256). If you import the same file twice, nothing happens. You can re-import your entire transaction history without fear of duplicates.

Categories

Cascading hybrid classification

Categorisation uses four levels in sequence:

  • 1Your rules — "CONAD" → Groceries (applied retroactively)
  • 2Static regex — predefined patterns for common categories
  • 3LLM — for everything else, local or cloud AI
  • 4Fallback — "To review" if everything else fails

Your data stays yours. Seriously.

It is not just a slogan. It is the architecture.

🏠

Offline-first by default

Spendify uses Ollama locally by default: an AI engine that runs on your computer, with no internet connection. Your bank statements never leave your disk.

🛡️

Automatic PII redaction

If you use OpenAI or Claude, Spendify automatically removes all identifying data before any remote call:

IBAN → <ACCOUNT_ID> PAN → <CARD_ID> Tax ID → <FISCAL_ID> Name → fictitious alias

If the check fails, the call is blocked — not silently degraded.

💾

Portable local database

Data is stored in a SQLite file on your computer. You can copy it, move it, back it up like any other file. No mandatory cloud, no account, no subscription.


Not for everyone. For those who want real control.

Four profiles that find in Spendify something alternatives do not offer.

🏦

People with accounts at multiple banks

Current account + credit card + savings account + trading account? Spendify unifies them all into a single ledger without having to do anything manually.

📊

People who track their finances seriously

If you use Excel for your expenses, Spendify can replace that routine: you import the files once, Spendify unifies and classifies, you review only the exceptions.

🔐

People who do not trust the cloud

No mandatory remote backend, no account, no registration. Your banking data stays where it belongs: on your computer.

👨‍💻

Developers

Open source Python project with modular architecture, LLM pipeline on structured data, full test suite. A starting point for experimenting or building custom integrations.


Everything you need, nothing more


Multi-bank import CSV and XLSX from any bank
Auto-detect format No manual configuration for each file type
Unified ledger All transactions in chronological order, filterable by date / account / category / context
Automatic classification 15 expense categories + 7 income categories with subcategories
Customisable taxonomy Add / edit categories without restarting the app
Deterministic rules "ESSELUNGA → Groceries" rules applied retroactively
Interactive analytics 7 charts: monthly trend, cumulative balance, category pie, top 10 merchants
Life contexts Segment expenses by Work / Vacation / Daily life
Check List Month × account pivot table: see which months you have not imported yet
Export Standalone HTML (with charts), CSV, XLSX
Configurable LLM Ollama, OpenAI, Claude, Groq, Gemini, LM Studio, any compatible API
PII sanitization Automatic IBAN / card number / tax ID / name protection before remote calls

One command, app ready

Only Docker Desktop required. No git clone, no configuration.

bash
$ curl -fsSL https://raw.githubusercontent.com/drake69/spendify/main/installer/install.sh | bash
powershell
PS> irm https://raw.githubusercontent.com/drake69/spendify/main/installer/install.ps1 | iex

The script pulls the image from GitHub Container Registry, starts the container and opens the browser at http://localhost:8501 automatically.
Optional local AI: the installer asks whether to add Ollama with gemma3:12b — downloaded in background (~8 GB). Works on Apple Silicon (arm64) and amd64.
To uninstall: curl -fsSL https://raw.githubusercontent.com/drake69/spendify/main/installer/uninstall.sh | bash


Mature technologies, no exotic dependencies

No LLM framework (no LangChain) — AI backends use the official SDKs directly.

Python 3.13 + pandas
Streamlit web interface
SQLite + SQLAlchemy
Pydantic v2 schema validation
Plotly interactive charts
uv package manager
Ollama local AI
chardet encoding detection
openpyxl Excel parsing

Modular architecture, full test suite

CSV/XLSX File Pre-processing (strip sparse rows, drop metadata columns) Schema classifier (SHA-256 fingerprint → LLM if new schema) Normalizer (encoding, parse_amount Decimal, SHA-256 tx_id) RF-03 Reconciler (credit card–current account, 3 phases) RF-04 Detector (internal transfers, symbolic matching) Description cleaner (LLM: noise → canonical text) Categorizer (rules → regex → LLM → fallback) Database (SQLAlchemy, idempotent upsert)

🔌 New LLM backends

Implement LLMBackend (3 methods) and register it in BackendFactory. Works with any OpenAI-compatible API.

🏦 New bank formats

Flow 2 recognises them automatically via LLM without code changes. The schema is saved and reused in subsequent imports.

🏷️ New categories

From the Taxonomy page, without touching the code. The taxonomy is fully configurable from the interface.

🚀 REST API

The process_file() pipeline is completely separate from the UI — it can be exposed via FastAPI without changes.


bash — test suite
$ uv run pytest tests/ -v # 199 tests, zero external dependencies
$ uv run pytest tests/ --cov=core # coverage of business logic layer

What is coming



Contributions are welcome

Areas where contributions are most useful:

🏦 New bank formats

If your bank is not automatically recognised, open an issue with an anonymised CSV sample.

🧪 UI tests

The suite covers the business logic layer but not yet the Streamlit interface. There is room to contribute.

🌍 Internationalisation

The architecture already supports multiple languages for descriptions. The UI is in Italian — there is scope to add other languages.

⚡ Performance

Batch categorisation is the bottleneck with a local LLM. There is room for parallelisation.


Go to GitHub