# Project pack: KitchenOwl @ cac641c

Facts about **KitchenOwl** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v2.md). This pack is pinned to one version and never changes after publication.

> KitchenOwl is a shopping list that everyone in the house shares. Tap a tile to add milk, and it appears on your partner's phone straight away, even in a shop with bad signal. Keep your recipes, plan the week's meals and add a recipe's ingredients to the list in one go. It can also track shared spending, so you know who paid for what. There are apps for phones, tablets and computers, and you run the server yourself.

## Version and source
- Repository: https://github.com/TomBursch/kitchenowl
- Pinned commit: `cac641c619963f13134aecb80fadfb81f0c9249b`. Use exactly this version.
- Fresh checkout: use the setup below in an empty folder. If you already have this exact source checked out, keep your branch and use the development command instead; do not clone again or reset local changes.
- Or download a zip: https://github.com/TomBursch/kitchenowl/archive/cac641c619963f13134aecb80fadfb81f0c9249b.zip
- Official docs: https://docs.kitchenowl.org
- Licence: **AGPL-3.0-only**. Free to use and change. If you run a changed version that other people use over the internet (not just your own household), you must offer them your source code under the same licence. Private family use has no extra obligations.

## Running the pinned source
- Fresh pinned-source setup (skip clone and checkout in an existing worktree):

  ```sh
  git clone https://github.com/TomBursch/kitchenowl bespoke-kitchenowl
  cd bespoke-kitchenowl
  git checkout --detach cac641c619963f13134aecb80fadfb81f0c9249b
  # Prepare development requirements and local configuration first.
  # Setup notes: API on :5000; then in kitchenowl/: flutter packages get && touch .env && flutter run
  cd backend && uv sync && uv run flask db upgrade && uv run wsgi.py
  ```

The commands below are a starting point from the reviewed source. Prepare the listed tools, local configuration and companion services before starting the app. These instructions have not yet been validated in participant sessions.

### Separate trial of the current release
This tries an upstream release, which may differ from the pinned source above. It does not run your source changes. Use only sample data and a separate data directory or volume. Check the upstream documentation before running it.

  ```sh
  docker volume create kitchenowl_data && docker run -d -p 8080:8080 -e "JWT_SECRET_KEY=$(openssl rand -hex 32)" -v kitchenowl_data:/data tombursch/kitchenowl:latest # then open http://localhost:8080 and create the first (admin) account, or connect the phone app to this address.
  ```

- Needs: Docker (the all-in-one image), or separate kitchenowl-web and kitchenowl-backend images with docker compose, For development, Python with uv for the backend and the Flutter SDK for the app
- Develop: `cd backend && uv sync && uv run flask db upgrade && uv run wsgi.py   # API on :5000; then in kitchenowl/: flutter packages get && touch .env && flutter run`
- Test: `cd backend && uv run pytest   # app: cd kitchenowl && flutter test`
- Check/lint: `cd kitchenowl && flutter analyze   # backend uses pre-commit hooks (uv run pre-commit install)`
- Stack: python, dart (Flask, SQLAlchemy, Alembic (Flask-Migrate), Socket.IO, Flutter, flutter_bloc). Difficulty for a non-developer with an AI: **moderate**. Two parts: a Flask backend (backend/) and a Flutter app (kitchenowl/) that is the website, the phone apps and the desktop apps at once. Server behaviour is set with environment variables; household options are in the app. Code changes often touch both a Flask controller and a Flutter page, and the Flutter toolchain is a large install.

