Adds `fin` — a typer/httpx CLI for the deployed API — so Claude Code and other agents can consume fin over HTTP without an MCP server. Backend: - api/app/auth.py: require_api_token dependency (no-op unless FIN_API_TOKEN env is set; RFC 7235 case-insensitive Bearer, constant-time compare). All nine routers wired; /api/health exempt for k8s probes. - GET /api/openapi.json added as an explicit token-gated route (FastAPI's built-in openapi_url bypasses dependency injection). - GET /api/transactions gains an optional `limit` query param (ge=1). CLI (cli/): - fin_cli/client.py: FinClient — sync httpx wrapper, zero typer/rich imports (MCP-ready core for a future MCP server). - Subcommands: networth, accounts, categories, tx, transfer, settle, split-expense, splitwise-paid, reconcile, holdings, stock, rsu, spending, prices. Every command supports --json for agent use. - fin tx add refuses transfer/settlement types to prevent single-leg writes. - Config via FIN_API_URL (required) and FIN_API_TOKEN (optional). Agent skill: .claude/skills/fin/SKILL.md — command map, jq patterns, and domain invariants (two-leg atomicity, net-share splitwise math, derived holdings, funded-buy, soft-deactivate, FIN_API_TOKEN web-UI lockout warning). Tests: 25 e2e tests (FinClient → real routes → temp SQLite) covering auth on/off, all key invariants (two-leg linkage, fee-in-balance, net-share math), transfer whole-group delete, and linked-leg edit rejection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPBt3s7Jyr2nozQTrVVGA4
fin
A self-hosted, single-user personal net worth tracker. fin aggregates bank accounts, investment portfolios, Splitwise balances, and receivables into a single EUR-denominated view, with daily automated snapshots and live stock prices.
Features
- Dashboard — current net worth broken down by account group, plus recent transactions
- Spending — monthly expense breakdown by category with a pie chart
- Portfolio — investment account holdings with live USD prices (via yfinance), P&L per position, and EUR conversion
- History — net worth over time as a line chart; snapshots taken automatically at midnight
- Transactions — full transaction log across all accounts
- Quick-add flows — mobile-friendly sheet for logging expenses, transfers, Splitwise splits/settlements, and stock trades
- Settings — manage accounts (bank, investment, RSU, Splitwise, receivable) and spending categories; manual balance override per account
- Multi-currency — EUR base currency; exchange rates via Frankfurter API
Quick Start
git clone <repo>
cd fin
docker compose up -d
The app is available at http://localhost.
Environment / Config
Set in docker-compose.yml under the api service:
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
sqlite:////data/fin.db |
SQLite path inside the container |
Data is persisted in a named Docker volume (sqlite_data). No other configuration is required.
Architecture
The backend is a Python FastAPI app backed by SQLite via SQLAlchemy; APScheduler runs a nightly job to fetch stock prices (yfinance) and currency rates (Frankfurter) and record a net worth snapshot. The frontend is a React + TypeScript SPA served by Nginx, communicating with the API through the same Nginx container via reverse proxy.