Household budget tracker: sections for incomes, bills, debt, essentials, subscriptions. FastAPI + HTMX + SQLite.
Find a file
archeious 9f1dd7a914 test: cover backup-db.sh exit paths and slug sanitisation
Asserts soft exit when the source DB is missing, a successful backup
round-trips sqlite rows, a non-file sqlite URL is rejected, the reason
slug defaults to "manual", and a messy reason is sanitised to a safe
filename fragment.

Refs #5

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 11:51:55 -06:00
alembic feat(ops): alembic env hook invokes backup-db.sh before migrations 2026-04-17 11:51:49 -06:00
scripts feat(ops): add backup-db.sh for safe sqlite snapshots 2026-04-17 11:51:46 -06:00
src/quartermaster feat(ui): stacked tabular layout, drop card look 2026-04-17 11:21:48 -06:00
tests test: cover backup-db.sh exit paths and slug sanitisation 2026-04-17 11:51:55 -06:00
.gitignore feat(ops): add backup-db.sh for safe sqlite snapshots 2026-04-17 11:51:46 -06:00
.python-version chore: init uv project with FastAPI, SQLAlchemy, Alembic 2026-04-17 11:03:59 -06:00
alembic.ini feat(db): add Entry and DebtTarget models with initial migration 2026-04-17 11:04:06 -06:00
CLAUDE.md docs: document DB safety rule in CLAUDE.md and README 2026-04-17 11:51:52 -06:00
LICENSE Initial commit 2026-04-17 10:57:47 -06:00
pyproject.toml chore: init uv project with FastAPI, SQLAlchemy, Alembic 2026-04-17 11:03:59 -06:00
README.md docs: document DB safety rule in CLAUDE.md and README 2026-04-17 11:51:52 -06:00
uv.lock chore: init uv project with FastAPI, SQLAlchemy, Alembic 2026-04-17 11:03:59 -06:00

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 for dependency management

Setup

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

uv run uvicorn quartermaster.main:app --reload

Open http://127.0.0.1:8000.

Tests

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:

./scripts/backup-db.sh <reason>

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.