## Customisation points (settings → extend → code)
- **household-features** [settings]: Turn the meal planner and expenses on or off, add members, set the language for the default item list. → `Household settings in the app (kitchenowl/lib/pages/settings_household/, backend/app/controller/household/)`
- **shopping-lists-and-categories** [settings]: Several lists (supermarket, chemist, market), categories sorted like your shop, and icons per item. → `Household settings → shopping lists, categories, item icons (backend/app/controller/category/, kitchenowl/lib/item_icons.dart)`
- **theme-and-language** [settings]: Light or dark mode, colours from your device, bigger item tiles for older eyes, and the interface language. → `App settings → theme, accent colour, item size and list style (kitchenowl/lib/cubits/settings_cubit.dart, kitchenowl/lib/styles/themes.dart, kitchenowl/lib/styles/dynamic.dart); 45+ languages in kitchenowl/lib/l10n/`
- **server-settings** [settings]: Registration, email, sign-in providers, PostgreSQL, the optional AI ingredient parser. → `Environment variables (docs/docs/self-hosting/advanced.md)`
- **recipe-import** [extend]: Paste a recipe link and KitchenOwl reads the ingredients, with a local parser or an AI model you choose. → `Recipe → import from a link (backend/app/service/recipe_scraping.py, backend/app/service/ingredient_parsing.py); docs/docs/self-hosting/ingredient_parsing.md`
- **api-and-integrations** [extend]: Add items from a script, a voice assistant or a Home Assistant automation. → `REST API (docs/docs/reference/API.md, backend/app/controller/), Python client and Home Assistant integration (separate kitchenowl-python and kitchenowl-ha repositories)`
- **mcp** [extend]: Let an AI assistant read your recipes and add to your shopping list, using your KitchenOwl login. → `/mcp endpoint, enabled with KITCHENOWL_MCP_ENABLED (backend/app/controller/mcp_controller.py)`
- **app-screens** [code]: New or changed screens in the Flutter app. → `kitchenowl/lib/pages/ (e.g. recipe_cooking_page.dart, expense_overview_page.dart), kitchenowl/lib/widgets/, text in kitchenowl/lib/l10n/app_en.arb`
- **backend-logic** [code]: New data or behaviour on the server. → `backend/app/controller/ (API) → backend/app/models/ → backend/migrations/ (database changes)`

