Use when adding a new recipe to the Meal OS system. Triggered by "/meal-add" or "add a recipe".
Naming note: Skills in this family use
meal-*(noun-first) rather than the verb-first convention. This is intentional: themeal-prefix groups all Meal OS slash commands together in discovery and matches how users type them (/meal-add,/meal-flyer, etc.).
Add a recipe to the Meal OS rotation by pasting recipe text from any website.
Announce at start: "Adding recipe to Meal OS..."
The user should paste recipe text along with the /meal-add command. If no recipe text is provided, ask:
"Please paste the recipe text (copy from any recipe website). Include the URL if you have it."
Read these files in parallel:
Read data/config.yaml to get the user's diet, excluded ingredients, and thresholds.
If the file does not exist: Stop and tell the user: "data/config.yaml is missing. Run /meal-setup first to initialize the project, then re-run /meal-add."
Read data/canonical-ingredients.yaml from the project root. This is a read-only reference of core rotation ingredients — do NOT add new entries to this file. It defines the stable set of ingredients the family regularly uses.
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-add."
Extract from the pasted text:
Minimal recipe handling: If the pasted text contains only an ingredient list with no instructions (or instructions that are a single vague sentence like "cook and serve"):
instructions: minimal in the frontmatter## Instructions section with whatever was provided (even if just "See original source")Cleaning rules:
For each ingredient in the recipe:
Match against canonical-ingredients.yaml — look for the closest canonical ID. Use the ingredient name, not the quantity/modifier. Examples:
chicken_thigholive_oilchickpeagarlicspinachNon-canonical ingredients — if an ingredient is not in canonical-ingredients.yaml:
extra_ingredients in the recipe frontmatter. Use a human-readable name (not a snake_case ID). Include the quantity from the recipe.## Ingredients section.Determine the primary protein — set the protein frontmatter field to the main protein's canonical ID (e.g., chicken_thigh, salmon, chickpea). If the protein isn't in the canonical list, use the protein name in plain text. If no clear protein, set to none.
Run these checks and report findings:
For each ingredient in excluded_ingredients from data/config.yaml:
warnings: [contains-[ingredient]] field in frontmatter.Read the diet field from data/config.yaml. If a diet is configured (not none), check whether the recipe contains ingredients that clearly conflict with that diet style. For example, for mediterranean: heavy cream, pork, bacon, butter as primary fat, non-olive cooking oils in large quantities.
warnings: [non-[diet]] field in frontmatterRead ingredient_thresholds.target from data/config.yaml. Count the number of unique canonical ingredients. If the count exceeds the target:
Show the user a preview before writing anything:
Ready to save recipe:
Name: [Recipe Name]
Protein: [protein canonical ID]
Canonical ingredients ([N]): [list of IDs]
Extra ingredients ([N]): [list of non-canonical items needed for shopping]
Tags: [tag list]
Warnings: [any warnings or "none"]
Save? (yes / no / edit ingredient mappings)
Generate a filename slug from the recipe name:
lemon-garlic-chicken-with-green-beansCheck if data/recipes/<slug>.md already exists:
Ensure the directory exists: run mkdir -p data/recipes via Bash before writing.
Write to data/recipes/<slug>.md using this exact format:
---