Skip to content
DAVE WARMERDAM

MoMoney

Self-hosted personal finance tracker. Drop a bank export, get auto-categorized transactions pushed to Google Sheets.

What it does

MoMoney automates the tedious parts of personal finance. Download a bank export (QFX, OFX, or CSV), drop it into a watched folder, and walk away. The app parses every transaction, deduplicates against your existing history, runs each one through an 8-step AI categorization pipeline, stores everything in a local SQLite database, and pushes a clean view to Google Sheets for review. If you correct a category in Sheets, the app polls the change back into SQLite. Your data never leaves your hardware.

The categorization pipeline

Every transaction passes through a prioritized 8-step fallback chain. The first confident match wins:

  1. Transfer detection — recognizes inter-account transfers by pattern and description prefix
  2. Merchant auto-match — 100% confidence exact and substring matches from a user-defined merchant dictionary
  3. Amount rules — disambiguates by transaction amount (e.g., Apple $9.99 = iCloud vs. $22.99 = YouTube Premium)
  4. Account rules — default categories for specific accounts like a business checking
  5. High-confidence merchant — broader 80-99% confidence pattern matches
  6. Gmail receipt lookup — searches Apple and Amazon receipt emails near the transaction date, then uses Claude to parse line items for split-allocation categorization
  7. Claude AI categorization — sends remaining ambiguous transactions to Claude for a single-shot category suggestion
  8. Manual review — flags any remaining unmatched transactions for human review in Google Sheets

The pipeline short-circuits at the first confident match — most transactions resolve by step 2 or 3 without hitting the API.

Key features

  • Multi-bank support — QFX/OFX (SGML and XML) and CSV formats across Wells Fargo, Capital One, Amex, Mercury, and more
  • 5-tier deduplication — file hash, external ID, import hash, cross-format matching, and fuzzy dedup key prevent duplicates across re-imports and different source formats
  • Google Sheets UI — six tabs (Transactions, Allocations, Review, Transfers, Summary, Categories) with dropdown validation for corrections that sync back to SQLite
  • File watcher daemon — polls the import directory every 30 seconds and waits for file stability before processing
  • Full CLI — 10+ commands including watch, import, status, review, reconcile, push, poll, and category management
  • Business account filtering — restricts category choices for business accounts
  • Balance reconciliation — compares statement balances against computed balances
  • API cost tracking — monitors Google Sheets and Anthropic usage per month

Architecture

Designed to run on a Synology NAS or any Docker host. The entire data flow is one-directional: bank files in, SQLite as the source of truth, Google Sheets as a read-only mirror with override columns.

Bank Website→import/→File Watcher
↓Parse + Deduplicate↓
Categorize (8-step pipeline)
Gmail APIClaude API
↓SQLite DB↓
Google Sheets Push→Sheets UI
feedback loop
User Corrections→Override Poller→SQLite DB

Built with

Python 3.12, SQLite, Docker, Anthropic Claude API, Google Sheets API, Gmail API, watchdog, gspread, and PyYAML. Configuration-driven design — all personal data lives in gitignored YAML files, not code. 820+ tests across 32 test files. Available as a GitHub template repo — use it as a starting point for your own setup. MIT licensed.

Security model

Single-user, self-hosted on a private network. No HTTP server, no exposed ports. Bank account numbers are used transiently during import only — never stored in the database. All SQL is parameterized, YAML uses safe loading, and credentials are environment variables mounted read-only in Docker. CodeQL scanning runs on every push. The repo has a clean git history with no secrets ever committed.