Back to projects

Tool Live 2026

Finance automation

A Firefly III instance holding the books, a command line tool that is the only thing allowed to write to it, and an agent on top that turns receipts and plain language into entries the tool will accept. Nothing reaches the ledger without being shown first.

Small translucent slips travelling along threads of light into a tall panel of ruled rows, one row lit, with a silver bar beneath it.

Bookkeeping across several accounts and more than one currency is not difficult work. It is repetitive work, which is worse, because repetitive work is where mistakes hide and where the will to do it at all runs out. The month you skip is the month that takes four hours to reconstruct.

The tempting fix is to point an automation at the bank and let it fill the ledger. That is also how a set of books gets quietly ruined, because an importer that runs unattended will happily enter the same fortnight twice and leave you unable to tell which half of the ledger to believe.

Three layers, and only one of them writes

The books live in Firefly III, an open source finance manager running on our own server. It owns the accounts, the categories, and the history, and it enforces the thing a ledger should enforce: every transaction moves money from a named source to a named destination.

In front of it sits a small Python tool that is the only thing permitted to write. Above that sits an agent, which is where the mess is allowed to be. The agent reads receipts, exports pasted out of a banking portal, and one line records written the way a person actually thinks them, then turns them into the strict format the tool accepts. Judgement happens in the layer that can be argued with, and writing happens in the layer that cannot.

Rules as a file, not as code

Categorisation lives in a JSON file next to the program: an ordered list of patterns, each one naming a keyword, a description, a category, and any tags. The first match wins, and the order is deliberate rather than incidental.

Adding a rule means editing a list, not editing a tool, and reading the file tells you exactly how a given entry got its category. The file is in version control, so the way money has been classified over time has a history rather than a current mood. Malformed rule data stops the tool with an error instead of quietly filing something in the wrong place.

Nothing is written without being shown first

Preview is the default and the commit is a separate flag. A preview prints every transaction that would be created, in full, with the rule that produced it, and then stops. A person reads that list and approves it before anything is written.

Before a batch starts, a read only query reports the latest transaction already recorded for each account, so work resumes from a real cutoff rather than a remembered one. Only one account and one currency are processed at a time, and the parser refuses input it cannot be certain about: future dates, zero amounts, missing descriptions, currency mismatches, ambiguous transfers, and duplicate payloads all stop the run rather than producing a best guess.

Written, then read back, then reversible

A commit is not trusted because the request succeeded. Every write is read back from the ledger afterwards, and the run fails if the stored transaction or the resulting account balance cannot be verified. A network timeout is treated as an unknown rather than a failure, and the rule is to inspect the live account instead of retrying, because a retry is how one payment becomes two.

Every committed batch is journalled, so the tool can be asked to undo the last one. Rollback follows the same shape as everything else: it first prints the exact entries it would delete and waits for approval, and the journal is only updated once a deletion is confirmed by the ledger itself.

Duplicate detection is deliberately left switched off, which sounds like the wrong choice and is not. Two identical amounts to the same shop on the same day are a normal thing that happens, and a tool that silently drops the second one is worse than a tool that shows you both and asks.

The general rule underneath all of it: automation that writes to a system of record should show its work, commit as a separate act, verify what it wrote, and always be able to say what it would take back.

Want something like this?

Tell us what the finished thing should do and roughly when you need it. You get a straight answer about scope and price.