Mousehold
Household finance ledger scaffold for an evidence-driven household budget and settlement system.
The first milestone is a local proof of concept:
- Python/FastAPI backend with SQLite by default.
- React/Vite web app.
- Local-agent scaffold for bank, CSV, statement, and IMAP ingestion.
- Raw observations become candidate, announced, outstanding, or confirmed financial events.
- Settlement and project summaries are calculated from confirmed ledger state.
Run
python -m venv .venv
. .venv/bin/activate
pip install -r requirements-dev.txt
pip install -e .
mousehold-api
In another shell:
npm install
npm run dev:web
Open http://127.0.0.1:5173.
The API listens on http://127.0.0.1:8000 and exposes OpenAPI at /docs.
If 8000 is already occupied:
uvicorn mousehold_api.main:app --host 127.0.0.1 --port 8001
cd apps/web
npm run dev -- --host 127.0.0.1 --port 5173
MVP workflow
Use Setup to create a household, users, accounts, and connector profiles. The
top bar has a Signed in selector; choosing a user creates a local session
cookie for that browser. This is passwordless local-session support for the
self-hosted MVP, not a hosted multi-tenant auth system.
Create FinTS, IMAP, or CSV/statement connector profiles in Setup before using
the Bank, Mail, or Statements pages. Those pages use the saved profile for
defaults and import attribution, while PIN/TAN, IMAP password, and selected CSV
files stay ephemeral.
Use Inbox after manual entry or imports to review source observations. You can
keep an observation, confirm its linked event, ignore just the observation,
ignore the linked event too, or link the observation to an existing ledger event.
Use Import runs on the dashboard or connector pages to see imported,
duplicate, and event counts from each sync.
Use Setup -> Backup to export the household as JSON or create a local SQLite
backup file.
Browser-driven FinTS access is embedded in the API under /agent/fints/....
Use the FinTS panel in the web app. PIN/TAN inputs go to the API process you
are running locally or self-hosting; normalized observations are imported into
the ledger only when you click import.
For comdirect, choose the comdirect preset in the FinTS panel. Enter your
comdirect Zugangsnummer as the bank user ID, leave customer ID empty, and enter
your registered FinTS product ID.
IMAP access is embedded under /agent/imap/... and available from the Mail
panel. Enter the IMAP host, login, app password, folder, and filters, then list
folders or scan. The scan uses a read-only folder selection and stages parsed
messages in the browser. Ledger observations are stored only when you click
import.
Use the Statements panel for PayPal Activity Download CSV files and Klarna CSV
statements. It previews rows in the browser and imports them as paypal_csv or
klarna_csv confirmation evidence.
Use the Reconcile panel after imports to find likely links between early mail
evidence, PayPal/Klarna statement rows, and bank/FinTS cash movement. Accepting a
suggestion links the evidence and can upgrade the original announced/outstanding
event to confirmed.
Local Agent
Register a local agent after creating a household and user:
mousehold-agent register \
--household-id <household-id> \
--owner-user-id <user-id>
Import demo observations:
mousehold-agent sync-demo \
--connection-id <connection-id> \
--household-id <household-id> \
--owner-user-id <user-id> \
--source-account-id <account-id>
Import bank or PayPal CSV:
mousehold-agent sync-csv \
--connection-id <connection-id> \
--household-id <household-id> \
--owner-user-id <user-id> \
--source-account-id <account-id> \
--source-type bank_csv \
--path ./transactions.csv
Discover FinTS accounts locally:
mousehold-agent fints-accounts \
--profile my-bank \
--blz <bank-blz> \
--server <fints-endpoint-url> \
--bank-user-id <bank-login-id> \
--with-balances
Display recent FinTS transactions locally:
mousehold-agent fints-transactions \
--profile my-bank \
--blz <bank-blz> \
--server <fints-endpoint-url> \
--bank-user-id <bank-login-id> \
--iban <iban> \
--days 30
Import FinTS transactions into the ledger:
mousehold-agent sync-fints \
--api-url http://127.0.0.1:8001 \
--connection-id <connection-id> \
--household-id <household-id> \
--owner-user-id <user-id> \
--source-account-id <account-id> \
--profile my-bank \
--blz <bank-blz> \
--server <fints-endpoint-url> \
--bank-user-id <bank-login-id> \
--iban <iban> \
--days 30 \
--display
The FinTS connector prompts for the PIN if MOUSEHOLD_FINTS_PIN or --pin is
not supplied. TAN mechanism and TAN medium selection are handled interactively
and cached under ~/.config/mousehold/fints/<profile>.json; the cache does not
store the PIN.
You can also run the FinTS browser bridge as a separate local-only process:
mousehold-agent serve --host 127.0.0.1 --port 8765
Set VITE_LOCAL_AGENT_URL=http://127.0.0.1:8765 in apps/web/.env.development
if you choose this mode.
CLI IMAP scanning can still use local environment variables:
MOUSEHOLD_IMAP_HOST=imap.example.com
MOUSEHOLD_IMAP_USERNAME=you@example.com
MOUSEHOLD_IMAP_PASSWORD=app-password
MOUSEHOLD_IMAP_SENDER_FILTERS=klarna,paypal,bestellung,order,invoice
In embedded connector mode, the API process receives FinTS PIN/TAN and IMAP password inputs while the request is running. In separate local-agent mode, those inputs stay out of the API process. In both modes, connector metadata and normalized observations are what get stored; credentials are not written to the database.
Scope
FinTS account and transaction retrieval is implemented and can run embedded in the API or in the separate local agent. It still depends on your bank supporting FinTS PIN/TAN access and on you providing the bank-specific endpoint and login data. IMAP folder listing, scanning, email parsing, preview, and import are implemented for the PoC. PayPal CSV and email evidence are the supported PayPal PoC path. PSD2 aggregator connectors are still scaffolded.
Tests
pytest
npm run lint:web
npm run build:web
The Playwright MVP smoke test expects the API and web app to be running:
npx playwright install
npm run test:e2e