User Guide

This is the archived guide for version 1.1.0. Read the latest guide · All versions

Bank Transaction Insights

Turn a folder of bank statement PDFs into categorized transactions, spending charts, and plain-English answers about your own money — with a nightly backup running quietly in the background.

About this project

This project is jax79sg's means of learning and understanding the challenges of building software with a coding agent. Much of this entire repository — the code, the tests and the documentation — was made with Claude Code, using Anthropic's Claude Opus and Sonnet models.

It is checked by automated tests and security scans on every change. Since the first push, 16 vulnerabilities have been fixed and 72 findings are still open (8 Oct 2026). The full breakdown, and what this is not.

Before you scroll

Every screenshot below is the real app — but the transactions, amounts, merchants, and names in them are AI-generated sample data, created purely to illustrate the screens. None of it is a real transaction or a real person. Each screenshot is marked Demo data as a reminder.

What this app does

You drop your bank statement PDFs into a Google Drive folder. The app reads them, works out the bank, currency, and every transaction line, and files each one under a category — automatically, using your past corrections as precedent. From there you get a searchable transaction list, spending dashboards converted to a single currency, and a place to ask plain-language questions like “how much did I spend on dining last month?”

Every night, it also writes a full CSV backup of your transactions to a separate Drive folder and keeps the most recent 7 — quietly, with no action needed from you. It can also spot when the same statement arrives twice, and it works in a light or a dark theme, on a computer or a phone. A Costs page shows what the app has spent on Google's Gemini models.

01 · First run

Getting started

Three things happen once, in order, before the app has anything to show you.

  1. Sign in Use the username and password you were given. The app is single-user — there's no sign-up screen.
  2. Connect Google Drive Open Settings and click Connect Google Drive. You'll be sent to Google's own consent screen — approving it is what lets the app read your statement folder and write nightly backups.
  3. Run your first ingestion Put a few statement PDFs in the connected Drive folder, then go to Ingestion and click Run Ingestion. Come back to the Dashboard once it finishes.
● Demo data Sign-in screen with username, password and the release number
Sign in — the only screen you'll see before connecting DriveAI-generated sample data

02 · Finding your way around

The top bar

The bar across the top is on every page. Besides the links, it tells you what is waiting for you and what the app is doing right now.

  • Dashboard — an amber number counts recurring payments that need attention: due soon, overdue, a charge waiting for your approval, or newly detected ones.
  • Review — an amber number counts category decisions waiting for you (suggested corrections and disagreements); a violet number counts probable duplicate statements waiting for your decision.
  • The dot beside the theme button pulses green, with "Ingestion run in progress", while a run or a re-categorization is working. Click it to see the most recent finished jobs.
  • v1.1.0 is the release you are running — click it to open the About card in Settings. More on releases.
  • Light / Dark switches the colours. The first time, it follows your device's setting; after that, your choice is remembered in this browser.
● Demo data The top bar with the Dashboard badge, the Review badges, the release number, an ingestion run in progress, and the theme button
The top bar — badges, release number, activity indicator, theme buttonAI-generated sample data
On a phone or another computer

