Meal flyer
Claude or other agent skills to help plan, make, and shop for meals
npx -y skills add scurry/meals-agent --skill meal-flyerAssembled 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 a grocery store flyer for the Meal OS system. Triggered by "/meal-flyer" or "parse a flyer" or "process flyer".
SKILL.md
7.6 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it
/meal-flyer — Store Flyer Parser
Parse a weekly grocery store flyer and extract sale items mapped to canonical ingredient IDs.
Announce at start: "Processing store flyer..."
Step 1: Get Flyer Input
The user provides flyer data in one of two ways:
Option A: PDF File
If the user provides a file path ending in .pdf:
- Read the PDF using the Read tool
- For PDFs over 20 pages, paginate: read pages 1-20, then 21-40, etc.
- Focus on food items — skip pages that are clearly non-food (cleaning supplies, pharmacy, seasonal items)
- After the flyer markdown is successfully written and verified, delete the source PDF so raw flyer files do not accumulate in the repo
Option B: Pasted Text
If the user pastes text from a store website or flyer:
- Use it directly
If no input is provided, ask: "Please provide the store flyer — either paste the text or give me the path to a PDF file."
Step 2: Load Config and Identify the Store
Read data/config.yaml to get the user's store list.
Determine which store this flyer is from:
- Look for store name in the flyer content
- If not obvious, ask: "Which store is this flyer from?" and list the stores from config as options
Step 3: Determine Date Range
Look for a validity date range in the flyer content (e.g., "Valid 3/22 - 3/28", "Weekly Specials March 22-28").
- If found, use the start date for the filename
- If not found, use today's date
- Record the full date range for frontmatter
Step 4: Load Canonical Ingredients
Read data/canonical-ingredients.yaml from the project root. This is the normalization reference for mapping sale items.
If the file 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-flyer."
Step 5: Extract Sale Items
For each sale item in the flyer, extract:
| Field | What to capture | Examples |
|---|---|---|
| Item description | As printed in the flyer | "Boneless Skinless Chicken Thighs Family Pack" |
| Price | The sale price | $2.49, $8.99 |
| Unit | Price unit | /lb, /each, /pint, /dozen, /bag |
| Deal type | Type of promotion | Regular Sale, BOGO, Manager's Special, 2 for $5 |
Price normalization rules:
- "2 for $5" → price: $2.50, unit: /each, deal type: "2 for $5"
- "Buy One Get One Free" / "BOGO" → price: [listed price], deal type: "BOGO (effective 50% off)"
- "Save $2" → note the savings but use the final sale price if shown
- "$X.XX/lb" → price: $X.XX, unit: /lb
- If price per unit can't be determined, record as-is with the deal description
Filtering rules:
- Include: All food and beverage items
- Skip entirely: Non-food items (cleaning supplies, paper goods, pet food, pharmacy, health/beauty). Do not include them in the Sale Items table. Track the count for the confirmation summary only.
Step 6: Map to Canonical Ingredients
For each food item:
-
Match against canonical-ingredients.yaml — find the closest canonical ID:
- "Boneless Skinless Chicken Thighs Family Pack" →
chicken_thigh - "Fresh Atlantic Salmon Fillets" →
salmon - "Grape Tomatoes Pint" →
cherry_tomato - "Greek Yogurt Assorted" →
greek_yogurt
- "Boneless Skinless Chicken Thighs Family Pack" →
-
Unmappable food items — if a food item doesn't match any canonical ingredient:
- Mark with
?in the canonical ID column - These go into an "Items Needing Review" section for the user to decide if they should be added to the canonical list
- Mark with
-
Non-food items — already excluded in Step 5; do not include any row for them in the table
Step 7: Generate Summary
Identify which ingredients from the core set (~24 items in canonical-ingredients.yaml) are on sale this week. List them with price and store name.
If no core ingredients are on sale, note: "No core ingredients on sale this week."
Step 8: Detect Likely Loss Leaders
Identify items priced aggressively low — likely below store cost to drive foot traffic.
Method 1 — Savings Heuristic (always available)
For each sale item with a "Save $X" value: compute savings_pct = save_amount / (sale_price + save_amount). Flag as loss leader if savings_pct >= 0.35.
Method 2 — Price History Comparison (when data exists)
Read data/receipts/price-history.yaml if it exists.
For each sale item that has a canonical ID (not ?):
- Look up the canonical ID in the price history
- Compute the average price from all ledger entries for that item
- If the sale price is >30% below the average, flag as a likely loss leader
If the price history file doesn't exist, skip Method 2 silently.
Output
If any items are flagged, add a new section to the flyer markdown between "Core Ingredients On Sale This Week" and "Items Needing Review":
## Likely Loss Leaders
| Item | Sale Price | Regular/Avg Price | Savings | Method |
|------|-----------|-------------------|---------|--------|
| [Item] | $X.XX/unit | $Y.YY (regular) | NN% | heuristic |
| [Item] | $X.XX/unit | $Y.YY (avg from N receipts) | NN% | price-history |
| [Item] | $X.XX/unit | $Y.YY (regular) / $Z.ZZ (avg) | NN% | both |
Consider building meals around these items — they're priced to get you in the store.
If an item is flagged by both methods, show it once with Method = "both" and show both the regular and average prices.
If no items meet either threshold, omit this section entirely.
Step 9: Check for Collisions
Generate filename: data/flyers/YYYY-MM-DD-<store-slug>.md
- Store slug:
market-basketorhannafords - Example:
data/flyers/2026-03-22-market-basket.md
If the file already exists, ask: "A flyer for [store] on [date] already exists. Overwrite, save as [date]-[store]-2.md, or cancel?"
Step 10: Write the Flyer File
Ensure the directory exists: run mkdir -p data/flyers via Bash before writing.
Write to data/flyers/YYYY-MM-DD-<store-slug>.md using this format:
---
store: [Store Name]
date_range: [YYYY-MM-DD to YYYY-MM-DD]
source: [weekly-flyer-pdf or pasted-text]
---
## Sale Items
| Item | Canonical ID | Price | Unit | Deal Type |
|------|-------------|-------|------|-----------|
| [Item description] | [canonical_id or ?] | [$X.XX] | [/unit] | [deal type] |
## Core Ingredients On Sale This Week
- [canonical_id] — $[price]/[unit] ([Store Name])
- [canonical_id] — $[price]/[unit] ([Store Name])
<!-- Include this section only if Step 8 flagged any loss leaders; omit entirely if none -->
## Likely Loss Leaders
| Item | Sale Price | Regular/Avg Price | Savings | Method |
|------|-----------|-------------------|---------|--------|
| [Item] | $X.XX/unit | $Y.YY (regular) | NN% | heuristic |
Consider building meals around these items — they're priced to get you in the store.
## Items Needing Review
- [Item description] → marked `?` ([reason or suggestion for canonical mapping])
If the source input was a local PDF file and the markdown flyer was written successfully, delete the PDF after saving the markdown output. Do not keep a separate archived PDF copy.
Step 11: Confirm
Output a summary:
Flyer saved: data/flyers/YYYY-MM-DD-<store-slug>.md
Store: [Store Name]
Date range: [date range]
Items extracted: [N total]
Mapped to canonical: [M items]
Marked for review (?): [K items]
Skipped (non-food): [J items]
Core ingredients on sale:
- [list or "none"]
Loss leaders detected: [N items, or "none"]
- [list if any]
Source PDF deleted: [yes/no/not-applicable]
Review items marked with ? and decide if they should be added to data/canonical-ingredients.yaml.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.