## Must keep working
- Existing households, lists, recipes, plans and expenses. Back up /data before changing anything.
- Household separation. Members must only see their own households' data.
- Real-time sync and offline use in the apps (Socket.IO events and the app's local cache).
- The API used by released phone apps. Add fields and endpoints rather than changing existing ones.
- Database changes need an Alembic migration in backend/migrations/.
- App text goes in kitchenowl/lib/l10n/app_en.arb; other languages come from Weblate.

## Staying updatable
Household settings, environment variables, the API and the MCP endpoint cover most family needs. For code changes, upstream asks you to open an issue first for new features or API changes, one PR per fix or feature, with conventional commit messages. The project calls itself a public alpha, so expect changes between releases.

## Data, costs and safety
- Personal data: **yes**. Stored in: SQLite database and uploaded photos in the kitchenowl_data volume (/data); PostgreSQL optional. Holds your household's lists, recipes, meal plans and spending. Back up the /data volume (database.db and the upload folder) before upgrades. Households can export and import their data from the household settings.
- Service: LLM provider through LiteLLM (OpenAI, OpenRouter and others) (optional, pay-per-use (or free with local Ollama)): Better ingredient recognition when importing recipes from websites, especially in languages other than English. Off by default; a local model is used instead.
- Service: Email (SMTP) (optional, free with most providers): Password resets and email verification.
- Service: OpenID Connect, Google or Apple sign-in (optional, free (self-hosted) or varies): Log in with an existing account instead of a KitchenOwl password.
- Service: Recipe websites (optional, free): The recipe importer fetches the page you paste a link to.
- Setting `JWT_SECRET_KEY` (**secret**: the person enters it themselves, never in chat): Long random string that signs logins. Change it from PLEASE_CHANGE_ME. Never paste it into an AI chat.
- Setting `FRONT_URL`: The exact address you open KitchenOwl at, including https:// (needed for sign-in providers and browser security).
- Setting `OPEN_REGISTRATION`: Leave false so strangers can't make accounts. Add family members yourself.
- Setting `DB_DRIVER`: sqlite (default) or postgresql. DB_HOST, DB_PORT, DB_NAME, DB_USER and DB_PASSWORD go with it.
- Setting `DB_PASSWORD` (**secret**: the person enters it themselves, never in chat): PostgreSQL password, if you use PostgreSQL.
- Setting `SMTP_HOST`: Mail server for password resets. SMTP_PORT, SMTP_USER and SMTP_FROM go with it.
- Setting `SMTP_PASS` (**secret**: the person enters it themselves, never in chat): Mail account password.
- Setting `LLM_MODEL`: Optional AI model for ingredient parsing, e.g. ollama/llama3.1 or gpt-4o-mini. Empty means the built-in local parser. LLM_API_URL sets the server address.
- Setting `OPENAI_API_KEY` (**secret**: the person enters it themselves, never in chat): Only if LLM_MODEL uses OpenAI (other providers use their own key name, such as OPENROUTER_API_KEY).
- Setting `KITCHENOWL_MCP_ENABLED`: Set to true to turn on the MCP endpoint at /mcp so an AI assistant can use your lists and recipes. Off by default.
- Setting `OIDC_ISSUER`: Sign-in provider address for OpenID Connect. OIDC_CLIENT_ID and OIDC_CLIENT_SECRET go with it.
- Change JWT_SECRET_KEY from the example value and keep OPEN_REGISTRATION off.
- Upstream recommends running it behind a reverse proxy with HTTPS (and HSTS) if it is reachable from outside your home.
- If you set LLM_MODEL to a cloud model, ingredient lines from imported recipes are sent to that provider. Leave it empty or use Ollama to keep everything local.
- The MCP endpoint lets an AI assistant read and change your household's data. Only enable it if you need it.

---

# Customising KitchenOwl

KitchenOwl has two parts: a Python (Flask) server and a Flutter app that is the website, the phone apps and the
desktop apps at once. **Most household needs are settings in the app or environment variables on the server.**

## Level 1: Settings (no code)
- **Household settings (in the app):** members, the meal planner and expenses on or off, shopping lists (e.g. supermarket and chemist), categories, items, tags and expense categories.
- **Shop order:** sort categories the way your shop is laid out, then switch the list to sort by category.
- **App settings:** light or dark theme, accent colour from your device, item tile size and list style, language (45+).
- **Server (environment variables, `docs/docs/self-hosting/advanced.md`):** `JWT_SECRET_KEY`, `OPEN_REGISTRATION`, `FRONT_URL`, email (`SMTP_*`), sign-in with OIDC, Google or Apple, PostgreSQL (`DB_*`).
- **AI ingredient parsing (optional):** leave `LLM_MODEL` empty for the built-in local parser, set `ollama/<model>` with `LLM_API_URL` for a local model, or a cloud model with its API key (`docs/docs/self-hosting/ingredient_parsing.md`).

## Level 2: Extend (no fork)
- **Recipe import:** paste a link and KitchenOwl reads the recipe (`backend/app/service/recipe_scraping.py`).
- **REST API:** documented at `/api/openapi` on your server (`docs/docs/reference/API.md`). There is also an official Python client (kitchenowl-python).
- **Home Assistant:** the official kitchenowl-ha integration (installed through HACS) brings your shopping lists into Home Assistant, so automations and voice commands can use them.
- **MCP endpoint:** set `KITCHENOWL_MCP_ENABLED=true` to let an AI assistant read recipes and edit lists at `/mcp` (`backend/app/controller/mcp_controller.py`).
- **Export and import:** household data can be exported and imported (`backend/app/controller/exportimport/`).

## Level 3: Code

| Change | Where |
|---|---|
| App screens | `kitchenowl/lib/pages/` (e.g. `recipe_cooking_page.dart`, `recipe_page.dart`), shared pieces in `kitchenowl/lib/widgets/` |
| App state | `kitchenowl/lib/cubits/` |
| Colours and styles | `kitchenowl/lib/styles/` |
| App text | `kitchenowl/lib/l10n/app_en.arb` (other languages via Weblate) |
| API endpoints | `backend/app/controller/<area>/` |
| Data | `backend/app/models/` + a migration in `backend/migrations/` (`uv run flask db migrate`) |
| Server logic | `backend/app/service/` |

## Running locally
- **Just use it:** the all-in-one Docker command in `bespoke.yaml`, then open http://localhost:8080.
- **Develop the server:**
  1. `cd backend && uv sync`.
  2. `uv run flask db upgrade`.
  3. `uv run wsgi.py` (API on http://localhost:5000). Don't start it with `flask run`; sockets won't work.
- **Develop the app:**
  1. Install the Flutter SDK.
  2. `cd kitchenowl && flutter packages get && touch .env`.
  3. `flutter run` and point it at your local server.
- **Check:** `cd backend && uv run pytest`; `cd kitchenowl && flutter analyze && flutter test`.

## Pitfalls
- Back up the `/data` volume first. It holds the database and all photos.
- Released phone apps talk to your server. Don't rename or remove API fields they use.
- Keep household scoping in every query; one household must never see another's data.
- Upstream asks for an issue before new features or API changes, and is still in public alpha.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/kitchenowl/cac641c/r2/bespoke.yaml) · Hosting options: [hosting.md](https://handoff.bespokeai.software/p/kitchenowl/cac641c/r2/hosting.md) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/kitchenowl/cac641c/r2/SKILL.md)