Open the app at the address of the computer running it (for example http://192.168.1.20:8787). The top bar scrolls sideways and every table scrolls inside its own frame. The server only accepts addresses listed in its FRONTEND_ORIGIN setting, so if sign-in fails from another device, add that address there (see the README) — and since a computer's address can change, a reserved address on your router keeps it fixed.

● Demo data The Dashboard in dark mode
Dark mode — the same DashboardAI-generated sample data

03 · Overview

Dashboard

Four views of the same date range: what you spent by category, income against expenses, how spending splits across banks, and what recurring payments are due. Set the From / To fields once and the first three follow.

  • Category Trends — a grouped bar per month, one color per category, so a spike in any one area is easy to spot.
  • Cash Flow — income versus expenses side by side, month over month.
  • Bank Breakdown — the same spending split out by which bank account it came from.
  • Recurring Payments — every subscription and bill you're tracking, with a status per cycle (Paid, Due soon, Overdue or Pending review). Once a payment is trusted, a matching charge auto-applies; anything less certain waits here for your review.
    • Notify sets how many days before the due date a payment turns Due soon — 5 days for a monthly payment and 30 for an annual one unless you set your own for that payment.
    • An annual payment shows Set aside/mo: a twelfth of its amount, to put away each month so the bill is covered when it arrives.
    • Detected Recurring Charges lists repeats the app found in your transactions, monthly or yearly, each with Add and Dismiss.
    • You can add one payment at a time, or paste several lines into Bulk import.
Currency

Everything is converted to a single reporting currency automatically. When an exact exchange rate for a transaction's date wasn't available, the app uses the nearest one it has and says so in a small notice above the chart — nothing is hidden or silently estimated.

● Demo data Dashboard showing Category Trends as a grouped bar chart by month
Dashboard — Category TrendsAI-generated sample data
● Demo data Dashboard Recurring Payments tab with status, set-aside and notify columns, and detected recurring charges
Dashboard — Recurring PaymentsAI-generated sample data

04 · The full ledger

Transactions

Every transaction the app has ever extracted, searchable and filterable, with the converted amount always shown alongside the original.

  • Search by description, or filter by bank, category, or currency.
  • The UNSURE only shortcut jumps straight to anything the app couldn't confidently categorize.
  • Click a transaction's category to correct it — the app remembers the correction and uses it as precedent for similar transactions from then on.
  • Export CSV exports exactly the rows your current filters and search are showing.
  • Sort by clicking a column header marked ↕; click again to reverse. A ▲ or ▼ shows the column currently in charge. Description sorts alphabetically, ignoring capitals, and Converted (SGD) by the converted amount (a transaction with no exchange rate always comes last). Tables elsewhere in the app (Ingestion, Review, Recurring Payments, Costs) sort the same way.
● Demo data Transactions table with sortable column headers, in-flow and out-flow columns, bank, category and converted amount
Transactions — filtered, searchable listAI-generated sample data

05 · Plain-language questions

Ask AI

Ask a question the way you'd ask a person, and get an answer grounded in your own transaction data for the date range you choose — not general financial advice.

  • Set a From / To range, or tick Use all transactions to skip the date filter entirely.
  • Every answer opens with a short disclaimer: it's an observation about your own numbers, not financial guidance.
  • Each row on the Transactions page also has its own Ask AI shortcut, for a question scoped to just that one transaction.
● Demo data Ask AI page showing a question and a grounded answer summarizing dining and groceries spending
Ask AI — a real answer, grounded in the transaction data aboveAI-generated sample data

06 · Turning PDFs into data

Ingestion

This is the only screen where new statements actually become transactions. Everything else in the app is reading from what Ingestion has already processed.

  • Click Run Ingestion to scan the connected Drive folder for PDFs it hasn't seen before — already-processed statements are detected and skipped automatically, so it's always safe to run again.
  • A run in progress can be cancelled from this page at any time.
  • Run History keeps every past run, with how many files were found, processed, skipped, and failed.
  • A statement that fails (usually a scan quality issue) is marked failed with a reason — it never blocks the rest of that run.
  • Click a run to see its files: each one's outcome, the reason if it failed, and how many transactions were read.
  • With duplicate detection switched on, a file that turns out to be a second copy of a statement you already have is skipped and listed as Probable duplicate of … — click that to see the two side by side (see Review).
● Demo data Ingestion page with a Run Ingestion button and a run history table
Ingestion — trigger a run, watch the historyAI-generated sample data
● Demo data A run opened to show a file skipped as a probable duplicate of a statement already held
Ingestion — a run opened: the copy was skipped as a probable duplicateAI-generated sample data

07 · What needs your attention

Review

Four independent things live on this page: category corrections waiting on your judgment, transactions where two categorization methods disagreed, statements that look like copies of each other, and the status of last night's backup.

  • When you correct a transaction's category, the app looks for similar past transactions. A near-certain match is applied automatically; anything less certain is listed here for you to Approve or Reject — one at a time or selected in bulk.
  • Rejecting a proposal never changes the transaction — it's left exactly as it was.
  • Category Disagreements — sometimes the fuzzy-match and the AI classifier land on two different categories for the same new transaction. Rather than silently pick one, the app shows both and asks you to choose.
  • Amounts carry a minus sign when money went out, so you can tell outflow from inflow at a glance.
Backup Status

A full CSV snapshot of every transaction is written to a dedicated Drive backup folder every night, with the 7 most recent kept and older ones cleaned up automatically. This panel shows when that last happened. If it ever asks you to reconnect Google Drive, head to Settings — the connection can occasionally need re-approving.

● Demo data Review page with backup status, category disagreements, probable duplicate statements and suggested corrections
Review — backup status, category disagreements, a probable duplicate and suggested correctionsAI-generated sample data

Probable duplicate statements

Downloading the same statement twice (or being sent a corrected copy) can put every transaction in your totals twice. When duplicate detection is switched on, the app compares the statements it holds and lists pairs that look like the same statement.

  • Each pair shows which copy would be kept and which removed, with how many transactions and manual corrections each holds.
  • View comparison opens the two side by side: the largest transactions of each, marked Also on the other statement or Only on this one.
  • Remove duplicate… asks you to confirm and lists exactly what will be permanently deleted — including any manual corrections or transactions that exist only on that copy. The file in Google Drive is never touched.
  • Not a duplicate — dismiss keeps both and stops the app raising the pair again.
  • Two statements of clearly different sizes are listed for information only: nothing can be removed from them here.
  • Check again asks the app to look again straight away; the panel also says when it last checked.
Switched off until you turn it on

Duplicate detection ships off so you can first test it against your own statements, then switch it on under Settings → Duplicate Statements. Nothing is ever removed without your confirmation.

● Demo data The probable duplicate comparison page with two statements side by side
Review — the comparison behind a probable duplicateAI-generated sample data

08 · What it costs

Costs

What the app has spent on Google's Gemini models, in US dollars — so a bill from Google never comes as a surprise.

  • Four things can use Gemini: statement extraction (reading your PDFs) and Ask AI always do; categorization and embeddings (finding similar descriptions) do only if you switched them to Gemini in Settings. Models you run yourself cost nothing and are not counted.
  • Pick a From / To range (the last 30 days to start with), whether to Show by day, week (starting Monday) or month, and what to Group by: nothing, purpose or model. A day is your own calendar day.
  • The tiles give the total cost, the number of calls and the tokens read and written. The chart stacks the groups (hover for a day's breakdown and total); below it, a table by period and, when grouped, a table by purpose or model with each one's share. Every column sorts.
  • A call that fails is not counted: Google does not charge for it.
How the cost is worked out

Each call is priced from its token count and the three prices under Settings → Model Costs (they start at Google's published prices) at the moment it is made, so changing a price later never rewrites past days. Google reports no token counts for embeddings, so those are estimated (about four characters to a token) and the page says so. Spending before this page existed was never recorded.

Change the prices with the model

The prices are for the Gemini model you have chosen. If you change that model in Settings, change its prices too, or the page will keep pricing at the old rates.

● Demo data The Costs page with totals, a stacked chart by purpose and a table by day
Costs — a month of Gemini spend, by purposeAI-generated sample data

09 · Connections and categories

Settings

Everything that's configured once and rarely touched again — plus, further down, every tunable value the app runs on.

  • Google Drive shows whether the app is connected, and a button to connect or reconnect. Reconnecting doesn't lose anything — it's the same one-time consent step as the first time.
  • Categories is your whitelist — add, rename, or remove any category. UNSURE is reserved by the app itself and can't be removed; it's where anything it couldn't confidently place ends up.
  • About this release (at the bottom of the page) shows the release of the interface and of the server, warns if they differ, and links to the guide for that release.
Removing a category

A category already used by existing transactions can't be deleted outright — the app will tell you how many transactions are affected so you can recategorize them first.

● Demo data Settings page with Google Drive connection card and category management list
Settings — Drive connection and category managementAI-generated sample data

Application Settings

Below the categories list, grouped by area (matching, embeddings, recurring payments, backups, and more) — every value the app runs on, with a plain-language description of what it does. Groups tinted amber contain advanced settings; the rest are safe to leave alone. Editing one shows exactly which container needs restarting, and every past change is kept in a history log.

Sensible defaults

Nothing here needs to be touched to use the app day to day — the defaults are what a real deployment runs on. This exists for the moment you do want to tune something, not as a checklist to work through.

● Demo data Application Settings showing the categorization provider choice and its related settings
Settings — Application Settings, grouped by areaAI-generated sample data
  • Where categorization and embeddings happen. categorization_provider and embedding_provider choose between a model server of your own (local, the default) and Google's Gemini. With Gemini, each transaction's description and amount is sent to Google for categorization; the description, direction and price range for embeddings. It costs a few cents for a full set of transactions.
  • Duplicate Statements holds the switch for duplicate detection and how closely two statements must match.
  • Model Costs holds the three prices (Gemini input, output and embedding, per million tokens) that the Costs page uses.
● Demo data The About this release card showing the interface and server releases and links to the guide
Settings — About this releaseAI-generated sample data

10 · About this project

How it was made, reviewed and hardened

This is jax79sg's means of learning and understanding the challenges of building software with a coding agent. Much of this entire repository — the code, the tests and the documentation — was made with Claude Code, using Anthropic's Claude Opus and Sonnet models. What follows is how it was checked, including the parts that are not flattering. The figures are a snapshot from GitHub's own security records on 8 October 2026.

Reviewed

  • Approval gates, on the record. Requirements, designs and plans are written first and approved by jax79sg before code is generated. Every request, answer and approval is logged verbatim (443 logged inputs); some approvals were a standing instruction to carry on, and the log shows which.
  • Pull requests with automated checks. Since 21 August 2026 every change has gone through a pull request (23 so far), each running about 15 checks: lint, type checks, tests, Docker builds, CodeQL, gitleaks, GitGuardian and dependency scans. Those were only switched on on 17 August, two weeks after the first push.
  • About 1,800 automated tests, run against a real PostgreSQL, with property-based tests and nightly browser tests. For recent features the tests were themselves tested by deliberately breaking the code to confirm a test notices.

Hardened

  • 57 of the server's 61 operations need a login. The four that don't are the health check, the release number, sign-in, and the address Google redirects back to when you connect Drive. Passwords are stored hashed (bcrypt) and sessions expire.
  • The server accepts browser requests only from listed addresses, and Settings can change only an allow-list of values and never shows secrets.
  • Destructive steps ask first and say exactly what they will delete; the one-time re-ingestion needs a typed confirmation and a backup.
  • Secrets stay out of the repository: GitHub secret scanning and push protection are on, and CI runs gitleaks.

Vulnerabilities since the first push

Dependency and code scanning began on 17 August 2026, so nothing before that was scanned.

  • Dependencies (Dependabot): 80 raised, 14 fixed (1 critical, 4 high, 8 medium, 1 low), 63 still open (33 distinct advisories: 3 critical, 9 high, 21 medium) and 3 auto-dismissed by GitHub.
  • Code scanning (CodeQL): 11 raised, 2 fixed (a CI-only fixture password echoed in a script's output; a missing workflow permission), 9 still open (all medium: workflows without an explicit permissions block).
  • Leaked secrets: none flagged by GitHub.
16 fixed, 72 still open

Most of the open dependency alerts are advisories published in early October against PyJWT and urllib3, repeated across the project's lock files. Automatic security updates are off and the CI dependency scan only reports, so these are fixed by hand, and have not been yet.

What this is not

No independent security review or penetration test has been done, and the workflow's security-baseline rules were not enabled: the hardening comes from the scanners, the tests and jax79sg's approvals. It is a single-user app designed to run on your own machine or network. Treat it as a learning project. The live numbers are on the repository's Security tab.

11 · Which version?

Releases

The app has a release number, written MAJOR.MINOR.PATCH. This guide is for version 1.1.0, and every release keeps its own copy of the guide.

  • The number is shown on the sign-in screen, in the top bar of every page and in Settings → About this release, which also links to the guide for exactly that version.
  • The list of all releases links to every earlier guide, so you can read the one that matches the version you run.
  • If the interface and the server report different releases, Settings says so — rebuild and restart both so they match.

What's new in 1.1.0

  • The Costs page — what the Gemini calls cost, by day, week or month, grouped by purpose or model — and the Model Costs prices in Settings.
  • Transactions can now be sorted by Description (ignoring capitals) and by Converted (SGD), and rows with the same value stay in a steady order from page to page.

Earlier releases

1.0.0, the first numbered release, added probable duplicate statements, the reworked recurring payments, sorting, dark mode, the activity indicator, Gemini as an option for categorization and embeddings, and release numbers with a guide for every release. Its guide is kept as it was: see the list of all releases.