# quartermaster Household budget tracker. FastAPI + HTMX frontend, SQLite backend. ## Sections The budget page shows one card per section. Every section accepts a name and amount per entry and displays a running total, except *Primary Debt Target*, which is a pointer to one of the *Debt Minimums* rows. * Incomes * Fixed Amount Bills * Debt Minimums * Primary Debt Target (pointer) * Food and Essentials * Subscriptions * Other ## Requirements * Python 3.12+ * [uv](https://github.com/astral-sh/uv) for dependency management ## Setup ```sh uv sync uv run alembic upgrade head ``` The SQLite file lives at `./quartermaster.db` by default. Override with the `QUARTERMASTER_DB_URL` environment variable (any SQLAlchemy URL). ## Run ```sh uv run uvicorn quartermaster.main:app --reload ``` Open http://127.0.0.1:8000. ## Tests ```sh uv run pytest ``` Tests run against an in-memory SQLite database; no migration step needed. ## Backups The SQLite data file is precious and gitignored. Before any schema change or destructive operation, back it up: ```sh ./scripts/backup-db.sh ``` Backups land next to the database in `./backups/` by default (`QUARTERMASTER_BACKUP_DIR=/some/path` to override) as `quartermaster-YYYYMMDD-HHMMSS-{slug}.db` using SQLite's online backup API (safe even while the app is writing). Alembic invokes the script automatically before every migration via `alembic/env.py`; retention is forever for now. To restore, stop the app, copy the chosen backup over `quartermaster.db`, and restart. ## Project Layout ``` src/quartermaster/ main.py FastAPI app factory routes.py HTTP handlers, HTMX partials service.py Queries, totals, target logic models.py SQLAlchemy models and Section enum db.py Engine, session, PRAGMA foreign_keys=ON config.py DB URL resolution templates/ Jinja2 templates (base, index, partials) static/ CSS alembic/ Migrations tests/ pytest suite ``` ## Scope Single-month budget. Multi-month support is planned for a later milestone and is intentionally not modelled yet.