From e8b8dc790e30131976fa22d70a79bd2a6ff4c94a Mon Sep 17 00:00:00 2001 From: Tyler Hoang Date: Fri, 8 May 2026 02:00:19 -0700 Subject: Add CLAUDE.md and README Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 43 +++++++++++++++++++++++++++++++++++++++++++ README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 CLAUDE.md create mode 100644 README.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5da8209 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,43 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +```bash +# Install dependencies +pip install -r requirements.txt + +# Run dev server (auto-reload) +uvicorn main:app --reload + +# Run on a specific port +uvicorn main:app --reload --port 8080 + +# Explore the API interactively +open http://localhost:8000/docs +``` + +There are no tests. The SQLite database (`chef.db`) is auto-created on first startup via `Base.metadata.create_all()` in the lifespan handler — no migrations needed. + +## Architecture + +Single-process FastAPI app. All state lives in SQLite. Ollama runs as a separate local process on port 11434. + +**Request flow for AI endpoints:** +1. Router calls `pantry_service.build_pantry_context(db)` to snapshot the current pantry + recent meal history into a plain dict +2. That dict is passed to an `ai_service` function which builds a prompt and calls Ollama synchronously via `run_in_executor` (keeps the async event loop unblocked during the 15–120s generation) +3. Ollama always returns JSON (`format="json"` is set on every call); the response is `json.loads()`'d and returned directly — no intermediate parsing layer +4. The router saves AI output into the DB and returns both the DB record and the raw AI response to the frontend + +**Route registration order matters:** `app.include_router(...)` calls happen before `app.mount("/", StaticFiles(...))`. Reversing this breaks all API routes — the static catch-all intercepts them first. + +**JSON columns:** `recipes.ingredients`, `menu_plans.plan`, and `grocery_lists.items` are stored as JSON strings in `Text` columns. Always `json.dumps()` before saving and `json.loads()` before using. + +**`menu_plans.plan` structure:** `{"monday": {"breakfast": , "lunch": , "dinner": }, ...}`. The `POST /api/menus/generate` response also includes `week_plan` with full recipe details (name, ingredients, instructions) — the frontend uses this for display without a second fetch. On page reload only the plan with IDs is available, so `GET /api/recipes` is needed to look up names. + +**`meal_ingredients.ingredient_name` is denormalized** — it stores a copy of the name string rather than a FK to `ingredients`. This preserves meal history when pantry items are deleted. + +**`grocery.py` exports two routers:** `router` (prefix `/api/grocery`) and `ai_router` (prefix `/api/ai`). Both are included in `main.py`. + +**Config** is loaded from `.env` via `pydantic-settings`. Key vars: `OLLAMA_HOST`, `MODEL_NAME`, `DATABASE_URL`. Change `MODEL_NAME` to switch Ollama models (e.g. `mistral`, `llama3.1`). diff --git a/README.md b/README.md new file mode 100644 index 0000000..2674b7b --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Commis + +An AI-powered personal chef that tracks your pantry, logs what you've eaten, and generates a rotating weekly menu and grocery list — all running locally via Ollama. + +## Requirements + +- Python 3.11+ +- [Ollama](https://ollama.com) running locally with a model pulled (e.g. `ollama pull llama3`) + +## Setup + +```bash +pip install -r requirements.txt +cp .env.example .env # or edit .env directly +uvicorn main:app --reload +``` + +Open [http://localhost:8000](http://localhost:8000). + +### `.env` + +``` +OLLAMA_HOST=http://localhost:11434 +MODEL_NAME=llama3 +DATABASE_URL=sqlite:///./chef.db +``` + +Change `MODEL_NAME` to any model you have pulled locally (`mistral`, `llama3.1`, etc.). + +## Features + +**Pantry** — Add ingredients with quantities, units, categories, and expiry dates. Items expiring within 7 days are highlighted; within 2 days flagged red. + +**Meal Log** — Record what you eat. Commis tracks the last 14 days of history so the AI knows what to avoid repeating. + +**Weekly Menu** — Hit "Generate Menu" and Ollama builds a 7-day breakfast/lunch/dinner plan based on what's in your pantry, prioritizing ingredients expiring soon and avoiding recent repeats. + +**Grocery List** — After generating a menu, "Generate List" diffs the menu's ingredient needs against your pantry and produces a cost-estimated shopping list grouped by store section. "Mark All Purchased" auto-updates your pantry. + +**Quick Recipe** — `POST /api/ai/suggest-recipe` returns one recipe you can make right now from what's on hand. + +## API + +Interactive docs at [http://localhost:8000/docs](http://localhost:8000/docs) once the server is running. -- cgit v1.3-2-g0d8e