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 Websiteimport/File Watcher
Parse + Deduplicate
Categorize (8-step pipeline)
Gmail APIClaude API
SQLite DB
Google Sheets PushSheets UI
feedback loop
User CorrectionsOverride PollerSQLite 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.