Ezra Hulsman

Finance Bot

A Discord bot that turns raw bank CSV exports into a categorized monthly budget in Google Sheets: regex rules handle the predictable transactions, Claude handles the rest.

ProjectFinance Bot
Running sinceJuly 2025
StackPython, discord.py, Claude, Google Sheets API, Docker
The Finance Bot drawn as a sorting line: a bank export goes through about 40 rules, the rest goes to Claude in batches of 40, and a gate at 0.75 confidence sends each row into the month's sheet, the unsure ones written and marked in red. /upload bank export RULES ~40 patterns matched, 100% rest CLAUDE batches of 40 0.75 MONTH SHEET one per month ! below it: written, flagged, never guessed

What I Built

The pipeline has three stages: ingestion, categorization, and export.

Ingestion starts with a /upload slash command. The bot accepts a CSV file from ASN Bank’s fixed-column export format (20+ columns), parses it into normalized transaction dicts, and applies pre-processing: mapping savings pot UUIDs to human-readable names and correcting known truncation errors in the bank’s export. Each transaction gets a standardized shape: booking date, amount, credit/debit indicator, counterparty, and remittance information.

Categorization runs in two tiers. First, ~40 regex rules match against counterparty names and remittance text, which cover recurring patterns like grocery stores, subscriptions, utilities, and charitable donations, and resolve instantly at 100% confidence. Transactions that don’t match any rule go to Claude for AI categorization. The bot sends the unmatched transactions as a batch (chunked at 40 with automatic repair for partial failures), with the regex-matched transactions included as context so the AI can detect cross-transaction relationships, like multiple savings pot withdrawals that sum to match a large expense. Claude returns a category, Dutch-language description, and confidence score. Answers below 75% confidence are still written, but flagged, so nothing waits on a review step.

A provider abstraction tries the Claude Code CLI first (free, uses an existing subscription) and falls back to the Anthropic API if the CLI isn’t available, keeping per-transaction costs at zero for normal use.

Before any transaction data reaches the AI, an anonymization layer strips IBANs, personal names, and reference numbers. Known merchants and businesses are preserved; personal counterparties become consistent placeholders (Person_A, Person_B) so the AI can still detect patterns across transactions from the same person.

Review happens in the sheet, not in Discord. Rows the bot is unsure about are written with the category ! Nog in te delen ! or a ? before the description, and the summary in Discord lists them next to the AI guess that wasn’t used. An interrupted upload keeps its state on disk and can be continued with /resume.

Export writes to Google Sheets, one spreadsheet per financial month, creating the next month’s sheet from a template when it’s missing. Expenses go to columns B–E, income to G–J, matching the existing budget spreadsheet layout. After the rows are written, the bot sorts the sheet by date.

Key Decisions

Discord as the interface. My wife and I manage a shared household budget. Discord is already open on both our phones, supports ephemeral messages so financial data doesn’t persist in chat history, and slash commands with a private progress thread are all the interface an upload needs, without building a web frontend.

Two-tier categorization with an anonymization boundary. Regex rules are fast, free, and deterministic: they handle most transactions that go to the same merchants every month. AI handles the long tail. The anonymization layer between them means the AI never sees personal names or account numbers, only merchant names and sanitized descriptions. This lets me use an external API without exposing household financial data.

Append-and-sort over clear-and-rewrite. The bot appends the new rows below the ones already there and sorts afterward, rather than clearing the sheet and rewriting everything. This preserves any manual edits made directly in the spreadsheet between bot runs.

Outcome

The bot has processed every month of household transactions since July 2025. A typical month runs through the full pipeline (CSV upload, categorization, sheet export) in under two minutes. A daily reminder pings the household to upload the month’s CSV. It runs in Docker on a home server.

Source code is not public: the repository contains financial categorization rules and configuration tied to personal banking data.