Foomax

I pointed Claude at a decade of credit card statements. Then at a second archive.

September 2026

I had a folder of PDF statements from a credit card I’ve held for over a decade, and an afternoon free. I gave Claude Code three instructions:

  1. Build a tool for scanning the statements.
  2. Use it to extract every transaction into a CSV.
  3. Analyse the CSV for habits, trends, and outliers.

What came back was better than I expected, occasionally wrong in instructive ways, and — once I pointed it at my AI chat history as a second dataset — genuinely surprising. This post is half about what a decade-plus of money looks like, and half about the prompting techniques that made the analysis trustworthy, because the second half is what I’d want to read if this were someone else’s blog.

Act 1: Make the parser prove itself

The statements span two completely different layout generations, and in both, whether a number is a debit or a credit is encoded only by which column it sits in. Parse naively and every payment becomes a purchase.

The one design decision that mattered: every statement prints its own summary — opening balance, total debits, total credits, closing balance. So the tool reconciles itself against the statement’s own arithmetic: opening + debits − credits must equal the printed closing balance, to the cent, for every statement.

That single check caught four real bugs before I ever saw the data:

Final state: every statement unique once a few duplicate files were dropped, several thousand transactions, and every single one reconciles exactly. When an agent writes a parser for you, don’t check its output — make it check its own.

Act 2: What the money said

The card changed jobs twice. For its first few years it was a travel instrument: many countries, many currencies. Then a long quiet stretch as a background card. Then, in recent years, it became the default way I pay for everything.

The growth is frequency, not extravagance. Comparing full years: a handful of transactions a month in the early years versus more than ten times that by the end — while the median purchase size stayed flat throughout. The card didn’t start buying bigger things; it started buying all the things.

Total fees and interest across the whole life of the card: under $1,000. No interest charged in years. If you’re going to hold a credit card for that long, this is the report card you want.

The one line that only goes up: subscriptions. Digital subscriptions ran flat and small for years. Then, over three consecutive years, they multiplied several-fold each year — close to an order of magnitude in total. Nothing else in the dataset has that shape. Nobody decides to quadruple their subscription spending; it’s the aggregate of a dozen individually reasonable small decisions.

Act 3: Categories are hypotheses. Correct them.

Claude’s first categorisation pass looked plausible and was quietly wrong in places only I could know about. A “personal services” bucket was actually a set of recurring service providers I use regularly. A merchant it filed under electronics really does sell electronics — that one it had right — but another “electronics” merchant, a cryptically named web-payment line, turned out to matter more (Act 4).

So I did the unglamorous thing: I told it who my merchants actually are, in plain English, and had it re-run everything. Two useful things happened:

  1. It didn’t just relabel rows — it rewrote the rules, so every past and future statement gets the correction.
  2. It deleted its own cleverness. It had a heuristic guessing that name-shaped merchants were people. When my corrections showed the heuristic was ~90% wrong (one “person” turned out to be a cafe; another, a transport operator), it removed the heuristic entirely rather than patching it. Explicit ground truth beats inference, and an agent that will delete its own ideas is worth more than one that defends them.

The tool grew a review command — list the biggest unlabelled merchants, tell me who they are, re-scan — which is just active learning with a human oracle, run over a CSV.

Act 4: The crossover

Then the experiment I actually wanted to run: I exported my AI conversation histories — every provider, several years, thousands of conversations — and asked Claude to correlate them with the spending.

It identified my own purchases better than the bank could. The ledger showed periodic charges at that cryptic merchant, still filed under electronics. The chat history showed me working through sizing questions for a piece of equipment. The merchant turned out to be the retailer that sold it, and the matching purchase hit the card the day after that conversation. One dataset knew what; the other knew why; neither alone knew both. Three “mystery merchants” and one fake statistical outlier (a “government services” anomaly that was actually a routine administrative fee) dissolved the same way.

Deliberation time scales backwards with reversibility. One expensive, hard-to-return item got months of research conversations before I bought it. An easily returned one got a single day. This is, I suspect, not unique to me.

The best purchase was the one that didn’t happen. The chat record contains a long deliberation about an expensive course, in which I’d explicitly told the model to act as a friend who cared about my long-term welfare rather than as a salesperson. The card record contains no purchase. A model instructed to be a sceptical friend, consulted before the checkout page, is the cheapest financial advisor that has ever existed.

Busy months are cheap months. I’d assumed my heaviest AI-usage months would be my most expensive ones. The correlation is ~zero. The actual pattern is stranger: my highest conversation-volume months were also among the cheapest. When I’m deep in focused work, consumption collapses. Spending spikes live somewhere else entirely — in the restless months. If I ever build a personal dashboard, “spending velocity as an inverse focus metric” goes on it.

When one dataset goes dark, the other keeps recording. There’s a long gap in my chat exports. The ledger doesn’t blink: it dates a whole life development to within weeks, where the chat record only picks it up mid-stream much later. Archives triangulate.

Act 5: The techniques, extracted

Everything above reduces to eight moves, all of them transferable:

  1. Ask for the instrument, not the answer. “Build a tool, then use it” gets you something inspectable, re-runnable, and fixable. “Analyse my statements” gets you vibes.
  2. Give the agent an oracle. Find something in your data that must sum, balance, or reconcile, and make agreement non-negotiable. This converts silent parsing errors into loud failures. It caught four.
  3. Make it build its own review loop. The review command — surface the biggest unknowns, ingest my answers, re-run — did more for data quality than any prompt phrasing.
  4. Supply ground truth generously. Five minutes of “here’s who these merchants actually are” beat any amount of model cleverness. The model’s job is to propagate your knowledge, not replace it.
  5. Commission both framings. For the self-analysis layer I asked for a positive framing and a constructive-criticism framing as separate deliverables. A model asked for one summary averages into mush; asked for two adversarial ones, it commits to each. (Related: occasionally ask it to roast you. Calibrating.)
  6. Triangulate datasets. The single most productive prompt in the whole project was “correlate this with that.” Cross-referencing beats deep-reading either source alone, and it’s exactly the work humans are worst at doing by hand.
  7. Use the dials. Effort and model settings are there to be switched mid-session — cheap mode for extraction plumbing, maximum-thinking mode for the synthesis passes.
  8. Workshop the prompt itself. Before the big analysis run I asked the model to critique and rewrite my prompt. Thirty seconds of meta beats three retries.

Coda

A privacy note, because it’s load-bearing: everything here ran locally over files on my machine, and this post reports aggregates. The full analysis knows considerably more about me than I’m publishing — identifying details that are not going in a public post — and the same model that wrote the analysis helped decide what stays out of this post. If you replicate this (you should — everyone’s bank offers statement PDFs, and everyone’s chat history is exportable), decide before you start what the public artifact is allowed to contain.

A decade-plus of statements compresses to this: under $1,000 of fees, one large purchase the bank never understood, a subscription line growing like a weed, and the discovery that my money is quietest exactly when my mind is loudest. Not bad for a folder of PDFs.

Built with Claude Code. The scanning tool is ~600 lines of Python with no dependencies beyond pdftotext, and the techniques above will survive contact with your bank’s PDFs, which are worse than mine.

LLM-to-read