AI Build · 2026

A custom personal-finance app

I ran my personal money in Monarch Money and my consultancy's books in FreshBooks. Both are excellent at their own jobs — but for a single-member LLC, where the business and personal sides are really one interwoven picture, nothing tied them together. So I built the thing that did: read-only bank sync, a cash-flow allocation engine, a real P&L with tax-ready export for the CPA, net-worth tracking, and an AI layer that proposes but never decides. It runs my actual finances; the public demo below runs on fictional data.

The demo is public and read-only, seeded with a fictional consultancy's data — explore the P&L, transactions, burn, health, and trends.

$0

Money the app can move

100%

Ledger entries a human approves

7

Read-only tools an LLM can query

1

Model in the loop (Claude)

Node · TypeScript · Postgres · Plaid (read-only) · a small LLM categorizer · vanilla front-end — deployed in Docker behind Traefik. Deterministic core; the model only orchestrates around the edges.

The problem

Two good tools, and a gap right between them.

Monarch Money handled my personal side well — net worth, budgeting, cash flow. FreshBooks handled the business side well — invoicing, expenses, clean books for the consultancy. The catch is that a single-member LLC isn't two separate financial lives. Owner draws, a personal card that catches a business lunch, taxes owed on business profit but paid out of personal cash — it's one interwoven picture, and I was reconciling it across two apps by hand.

Nothing on the market modeled the whole thing in one place: a business P&L and personal cash flow together, feeding the allocation waterfall I actually run on — set aside taxes on net profit, pay myself a flat “salary,” top up a cash floor, and only then free a deployable surplus. So I built it — with one guarantee baked in as a hard property, not a setting: the software can never move my money.

The system

Bank in. Approve. A real P&L out.

Three stages, with a bright line between what the machine pulls, what the AI suggests, and what a human decides. Everything that has to be exact lives in code; the model is kept to the one job it's good at — guessing a category for a brand-new merchant.

  1. 01

    Ingest — read-only

    Plaid pulls transactions and balances. The allowed product list is hard-locked to read-only at boot; money-movement products are rejected and the app refuses to start. It cannot move a dollar.

  2. 02

    Review — AI proposes

    A learned per-merchant rule (or an LLM first-guess for new vendors) drops each transaction into a pending queue with a suggested category. Nothing posts to the books until a human approves it.

  3. 03

    Report — deterministic

    P&L, the cash-flow allocation waterfall, financial health, burn-vs-estimate, and net worth are all computed in SQL/TypeScript. The model never does the math.

The engineering

Read-only banking, and an AI that never writes the books.

Two non-negotiables shaped the architecture. First, the bank connection is read-only at the protocol level: the Plaid product list is allow-listed in code and validated at startup, so money-movement products can't be requested and the app won't boot if one slips in. Second, the language model is never trusted with a number or a posting. It offers a category suggestion into a pending queue; a human approves it; and from there the P&L, the allocation waterfall, the tax set-aside on net profit, and net worth are all computed deterministically in SQL and TypeScript.

The payoff is trust: I can let AI help with the tedious part — recognizing merchants, drafting categories, answering questions — without ever wondering whether it quietly changed a balance or invented a figure. The model orchestrates; the ledger is law.

Keeping the ledger honest

The unglamorous 90%: data integrity.

Pulling transactions is easy. Keeping them correct over months of re-syncs is the actual work. When you re-link a bank, Plaid re-issues new IDs for charges you already have — so the same transaction quietly imports twice. I built a potential-duplicate flag (same account, amount, and merchant within a few days), a one-click dismiss for false positives, and a hard ingest floor so a backfill can never re-add history before the books' start date.

Cleanup is reversible by design. “Archive” is a soft-delete: an archived transaction drops out of every calculation but stays stored and can be restored — so I can be aggressive about tidying without fear of losing a real record. And before I trusted a single figure, I reconciled the entire ledger against the tool I was migrating off of, account by account and month by month, which surfaced the few genuine classification differences and confirmed the rest was clean.

Even net worth respects this. Prior months are reconstructed from the ledger plus historical market prices for the volatile holdings, tied so the latest point always equals today's live balance — an estimate that's honest about being one.

Then I made it answerable

Query the books in plain English — read-only.

The last piece turned the database into something I can just talk to. A read-only MCP connector exposes seven structured tools — P&L, transactions, financial health, trends, burn, net worth, and categories — to an LLM like Claude, behind a proper OAuth 2.1 flow that reuses the app's own login. I can ask “what's my 2026 P&L?” or “reconcile Amazon against the card payments” without opening a page — and, true to the rest of the system, it can read everything and write nothing. In fact, this whole case study grew out of one of those conversations.

Design principles

What building my own money software taught me.

Software the way an operator wants it

If the tool doesn't fit, build the tool.

This is what it looks like when the person who understands the workflow can also build the system that runs it — safety as a hard property, AI kept to its lane, and every number reproducible. If you've got an internal tool that doesn't exist yet, or one that almost fits but never quite did, that's the conversation. Thirty minutes, and I'll come with a point of view.

Or write me directly: hello@joekim.info