Back to all posts
    I Built a Personal Finance App in 3 Hours. My AI Remembered How.
    Case Study

    I Built a Personal Finance App in 3 Hours. My AI Remembered How.

    A real case study: 1,001 transactions, 5 bank accounts, one session.

    March 1, 2026
    Updated July 14, 2026
    8 min read
    72 views
    by Iwo Szapar

    Last Saturday I sat down to solve a problem that's been bugging me for months.

    I run a Polish sole proprietorship. Two income streams. Five bank accounts across four different banks. Business expenses in Mercury and mBank. Personal spending on Revolut and mBank. Tax payments, contractor invoices, car lease, groceries, health costs, all flowing through different accounts in different currencies.

    I had zero visibility into where my money actually goes.

    By lunch, I had a working system. 1,001 transactions imported. 15 spending categories auto-assigned. 6 months of wealth tracking computed. A full picture of business costs, personal spending, and month-by-month savings.

    Three hours. One person. No team.

    Every AI demo shows fast code generation. What they don't show: what happens when your AI assistant remembers everything from your previous work sessions.

    The Problem: Five Banks, Zero Visibility

    My financial setup is typical for a Polish JDG (sole proprietorship) on ryczalt:

    • Mercury (US business account, USD)
    • mBank Business (Polish business account, PLN)
    • Revolut Business (EUR/PLN invoicing)
    • mBank Personal (rent, car lease, utilities)
    • Revolut Personal (daily spending, subscriptions)

    Each bank exports data in a completely different format. Mercury gives you clean CSVs. mBank uses semicolons with Polish number formatting (“1 234,56 PLN”). Revolut Personal exports comma-delimited files with Polish column headers. Revolut Business gives you PDFs.

    I already had a business accounting cockpit built in previous sessions. It tracked ISG consulting revenue, Second Brain product sales, and business expenses from Mercury. But it only covered the business side.

    I had no idea what my actual personal spending looked like. No idea if I was saving money or bleeding it. No visibility into which months were profitable after personal costs.

    What Made This Possible: Memory, Not Speed

    I opened Claude Code and said: “Here are my bank statements. Import everything.”

    I dropped five files into the conversation. Four CSVs and a PDF.

    What happened next is the part most people miss about AI coding assistants. Claude didn't start from zero. It didn't ask me “what database are you using?” or “what's your table schema?” or “how do your API endpoints work?”

    It already knew.

    My Second Brain memory system had stored everything from previous sessions:

    • The business_expenses table schema with its CHECK constraints on source and category columns
    • The accounting_months table structure with revenue and cost tracking
    • The API pattern using authenticateAdmin middleware
    • The existing fetchNbpRate() function for converting USD to PLN via the National Bank of Poland API
    • The parseCSVLine() utility that handles quoted fields in CSVs
    • The coding conventions (Vercel serverless functions, Supabase PostgreSQL, TypeScript)

    This is 6 months of accumulated context. Schema definitions, API patterns, helper functions, naming conventions. All persisted across sessions in structured memory files.

    So when I said “import these,” Claude could immediately:

    1. Read each file format and detect which bank it came from
    2. Map the data to existing table structures (or create new ones)
    3. Use existing utility functions for currency conversion
    4. Follow established patterns for deduplication and error handling

    No boilerplate. No “let me understand your stack first.” Just straight to the real work.

    The Session: What Actually Happened

    Phase 1: Database Extension (10 minutes)

    The existing system tracked business expenses. I needed personal transactions too.

    Claude created a new personal_transactions table with the right columns: transaction date, description, amount in original currency, amount in PLN, exchange rate, category, bank account source, and an is_internal flag.

    That flag matters. When I transfer money from mBank to Revolut, it shows as an outflow in mBank and an inflow in Revolut. Without the is_internal flag, that transfer would count as both spending AND income. Double-counting kills your numbers.

    Claude also added three new columns to the existing accounting_months table: personal_income_pln, personal_spending_pln, personal_savings_pln.

    Phase 2: Parsing Four Different Formats (30 minutes)

    This is where it got interesting. Claude launched three parallel agents, each handling a different file format simultaneously:

    mBank Business (semicolons, Polish number formatting):

    • Parsed 60 raw rows
    • Imported 29 actual expenses (tax payments, contractor invoices, bank fees)
    • Skipped Stripe payouts (already tracked elsewhere) and internal transfers
    • Correctly categorized PIT-28 tax as tax_ryczalt and ZUS as tax_zus

    mBank Personal (semicolons, multiple sub-accounts):

    • Parsed and imported 132 transactions
    • Detected which mBank sub-account each transaction belonged to (main PLN, secondary, USD)
    • Flagged Revolut top-ups as internal (money moving between my own accounts, not real spending)
    • Flagged own-account transfers as internal
    • Auto-categorized: rent (WSM), car lease (ARVAL), health (Sport Medica), insurance (AVIVA)

    Revolut Personal (commas, Polish headers):

    • Parsed and imported 869 transactions
    • Converted foreign currency amounts to PLN using NBP exchange rates
    • Flagged vault movements (“Aby wypłacic”) as internal
    • Auto-categorized 15+ patterns: groceries (Zabka, Auchan), dining (restaurants, Uber Eats), subscriptions (Spotify), health, shopping

    All three agents ran simultaneously. Combined: 1,001 personal transactions imported in one batch.

    Phase 3: Auto-Categorization (Built Into Import)

    Each parser had category rules baked in. Pattern matching on transaction descriptions:

    Category Examples Monthly total
    Health Sport Medica, Biomedica, rehab 19,323 PLN
    Car lease Arval 13,421 PLN
    Subscriptions Spotify, Fitssey, various SaaS 11,748 PLN
    Shopping Amazon, Zalando, Ikea, Allegro 10,530 PLN
    Groceries Zabka, Auchan, bakeries 4,338 PLN
    Dining Restaurants, cafes, Uber Eats 3,033 PLN
    Gifts P2P transfers, family 3,570 PLN
    Housing WSM (rent/admin fees) 2,869 PLN

    193 transactions (38,406 PLN) still sit in the “other” bucket. Next session I'll refine those. But even with imperfect categorization, I can already see the picture.

    Phase 4: Wealth Computation (5 minutes)

    Simple math, but it required clean data first:

    personal_savings = personal_income - personal_spending
    (excluding all internal transfers)
    

    The results across 6 months:

    Month Personal In Personal Out Savings
    Oct 2025 0 2,747 -2,747
    Nov 2025 25,439 25,975 -536
    Dec 2025 29,403 42,141 -12,738
    Jan 2026 35,053 44,090 -9,037
    Feb 2026 69,231 33,574 +35,658

    December was a bloodbath. January wasn't great either. February finally turned positive. Now I know.

    The Memory Layer: Why This Took Hours, Not Days

    “Memory” sounds abstract. In practice it's concrete files.

    My Second Brain stores context in a CLAUDE.md file, a MEMORY.md file, a memory/ directory, and a docs/ folder. These persist between sessions. When I open a new Claude Code session, the AI reads them first and knows my project before I type anything.

    But storage alone isn't enough. Raw memory files would get stale, contradictory, full of wrong information. So the system also has quality gates: git hooks that block edits on the main branch, build checks that must pass before deployment, and a self-improvement protocol that turns my corrections into permanent rules.

    That last part matters most. When Claude makes a mistake and I fix it, the fix becomes a rule in CLAUDE.md. Next session, it won't make the same mistake. The system improves with use.

    In today's session, that played out concretely:

    • Claude knew the business_expenses schema because docs/ACCOUNTING_SYSTEM.md documented it
    • Claude found the fetchNbpRate() function for currency conversion because CLAUDE.md pointed to the right file
    • When inserting data hit a CHECK constraint violation on the source column, Claude caught the error and expanded the constraint without me asking
    • Claude already knew mBank CSVs need special parsing for Polish number formats because a previous session taught it that pattern

    Without this infrastructure, the same task starts with 30+ minutes of “let me understand your codebase” before writing a single line of import code. Every session. That re-orientation tax compounds into hours of waste per month.

    What This Means for You

    I'm not showing this to impress you with speed. Speed is a side effect.

    The real point: a well-configured AI assistant with persistent memory turns “I should really build that” into “done before lunch.”

    Everyone has that list of personal tools they want to build. The expense tracker. The CRM. The dashboard for their business metrics. Most never get built because the activation energy is too high. By the time you spec it out, find the right stack, set up the project, and get to the actual logic, your weekend is gone.

    With a memory system, each session builds on the last. The first session is the slowest (setting up schemas, choosing patterns, establishing conventions). Every session after that is faster. By session three or four, you're adding major features in hours because the AI already knows your entire codebase.

    The AI remembers how you code, what your database looks like, and which patterns your project follows. Each session picks up where the last one left off.

    The Numbers

    Session duration: ~3 hours

    Data processed:

    • 5 bank statement files (4 CSVs + 1 PDF)
    • 4 different parsing formats
    • 1,001 personal transactions
    • 69 business expenses
    • 6 months of wealth data

    System components used:

    • Supabase PostgreSQL (database)
    • NBP API (currency conversion)
    • Parallel AI agents (3 simultaneous parsers)
    • Auto-categorization (15+ spending categories)

    What would have taken without memory:

    • Understanding existing schema: 30-45 min
    • Reading existing API patterns: 15-20 min
    • Finding and understanding helper functions: 15 min
    • Total re-orientation overhead: 60-80 min saved

    That 60-80 minutes of saved re-orientation happens every single session.

    What I'd Build Next

    The system isn't done. 193 transactions still sit in the “other” bucket. Revenue tracking needs to pull from Stripe automatically. The UI needs a wealth overview dashboard alongside the existing business P&L.

    But that's the point. None of this needs to be done in one sitting. Next time I open Claude Code, the memory is already there. The schema, the patterns, the conventions. I'll say “add a wealth dashboard” and the AI will know exactly where to put it, which components to use, and how the data flows.

    The personal finance system I built today isn't the point. The 6 months of accumulated memory underneath it is. That's what made a 3-hour session feel like picking up mid-conversation instead of starting from scratch.

    Update: The accounting system described here is just one piece of a larger puzzle. For the full picture of every system running my business, read I Run a $48K Business With Zero Employees. Here's Every System.

    Everyone running a business has a version of this problem. Money flowing through multiple accounts, no unified view, spreadsheets that get abandoned after a week. What's yours?


    I build work systems for knowledge workers. If you want your own Second Brain with persistent memory that compounds over time, check out Second Brain AI.