CLAUDE.md (3382B)
1 # CLAUDE.md — Recipe & Grocery Telegram Bot 2 3 ## Project Purpose 4 5 A self-hosted Telegram bot for tracking recipes, managing a weekly staples 6 list, and generating grocery lists. Runs as a long-polling service in an 7 LXC/VM on Proxmox, alongside the rest of the homelab stack. 8 9 ## Dietary Constraints 10 11 - **Ketogenic**: recipes/ingredients should be tagged `keto` automatically 12 based on carb content where determinable, but always allow manual override. 13 14 Nut-free tracking was considered and deliberately dropped (2026-07-02): 15 single-user household, user doesn't eat nuts, so nut-containing recipes are 16 very unlikely to enter the system in the first place. Not worth the schema/ 17 logic complexity for this tool. 18 19 ## Tech Stack 20 21 - Python 3.11+ 22 - `python-telegram-bot` (async, v22+) — long polling, no public webhook needed. 23 v20.x is broken on Python 3.14 (AttributeError building `Updater`, 24 confirmed 2026-07-03) — pin to v22+ if the system Python is 3.14. 25 - SQLite via `sqlite3` stdlib or `sqlmodel` if an ORM is wanted — keep it 26 simple, this doesn't need SQLAlchemy's full weight 27 - `systemd` service file for deployment (same conventions for logging and 28 restarts as the rest of the homelab stack) 29 30 ## Data Model 31 32 - `recipes(id, name, servings, instructions, source, is_keto)` 33 - `ingredients(id, recipe_id, name, quantity, unit, category)` 34 - `staples(id, name, default_quantity, unit, category)` 35 - `grocery_list_items(id, name, quantity, unit, category, source)` 36 - `source` is one of `staple`, `recipe`, `freeform` — keep provenance so 37 items can be intelligently merged/deduped and so `/clearlist` behavior 38 is predictable 39 40 ## Bot Commands (initial scope) 41 42 - `/addrecipe` — conversational flow OR paste structured text/URL to parse 43 - `/recipes [tag]` — list/filter recipes 44 - `/staples` — show current staples list 45 - `/staples add <item>` / `/staples remove <item>` 46 - `/grocerylist [recipe1, recipe2, ...]` — staples + named recipes merged 47 into one list, quantities summed for matching items 48 - `/add <item>` — freeform one-off add to the current grocery list 49 - `/clearlist` — reset the working grocery list 50 - `/random [tag]` — random recipe suggestion, optionally filtered 51 52 ## Merge Logic Rules 53 54 - Same-name ingredients across recipes/staples/freeform sum their quantities 55 when units match; if units don't match, keep as separate line items rather 56 than guessing a conversion. 57 - Category (produce, dairy, pantry, etc.) is used for grouping the final list 58 output, not for merge logic. 59 60 ## Code Style / Conventions 61 62 - Match the conventions already used in Jake's other homelab projects: 63 small, readable functions over cleverness; explicit error handling. 64 - No unnecessary abstraction layers — this is a personal tool, not a 65 library. Prefer a flat file structure (`bot.py`, `db.py`, `models.py`, 66 `parsing.py`) over deep package nesting. 67 - Config (Telegram bot token, DB path) via environment variables or a 68 `.env` file — never hardcoded, never committed. 69 70 ## Out of Scope (for now) 71 72 - Web UI — SQLite backend should make this easy to bolt on later if wanted 73 - Multi-user support — this is a single-household tool 74 - Nutrition/macro calculation beyond keto tagging 75 76 ## Testing 77 78 - Unit tests for merge logic (the trickiest part) using `pytest` 79 - Manual testing against a test Telegram bot token before pointing at the 80 real one