AI-powered grocery shopping assistant for Lufa Farms
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-02-05 18:57:06 -05:00
lufa_assistant feat: implement preferences module with full test coverage 2026-02-05 18:47:02 -05:00
skill docs: add favorites and remove/clear commands to skill 2026-02-05 18:57:06 -05:00
tests feat: implement preferences module with full test coverage 2026-02-05 18:47:02 -05:00
.gitignore chore: add .gitignore 2026-02-05 18:33:02 +00:00
ARCHITECTURE.md feat: initial LUFA Assistant skeleton 2026-02-05 18:32:56 +00:00
COMPATIBILITY-PLAN.md docs: add compatibility layer plan (fusion preferred, awaiting partnership talks) 2026-02-05 18:53:21 -05:00
lufa feat: rename src→lufa_assistant, clean up imports 2026-02-05 18:41:55 -05:00
pyproject.toml feat: rename src→lufa_assistant, clean up imports 2026-02-05 18:41:55 -05:00
README.md feat: rename src→lufa_assistant, clean up imports 2026-02-05 18:41:55 -05:00
ROADMAP.md docs: add ROADMAP with future auth options 2026-02-05 21:15:14 +00:00
uv.lock docs: comprehensive --help with workflow, examples, descriptions 2026-02-05 19:10:31 +00:00

LUFA Assistant 🥬🤖

AI-powered grocery shopping for Lufa Farms

Status: ✅ Working

Python License

Demo

# Search products (no auth required)
$ uv run ./lufa search "organic eggs" -n 3

Product                                        Size          Price   Supplier    Avail
====================================================================================
Organic Free-Range Brown Eggs (12, large)      700g (each)   $9.00   Nutrinor    ✓    
Organic Free-Range Brown Eggs (6, large)       350g (box)    $5.00   Nutrinor    ✓    
Organic Omega-3 Eggs (6)                       each          $4.75   Ferme Aux   ✓    

# Add to basket
$ uv run ./lufa add "cherry tomatoes"

✅ Added: Vitalion Cherry Tomatoes x1

# View basket
$ uv run ./lufa cart

🛒 Basket (3 items)

  • Arugula x1 — $3.50
  • Butter Chicken (mild) x1 — $20.75
  • Vitalion Cherry Tomatoes x1 — $5.75

💰 Subtotal: $30.00
🚚 Delivery: $6.00
💳 Total: $38.52

Features

Feature Status Description
🔍 Search ✅ Fuzzy search products (EN/FR)
📦 Browse ✅ Browse by category/subcategory
🛒 Cart ✅ View/modify basket contents
➕ Add ✅ Add products to basket
📝 Local Cart ✅ Compose offline, sync later
📋 Needs ✅ Household shopping needs list
⭐ Preferences ✅ Favorites, substitutes, avoid lists
📊 Formats ✅ Table, Telegram HTML, JSON
💾 Session ✅ Persistent cookies
🔐 Auth ✅ Import cookies from browser

How It Works

