131 lines
5.2 KiB
Markdown
131 lines
5.2 KiB
Markdown
# Cauldron
|
|
|
|
Cauldron is a self-hosted companion app for [Mealie](https://mealie.io) that
|
|
adds AI-assisted meal planning and a smart, household-shared shopping list.
|
|
Mealie stays the source of truth for your recipes, plans and shopping lists;
|
|
Cauldron layers extra automation on top and stores only per-user preferences
|
|
and cached metadata.
|
|
|
|
## Features
|
|
|
|
- **Ingredient sterilizer** — turns free-form quantities ("about 2 cups",
|
|
"a couple handfuls") into structured `{qty, unit, food}` parses and writes
|
|
them back to Mealie, so downstream tooling has clean data to work with.
|
|
- **Weekly meal-plan generator** — builds a per-week plan from your recipe
|
|
library, honouring pinned picks, dietary targets (calories / macros) and
|
|
allergen exclusions.
|
|
- **Household shopping list** — aggregates ingredients across every recipe in
|
|
a plan and collapses duplicates into single lines (e.g. "2 cups rice +
|
|
1.25 lb rice" → "~2 lb rice") using a USDA-derived food-density table.
|
|
- **Recipe discovery, dedupe and enrichment** — scrape-and-import new recipes,
|
|
cluster and merge duplicates, and enrich recipes with structured metadata
|
|
for smarter planning.
|
|
- **Multi-user, OIDC-secured** — every user connects their own Mealie token
|
|
(encrypted at rest); an optional operator tier exposes the destructive admin
|
|
tools.
|
|
|
|
## Stack
|
|
|
|
- Flask + gunicorn (Python 3.12+)
|
|
- Any OpenID Connect provider for authentication (tested with Authentik)
|
|
- MariaDB for per-user preferences and Fernet-encrypted Mealie tokens
|
|
- An LLM runner reachable over HTTP for the AI features. This project targets
|
|
[clawdforge](https://github.com/Sulkta-Coop/clawdforge), but any service
|
|
exposing the same `POST /run` contract works.
|
|
|
|
## Quick start
|
|
|
|
Cauldron ships as a container and is configured entirely through environment
|
|
variables.
|
|
|
|
```bash
|
|
cp .env.example .env # then fill in the blanks (see Configuration)
|
|
docker compose up -d --build
|
|
curl http://localhost:7790/healthz
|
|
```
|
|
|
|
If you prefer to keep your secrets file outside the repo:
|
|
|
|
```bash
|
|
CAULDRON_ENV_FILE=/path/to/cauldron.env docker compose up -d
|
|
```
|
|
|
|
### Requirements
|
|
|
|
- A running Mealie instance and an API token.
|
|
- An OIDC provider with a client configured for Cauldron's redirect URI.
|
|
- A MariaDB database and user.
|
|
- An LLM HTTP runner for the AI features (sterilize / plan / discover /
|
|
enrich). Without it the app still runs; AI-backed endpoints return an error.
|
|
|
|
## Configuration
|
|
|
|
All settings are read from the environment. See `.env.example` for the full,
|
|
documented list. The most important variables:
|
|
|
|
| Variable | Purpose |
|
|
| --- | --- |
|
|
| `SECRET_KEY` | Flask session signing key |
|
|
| `BIND_HOST` / `BIND_PORT` | Listen address (defaults `0.0.0.0:7790`) |
|
|
| `MEALIE_BASE_URL` | Base URL of your Mealie instance |
|
|
| `MEALIE_API_TOKEN` | System Mealie token for admin batch operations |
|
|
| `CLAWDFORGE_URL` / `CLAWDFORGE_TOKEN` | LLM runner endpoint + auth |
|
|
| `OIDC_ISSUER` / `OIDC_CLIENT_ID` / `OIDC_CLIENT_SECRET` / `OIDC_REDIRECT_URI` | OpenID Connect login |
|
|
| `DB_HOST` / `DB_PORT` / `DB_NAME` / `DB_USER` / `DB_PASSWORD` | MariaDB connection |
|
|
| `CAULDRON_FERNET_KEY` | Key used to encrypt per-user Mealie tokens at rest |
|
|
| `ADMIN_BEARER` | Bearer token for the batch (`/api/...`) endpoints |
|
|
| `CAULDRON_ADMIN_SUBS` | OIDC subjects granted the operator-tier admin tools |
|
|
| `CAULDRON_BASE_URL` / `CAULDRON_BEHIND_TLS` / `CAULDRON_TRUSTED_PROXIES` | Public-deploy hardening (CSRF origin guard, HSTS, secure cookies, trusted-proxy `X-Forwarded-*` handling) |
|
|
|
|
When deployed behind a reverse proxy, set `CAULDRON_BASE_URL`,
|
|
`CAULDRON_BEHIND_TLS=true` and list the proxy peer in
|
|
`CAULDRON_TRUSTED_PROXIES` so forwarded headers are honoured safely.
|
|
|
|
## Endpoints
|
|
|
|
```
|
|
GET /healthz liveness + LLM-runner upstream check
|
|
GET /login /auth/callback OIDC flow
|
|
GET /me account + integration status
|
|
GET /plan /list household plan + shopping list
|
|
GET /api/recipes (admin bearer) proxy Mealie list
|
|
POST /api/sterilize/preview/<slug> (admin bearer) dry-run parser
|
|
POST /api/sterilize/apply/<slug> (admin bearer) write parses back
|
|
```
|
|
|
|
Admin-bearer endpoints expect `Authorization: Bearer $ADMIN_BEARER`.
|
|
|
|
## Project layout
|
|
|
|
```
|
|
cauldron/
|
|
config.py env-driven configuration
|
|
forge.py LLM-runner HTTP client
|
|
mealie.py Mealie API client
|
|
sterilizer.py ingredient parse + apply pipeline
|
|
aggregator.py cross-recipe shopping-list aggregator
|
|
foods.py USDA-seeded food catalogue + density lookup
|
|
recipe_index.py local fuzzy recipe search index
|
|
server.py Flask app + routes
|
|
data/ seed data (USDA SR Legacy foods)
|
|
scripts/
|
|
build_foods_seed.py build the foods seed from a USDA dataset
|
|
clean_foods_seed.py LLM-curated cleanup pass over the seed
|
|
tests/ unit tests
|
|
```
|
|
|
|
## Development
|
|
|
|
```bash
|
|
pip install -r requirements.txt
|
|
python -m pytest # run the test suite
|
|
```
|
|
|
|
## Contributing
|
|
|
|
Issues and pull requests are welcome. Please keep changes focused, add tests
|
|
for new behaviour, and make sure `pytest` passes before opening a PR.
|
|
|
|
## License
|
|
|
|
AGPL-3.0-or-later — see [LICENSE](LICENSE).
|