Writing a glob by hand meant guessing what it would catch, then running retag
to find out. The new screen, on 4, puts the glob, account and tag fields on
the left and every still-untagged description on the right, sorted
alphabetically and grouped by description with an occurrence count.
Matches are marked as the glob is typed, along with a count, so the effect of
a rule is visible before it is written. Enter appends it to rules.toml via
config.AppendRule, reloads the engine from disk and retags, so the rows it
caught leave the list immediately.
Rules are appended rather than prepended, keeping the precedence of anything
already in the file. Since the preview only lists transactions no existing
rule has tagged, it reflects that precedence for free.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Import ran inline in the update loop, so the whole interface froze for as
long as pdftotext took over a stack of statements, with no way to tell work
in progress apart from a hang.
It now runs as a command off the event loop, with a spinner and a note that
PDFs take a while. A repeat i press is ignored and retag is refused while an
import is running, so nothing writes to the index concurrently. The result
arrives as a message carrying the counts, the first failure, and the first
warning with a count of any others.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An account folder is only registered in the index by an import, so a freshly
configured account.toml produced an empty accounts table with nothing to say
why or what to do about it.
Each view now explains its own emptiness and names the key that resolves it,
distinguishing configured-but-not-imported from no-folders-at-all, and
telling apart a filter that matched nothing from having no data.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Running the tool from anywhere required either a --root flag or an exported
MONEY_ROOT. Read the data root from $XDG_CONFIG_HOME/money/config.toml
(~/.config/money/config.toml) instead, so it can be configured once.
Resolution order is --root, then $MONEY_ROOT, then the config file, then
~/money. A leading tilde in the config file is expanded, since no shell has
done it for us, and relative paths are made absolute.
The new "money config" subcommand prints the resolved root and which rule
chose it, which is the first thing to check when the tool reads the wrong
directory.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A data directory holds one folder per account. Statements dropped into
those folders are parsed into a rebuildable SQLite index, categorised by
ordered glob rules in rules.toml, and browsed or hand-tagged in a Bubble
Tea TUI. Movements between the user's own accounts are marked as
transfers by the same rules and excluded from spending totals.
Manual tags and transfer marks are stored separately from the rule-derived
ones and always win, so editing rules.toml and re-running retag never
destroys hand edits.
Parsers are pluggable. Three are ported from the Python extractors they
replace -- nlb and traderepublic read PDFs via pdftotext -layout, revolut
reads the CSV export -- alongside a configurable-column CSV parser and a
cmd parser that shells out to an external script.
Both ports fix two latent bugs in the originals: the sign character class
rejected the typographic minus U+2212 that some PDF fonts emit, and NLB's
hardcoded continuation indent broke when pdftotext compressed runs of
spaces, so the threshold is now measured from the description column.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>