Terminal-first finance tracking CLI for recurring transactions, spend breakdowns, and upcoming charge forecasts.
MVP sources:
- YNAB API transactions + scheduled transactions (money movement source of truth)
- Proton Mail Bridge IMAP purchase emails (enrichment evidence only, raw body not persisted)
- Bun 1.2+
- A writable state directory (default
~/.fintrack) - Optional for live sync:
- YNAB personal access token
- Proton Mail Bridge IMAP credentials
bun install
bun run src/cli.ts --help
# or
./bin/fintrack --helpcp .env.example .env.env is ignored by git. Use it for secrets like YNAB_TOKEN and optional FINTRACK_IMAP_PASS.
# Configure YNAB
fintrack setup ynab --token-env YNAB_TOKEN --budget-id last-used
# Configure Proton Bridge IMAP
fintrack setup email \
--imap-host 127.0.0.1 \
--imap-port 1143 \
--imap-user "<bridge-user>" \
--imap-pass-cmd "pass show fintrack/bridge"
# or use .env-backed password:
fintrack setup email \
--imap-user "<bridge-user>" \
--imap-pass-cmd "printf '%s' \"$FINTRACK_IMAP_PASS\""
# Sync all sources then recompute derived layers
fintrack sync all --days 365
# YNAB bootstrap window defaults to the last 6 months.
# Override for deeper history when needed:
fintrack sync ynab --since 2024-01-01
# Reports
fintrack report spend --month 2026-02 --group-by merchant
fintrack report subscriptions --month 2026-02 --explain
fintrack report upcoming --days 30 --visual
# Health checks
fintrack doctor --jsonfintrack
setup
ynab
email
sync
ynab
email
all
report
spend
subscriptions
upcoming
doctor
fintrack sync without a subcommand behaves as fintrack sync all.
--json--no-input--config <path>--state-dir <path>--verbose
0success1runtime failure2invalid arguments3auth failure4upstream failure/rate-limit exhaustion5partial success
report spend --json includes:
totalMinor(integer minor units, e.g. cents)totalMajor/totalUsd(decimal major units)totalDisplay(currency-formatted string)
Rows include matching fields (total_minor, totalMajor, totalUsd, totalDisplay) to reduce unit ambiguity.
bun run export:recurring
# optional custom output path and db path:
bun run src/tools/export-recurring-csv.ts exports/recurring.csv ~/.fintrack/fintrack.dbCSV fields include cadence-specific cost columns (weekly_usd, monthly_usd, yearly_usd, etc.).
Only the column matching the merchant cadence is populated.
Stored email data is limited to extracted evidence fields and operational metadata:
- stable dedupe IDs/hashes
- sender domain / timestamp / parser info
- extracted item name + price (if detected)
Raw body content and attachments are not persisted.
Rules are loaded from <state-dir>/rules.json and synchronized into SQLite rule tables.
Default template:
{
"aliases": {
"adobe systems": "Adobe"
},
"ignore": [
{ "merchant": "internal transfer", "reason": "non-spend flow" }
],
"force": [
{ "merchant": "icloud", "reason": "known subscription" }
]
}bun x tsc --noEmit
bun testCurrent automated tests cover:
- matching tie-break determinism
- recurring monthly detection and short-month prediction clamp
- migration forward-only behavior on DB reopen
- CLI doctor smoke test (JSON mode + exit code behavior)
You can still run local setup, doctor, migrations, and report plumbing in an empty DB.
Live sync ynab and sync email require credentials/config and will return actionable auth/config errors when missing.