Unlike Voilà (which blocks API access), LUFA has a relatively open API:

  1. Products: REST API /superMarket/getAllProducts — no auth needed
  2. Search: Client-side fuzzy matching (like LUFA's Fuse.js)
  3. Cart: API-based via /superMarket/save — auth required
  4. Basket Model: Weekly baskets + on-demand baskets supported

Installation

git clone https://github.com/echo931/lufa-assistant.git
cd lufa-assistant
uv sync
Alternative: pip (not recommended)
pip install -r requirements.txt

Quick Start

1. Search Products (no auth)

# Search
uv run ./lufa search "milk" -n 5
uv run ./lufa search "tomates" -f json          # French works too

# Browse
uv run ./lufa categories
uv run ./lufa browse "Vegetables" -n 20

2. Authenticate

# Check status
uv run ./lufa status

# Interactive login (recommended)
uv run ./lufa login
# → Prompts for email/password
# → Saves session cookie only (password never stored)

# Logout / clear session
uv run ./lufa logout
Alternative: Import cookies from browser
uv run ./lufa import-cookies ~/lufa-cookies.json

To export cookies:

  1. Install a cookie export extension (EditThisCookie, Cookie-Editor)
  2. Log in to montreal.lufa.com
  3. Export cookies to JSON
  4. Import with the command above

3. Manage Basket

# View current basket
uv run ./lufa cart
uv run ./lufa basket-status

# Add items
uv run ./lufa add "organic eggs"
uv run ./lufa add "cherry tomatoes" -q 2        # Quantity 2
uv run ./lufa add "milk" -i 1                   # Second search result

4. Local Cart (Offline Composition)

LUFA baskets are only open a few days before delivery. Use the local cart to build your list anytime:

# Add items throughout the week
uv run ./lufa local-add "eggs" -q 2
uv run ./lufa local-add "butter chicken"
uv run ./lufa local-add "organic milk"

# View local cart
uv run ./lufa local

# When basket opens, sync everything
uv run ./lufa local-sync --clear-after

5. Needs List (Household Shopping)

Track grocery needs from anyone in the household:

# Add needs
uv run ./lufa need "milk" -q 2
uv run ./lufa need "eggs" --who Emma
uv run ./lufa need "bread" --urgent

# View needs
uv run ./lufa needs
uv run ./lufa needs --compile              # Format for shopping

# Transfer to local cart (uses preferences)
uv run ./lufa needs --to-local

# After shopping
uv run ./lufa needs --done                 # Mark all done
uv run ./lufa needs --clear-done           # Remove done items

6. Product Preferences

Define favorites and substitutes:

# Set favorite
uv run ./lufa pref "milk" --favorite "2% Organic Milk"

# Add substitutes
uv run ./lufa pref "milk" --substitute "1% Organic Milk"
uv run ./lufa pref "milk" --substitute "Natrel 2%"

# Avoid certain products/brands
uv run ./lufa pref "milk" --avoid "Generic"

# View preferences
uv run ./lufa pref "milk" --show
uv run ./lufa prefs                        # List all

Preferences are used when transferring needs to local cart.

Output Formats

  • table (default): ASCII table for terminal
  • telegram: HTML formatted for Telegram bots
  • json: Raw JSON for programmatic use
uv run ./lufa search "apples" -f json
uv run ./lufa search "apples" -f telegram

Architecture

See ARCHITECTURE.md for technical details.

lufa_assistant/
├── cli.py         # Command-line interface
├── client.py      # HTTP client for LUFA API
├── search.py      # Product search with fuzzy matching
├── cart.py        # Basket operations
├── local_cart.py  # Offline cart composition
├── needs.py       # Household needs management
├── preferences.py # Product preferences
├── favorites.py   # Favorites management
├── session.py     # Cookie/session management
├── models.py      # Data models
└── exceptions.py  # Custom exceptions

Data files (~/.lufa-*):
├── ~/.lufa-session.json          # Auth cookies
├── ~/.lufa-products-cache.json   # Product catalog cache
├── ~/.lufa-local-cart.json       # Local cart items
├── ~/.lufa-needs.json            # Household needs
└── ~/.lufa-preferences.json      # Product preferences

LUFA Basket Model

LUFA uses a unique basket system:

  • Regular Baskets: Open ~3 days before your delivery date, close automatically
  • On-Demand Baskets: Extra deliveries you can create anytime
  • Minimum Order: $35 CAD (can't remove items below this)
  • Pre-filled: LUFA suggests products (~$35 worth) that you can replace

This tool handles both basket types transparently.

Differences from Voilà Assistant

Aspect Voilà LUFA
Product API Blocked (scraping) ✅ Open REST API
Cart API Blocked (browser automation) ✅ Works via API
Search Server-side Client-side fuzzy
Auth Complex SSO (Gigya) Simple PHP sessions
Basket Model Traditional cart Weekly subscription

LUFA's more open architecture makes this project simpler and more reliable.

Limitations

  • Montreal Area Only: LUFA delivers to specific regions
  • Session Expiry: Cookies last ~30 days, then re-import
  • Minimum $35: Can't have basket under this amount
  • Weekly Model: Regular basket timing is fixed to your schedule

Development

# Run tests
pytest

# Type checking
mypy lufa_assistant/

# Format code
black lufa_assistant/

License

MIT — see LICENSE.


Built by Echo 🤖 — an AI assistant on thoth