multiperiod
Per-meal optimization for balanced meals. Use when user wants to control calories per meal, avoid huge snacks, balance breakfast/lunch/dinner, or needs per-meal protein targets. Triggers on "per meal", "meal-by-meal", "balanced meals", "snack limits", "breakfast protein", "lunch calories".
When & Why to Use This Skill
The Multi-Period Meal Optimization skill is a high-precision nutritional planning tool designed to solve the problem of unbalanced daily nutrient distribution. Unlike standard meal planners, it utilizes mathematical optimization to enforce strict per-meal constraints for calories and macronutrients. This ensures that breakfast, lunch, dinner, and snacks adhere to specific targets, preventing common issues like excessive caloric intake during snacks or protein deficiencies in morning meals. It is ideal for users who require data-driven, granular control over their dietary structure through YAML-based profiles.
Use Cases
- Precision Weight Loss: Define exact calorie ranges for every meal (e.g., 400-500 kcal) to ensure a consistent deficit without energy crashes.
- Muscle Building Optimization: Set specific protein minimums for each meal (e.g., 30g+ at breakfast) to maximize muscle protein synthesis throughout the day.
- Metabolic Health Management: Use 'equi-calorie' constraints to keep lunch and dinner portions similar, helping to stabilize blood sugar and energy levels.
- Custom Dietary Rule Enforcement: Apply 'food-meal affinity' to restrict specific ingredients to certain times, such as eggs for breakfast only or almonds strictly as snacks.
- Automated Meal Balancing: Quickly generate a full-day plan using 'Balanced', 'Front-loaded', or 'Back-loaded' presets to match personal lifestyle and hunger patterns.
| name | multiperiod |
|---|---|
| description | Per-meal optimization for balanced meals. Use when user wants to control calories per meal, avoid huge snacks, balance breakfast/lunch/dinner, or needs per-meal protein targets. Triggers on "per meal", "meal-by-meal", "balanced meals", "snack limits", "breakfast protein", "lunch calories". |
Multi-Period Meal Optimization
This skill creates meal plans with per-meal constraints, ensuring balanced distribution of calories and nutrients across breakfast, lunch, dinner, and snacks. This prevents issues like 995-calorie "snacks" that occur with post-hoc meal allocation.
Template-Based vs Multi-Period
Consider template-based first (--template --pattern X):
- Produces more realistic meals (1 protein + 1 legume + vegetables per meal)
- Different foods at each meal by design
- Simpler to use:
uv run llmn optimize --pattern pescatarian --template --json
Use multi-period when:
- You need exact per-meal calorie/protein control (e.g., "exactly 500-550 kcal at breakfast")
- You want to restrict specific foods to specific meals (e.g., "almonds only as snack")
- You need equi-calorie constraints (e.g., "lunch within 100 kcal of dinner")
- Template-based doesn't meet your specific nutrient requirements
When to Use Multi-Period
Use multi-period optimization when:
- User wants exact calorie limits per meal (template gives approximate)
- User needs protein targets at each meal (e.g., 30g+ at breakfast)
- User wants lunch and dinner to be similar in calories (equi-calorie)
- User wants to restrict certain foods to certain meals (eggs→breakfast)
Quick Start
For basic multi-period optimization with auto-derived meal targets:
uv run llmn optimize --multiperiod --json
This uses default splits: Breakfast 25%, Lunch 35%, Dinner 35%, Snack 5%.
Workflow
Step 1: Gather Daily Targets
First, get the user's overall daily targets:
- Total daily calories (min/max)
- Total daily protein minimum
- Any other daily nutrient constraints
Step 2: Define Per-Meal Targets
Ask the user about meal distribution. Offer these presets:
Balanced (default):
- Breakfast: 25% of calories
- Lunch: 35% of calories
- Dinner: 35% of calories
- Snack: 5% of calories (~100-150 kcal)
Front-loaded (big breakfast):
- Breakfast: 35% of calories
- Lunch: 30% of calories
- Dinner: 30% of calories
- Snack: 5% of calories
Back-loaded (big dinner):
- Breakfast: 20% of calories
- Lunch: 30% of calories
- Dinner: 45% of calories
- Snack: 5% of calories
For a 2000 kcal diet with "Balanced" split:
- Breakfast: 450-550 kcal
- Lunch: 650-750 kcal
- Dinner: 650-750 kcal
- Snack: 50-150 kcal
Step 3: Per-Meal Protein (Optional)
Ask if user wants per-meal protein targets:
- Breakfast protein minimum (suggest 25-30g)
- Lunch protein minimum (suggest 40-50g)
- Dinner protein minimum (suggest 40-50g)
- Snack protein (usually 5-10g)
Step 4: Create Multi-Period Profile
Create a YAML profile at /tmp/multiperiod_profile.yaml:
name: multiperiod_custom
description: "Multi-period optimization with per-meal constraints"
# Daily totals (linking constraints)
calories:
min: <daily_cal_min>
max: <daily_cal_max>
nutrients:
protein:
min: <daily_protein_min>
fiber:
min: 30
# Per-meal structure (triggers multi-period mode)
meals:
breakfast:
calories:
min: <breakfast_cal_min>
max: <breakfast_cal_max>
nutrients:
protein:
min: <breakfast_protein_min>
lunch:
calories:
min: <lunch_cal_min>
max: <lunch_cal_max>
nutrients:
protein:
min: <lunch_protein_min>
dinner:
calories:
min: <dinner_cal_min>
max: <dinner_cal_max>
nutrients:
protein:
min: <dinner_protein_min>
snack:
calories:
min: 50
max: 200 # Keep snacks small!
include_tags:
- staple
options:
max_grams_per_food: 400
Step 5: Add Optional Constraints
Equi-calorie constraint (lunch ≈ dinner):
equicalorie:
- meals: [lunch, dinner]
tolerance: 100 # Within 100 kcal of each other
Food-meal affinity (restrict foods to specific meals):
food_meal_rules:
171287: [breakfast] # Eggs only at breakfast
170567: [snack] # Almonds only as snack
175167: [lunch, dinner] # Salmon for lunch/dinner only
Step 6: Run Optimization
uv run llmn optimize --file /tmp/multiperiod_profile.yaml --json
Step 7: Present Results
The JSON output has a meals structure:
{
"data": {
"meals": [
{
"meal_type": "breakfast",
"foods": [...],
"total_calories": 480,
"total_protein": 32
},
{
"meal_type": "snack",
"foods": [...],
"total_calories": 145, // Now properly constrained!
"total_protein": 5
}
],
"daily_totals": {...}
}
}
Present each meal separately with its foods and totals.
Step 8: Handle Infeasibility
Multi-period has more constraints, so infeasibility is more common. Check for:
Per-meal minimums exceed daily maximum: "Your per-meal calorie minimums sum to 2500 kcal but daily max is 2000 kcal" → Reduce per-meal minimums
Per-meal maximums below daily minimum: "Your per-meal calorie maximums sum to 1500 kcal but daily min is 1800 kcal" → Increase per-meal maximums
Protein constraints too tight: "Can't get 50g protein at breakfast with available foods" → Reduce breakfast protein or add high-protein breakfast foods
The optimizer's infeasibility_diagnosis field explains the conflict.
Example Profiles
Weight Loss with Balanced Meals (1800 kcal)
calories:
min: 1700
max: 1900
nutrients:
protein:
min: 150
meals:
breakfast:
calories: {min: 400, max: 500}
nutrients: {protein: {min: 30}}
lunch:
calories: {min: 550, max: 650}
nutrients: {protein: {min: 45}}
dinner:
calories: {min: 550, max: 650}
nutrients: {protein: {min: 45}}
snack:
calories: {min: 50, max: 150}
equicalorie:
- meals: [lunch, dinner]
tolerance: 75
High-Protein Muscle Building (2800 kcal)
calories:
min: 2700
max: 2900
nutrients:
protein:
min: 200
meals:
breakfast:
calories: {min: 600, max: 750}
nutrients: {protein: {min: 50}}
lunch:
calories: {min: 800, max: 950}
nutrients: {protein: {min: 60}}
dinner:
calories: {min: 800, max: 950}
nutrients: {protein: {min: 60}}
snack:
calories: {min: 200, max: 350}
nutrients: {protein: {min: 20}}
Commands Reference
# Quick multi-period with auto-derived targets
uv run llmn optimize --multiperiod --json
# Multi-period with custom profile
uv run llmn optimize --file /tmp/multiperiod_profile.yaml --json
# With verbose output (shows constraint matrices)
uv run llmn optimize --file /tmp/multiperiod_profile.yaml --verbose
# With explicit food IDs (bypass tag filtering)
uv run llmn optimize --multiperiod --foods 175167,171287,172421 --json
Tips
- Start simple: Use
--multiperiodflag first, then customize with a profile - Check the math: Per-meal calorie ranges must sum to cover daily range
- Read the diagnosis: Infeasibility messages are specific and actionable
- Snacks are small: Keep snack max at 150-200 kcal to avoid the "995 cal snack" problem
- Equi-calorie helps: Requiring lunch ≈ dinner creates more balanced days