Meal receipt
Claude or other agent skills to help plan, make, and shop for meals
npx -y skills add scurry/meals-agent --skill meal-receiptAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when processing grocery receipt images for the Meal OS system. Triggered by "/meal-receipt" or "process receipts" or "scan receipts".
SKILL.md
6.6 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
/meal-receipt — Receipt OCR & Price Tracker
Process grocery receipt images to build a price history ledger for cost estimates and loss leader detection.
Announce at start: "Processing grocery receipts..."
Step 1: Get Receipt Images
The user provides receipt images in one of two ways:
Option A: Folder Scan
Scan data/receipts/images/ for image files (.jpg, .jpeg, .png). Ignore files in the processed/ subfolder.
Group images into receipts by set ID — everything before the last -N in the filename:
mb-1.jpg,mb-2.jpg,mb-3.jpg→ set "mb" (one receipt, 3 pages)hannafords-1.jpg→ set "hannafords" (one receipt, 1 page)mb2-1.jpg,mb2-2.jpg→ set "mb2" (second receipt, 2 pages)
The -N suffix determines page order within a set.
Option B: Chat
If the user provides image paths directly (e.g., /meal-receipt @mb-1.jpg @mb-2.jpg):
- If multiple images, ask: "Are these all from the same receipt?"
- If yes, treat as one set ordered by the filenames
- If no, ask the user to clarify grouping
If no images are found or provided, say: "No receipt images found. Drop photos in data/receipts/images/ (e.g., mb-1.jpg, mb-2.jpg) or pass them directly: /meal-receipt @receipt.jpg"
Step 2: Load References
Read these files in parallel:
data/canonical-ingredients.yaml— for matching items to canonical IDsdata/receipts/aliases.yaml— for learned abbreviation mappings (if file exists)
If canonical-ingredients.yaml does not exist: Stop and tell the user: "data/canonical-ingredients.yaml is missing. Run /meal-setup first to initialize the project, then re-run /meal-receipt."
Step 3: OCR Receipt Images
For each receipt set, read the images in page order using the Read tool (Claude vision).
Extract from each receipt:
- Store name — from the receipt header
- Date — from the receipt header (fall back to file modification date if unreadable)
- Line items — each with:
- Item description (as printed)
- Quantity (if weight-based, e.g., "2.13 lb")
- Unit price (e.g., "$2.99/lb")
- Total price
Lines to skip:
- Tax lines, subtotals, totals, tender/payment, change
- Savings summary lines, coupon lines, rewards/loyalty lines
- Store header/footer info (address, phone, etc.)
Price normalization:
- Weight-based: "2.13 lb @ $2.99/lb = $6.37" → extract per-unit price $2.99/lb
- Multi-for: "2 @ 2/$5" → $2.50/each
- Per-item: "$3.99" → $3.99/each
If store or date cannot be determined from the receipt, ask the user.
Step 4: Match Items to Canonical Ingredients
For each extracted line item, attempt to match to a canonical ingredient ID using this priority:
- Exact alias match — check
data/receipts/aliases.yamlfor the item description - Fuzzy match against canonical-ingredients.yaml — compare to display names
- Common abbreviation patterns — apply known grocery shorthand:
- CKN/CHKN = chicken, BRST = breast, THGH = thigh
- EVOO = olive oil, EV OLV OIL = olive oil
- GRK = greek, YOG = yogurt
- ORG = organic (modifier, match base item)
- FRSH = fresh (modifier, match base item)
- GRND = ground
- BKLS/BNLS = boneless, SKNLS = skinless
- No match — mark as
?
Step 5: Preview and Confirm
Show the full mapping before saving anything:
Receipt: [Store Name] — [YYYY-MM-DD] ([N] images)
Matched items:
1. [RECEIPT TEXT] $[price] → [canonical_id] ($[unit_price]/[unit])
2. [RECEIPT TEXT] $[price] → [canonical_id] ($[unit_price]/[unit])
...
Unmatched:
N. [RECEIPT TEXT] $[price] → ? ([suggestion or "non-food, skip"])
...
Confirm? (yes / fix [#] [canonical_id] / skip [#])
User corrections:
- yes — save all matched items to the price ledger
- fix 6 pasta — changes item 6's mapping to
pasta; saves the abbreviation → canonical_id pair todata/receipts/aliases.yaml - skip 5 — marks item as non-food or irrelevant, excluded from ledger
- Allow multiple corrections before final yes
- After corrections, re-show the updated mapping for final confirmation
Step 6: Update Price Ledger
Write confirmed items to data/receipts/price-history.yaml.
Note: data/receipts/price-history.yaml is gitignored. See samples/receipts/price-history.yaml for a sanitized example.
Ledger format:
chicken_breast:
- date: 2026-03-22
store: Market Basket
price: 2.99
unit: /lb
receipt: mb
- date: 2026-03-15
store: Hannaford's
price: 4.49
unit: /lb
receipt: hannafords
olive_oil:
- date: 2026-03-22
store: Market Basket
price: 9.99
unit: /25 oz
receipt: mb
Rules:
- Append-only — never overwrite or remove previous entries
- Organize by canonical ID (or human-readable name for non-canonical items)
- Entries sorted by date descending within each ID
- If the file doesn't exist yet, create it
- If the file exists, read it first and append new entries
Step 7: Update Aliases
Write any new alias mappings (from user corrections or high-confidence matches) to data/receipts/aliases.yaml.
Aliases format:
# Learned receipt abbreviation → canonical ingredient ID
# Added automatically when user corrects a fuzzy match
'MB CKNBRST': chicken_breast
'PERDUE CKNBRST': chicken_breast
'MB GRAPE TOMATO': cherry_tomato
'EVOO 25OZ': olive_oil
'CHOBANI GREEK YOG': greek_yogurt
Rules:
- Always single-quote alias keys — receipt text is unpredictable and may contain
#,:,%, or other YAML-special characters - If the file doesn't exist yet, create it with a header comment
- If the file exists, read it first and append new entries
- Never overwrite existing aliases (if a conflict arises, keep the existing one and warn)
- Only save aliases from user corrections (fix command) and high-confidence matches that the user confirmed
Step 8: Move Processed Images
After successful processing, move all images in the receipt set from data/receipts/images/ to data/receipts/images/processed/ to prevent re-processing while preserving originals.
Step 9: Confirm
Output a summary:
Receipt processed: [set ID] ([Store Name], [YYYY-MM-DD])
Items matched: [N]
Items skipped: [M] (non-food)
New aliases learned: [K]
Price ledger updated: data/receipts/price-history.yaml
Notable prices vs. history:
- [canonical_id]: $X.XX/unit (avg $Y.YY, ZZ% below/above average)
- [canonical_id]: $X.XX/unit (first entry — no comparison yet)
...
If multiple receipt sets were processed, show a summary for each.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.