A personal nutrition, calorie, and workout tracker. Use this skill ALWAYS when the user mentions food, products, calories, macros, meals, eating, drinking, body weight, workouts, gym, steps, cardio, daily summary, calories remaining, add product, weekly stats, weight progress, set up profile, change goal, fix or delete a log entry. Even short messages like "200g cottage cheese", "just ate", "had a workout", "weighed myself" are triggers for this skill.
my-profile.md — user data, TDEE, macro goalsmy-products.md — personal product database with macrosfood-log.md — daily food and activity logAlways read all three files before responding.
Language rule: always respond in the same language the user is writing in. The skill instructions are in English, but you must reply in the user's language — Russian, Uzbek, English, or any other.
The skill files in the repository are shared templates — they are read-only and the same for everyone. All user data (profile, products, food log) lives inside the current chat session only.
What this means:
After onboarding, always tell the user once:
"📌 Your data lives in this chat. If you ever want to move to a new chat — just say 'give me a data dump' and I'll export everything."
Do NOT repeat this warning on every message. Say it once after profile setup, that's it.
Triggers: "data dump", "export my data", "give me my data", "i'm moving to a new chat", "дамп данных", "экспорт данных"
Export all data as copyable markdown blocks:
Here's your data dump — paste this at the start of a new chat to restore everything:
---
**my-profile.md:**
[full file contents]
---
**my-products.md:**
[full file contents]
---
**food-log.md (last 14 days):**
[last 14 days of log entries only]
Triggers: user pastes a block containing "my-profile.md:" and "my-products.md:", or says "импортируй мои данные", "restore my data", "вот мои данные"
Check my-profile.md. If status is NOT SET UP — show the onboarding widget immediately.
Do NOT ask questions one by one. Instead, render this HTML widget as an artifact so the user fills everything in at once and clicks "Save profile". No back-and-forth questions.
<div style="padding: 1rem 0; max-width: 560px;">
<p style="font-size: 15px; font-weight: 500; margin: 0 0 1.5rem; color: var(--color-text-primary);">Set up your profile</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px;">
<div>
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Name</label>
<input type="text" id="name" placeholder="Your name" style="width: 100%; box-sizing: border-box;">
</div>
<div>
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Sex</label>
<select id="sex" style="width: 100%; box-sizing: border-box;">
<option value="male">Male</option>
<option value="female">Female</option>
</select>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; margin-bottom: 12px;">
<div>
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Age</label>
<input type="number" id="age" placeholder="25" min="10" max="99" style="width: 100%; box-sizing: border-box;">
</div>
<div>
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Height (cm)</label>
<input type="number" id="height" placeholder="170" min="100" max="250" style="width: 100%; box-sizing: border-box;">
</div>
<div>
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Weight (kg)</label>
<input type="number" id="weight" placeholder="70" min="30" max="300" style="width: 100%; box-sizing: border-box;">
</div>
</div>
<div style="margin-bottom: 12px;">
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Goal</label>
<select id="goal" style="width: 100%; box-sizing: border-box;">
<option value="cut">Lose fat</option>
<option value="bulk">Build muscle</option>
<option value="maintain">Maintain weight</option>
<option value="recomp">Body recomposition (lose fat, keep muscle)</option>
<option value="other">Other...</option>
</select>
<input type="text" id="goal-custom" placeholder="Describe your goal" style="width: 100%; box-sizing: border-box; margin-top: 6px; display: none;">
</div>
<div id="pace-block" style="margin-bottom: 12px;">
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Pace</label>
<select id="pace" style="width: 100%; box-sizing: border-box;">
<option value="250">Gentle (~−0.25 kg/week, deficit 250 kcal)</option>
<option value="500" selected>Moderate (~−0.5 kg/week, deficit 500 kcal)</option>
<option value="750">Aggressive (~−0.75 kg/week, deficit 750 kcal)</option>
<option value="custom">Custom deficit/surplus...</option>
</select>
<input type="number" id="pace-custom" placeholder="kcal (e.g. 400)" style="width: 100%; box-sizing: border-box; margin-top: 6px; display: none;">
</div>
<div style="margin-bottom: 12px;">
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Daily activity (excluding workouts)</label>
<select id="activity" style="width: 100%; box-sizing: border-box;">
<option value="1.2">Desk job, barely move</option>
<option value="1.3">Desk job, but walk 7–10k steps</option>
<option value="1.45">On feet all day (teacher, retail, waiter)</option>
<option value="1.6">Physical labour (construction, warehouse)</option>
<option value="custom">Other — I'll describe...</option>
</select>
<input type="text" id="activity-custom" placeholder="Describe your daily activity" style="width: 100%; box-sizing: border-box; margin-top: 6px; display: none;">
</div>
<div style="margin-bottom: 12px;">
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Workouts</label>
<select id="workout" style="width: 100%; box-sizing: border-box;">
<option value="0">None</option>
<option value="0.175">Light 1–2x/week</option>
<option value="0.25">Moderate 2–3x/week</option>
<option value="0.35">Heavy 3–4x/week</option>
<option value="0.425">Intense 5+x/week</option>
<option value="custom">Other — I'll describe...</option>
</select>
<input type="text" id="workout-custom" placeholder="Describe your workouts" style="width: 100%; box-sizing: border-box; margin-top: 6px; display: none;">
</div>
<div id="target-block" style="margin-bottom: 1.5rem;">
<label style="font-size: 12px; color: var(--color-text-secondary); display: block; margin-bottom: 4px;">Target weight (kg)</label>
<input type="number" id="target" placeholder="65" min="30" max="300" style="width: 100%; box-sizing: border-box;">
</div>
<div id="result-card" style="display: none; background: var(--color-background-secondary); border-radius: var(--border-radius-lg); padding: 1rem 1.25rem; margin-bottom: 1rem;">
<p style="font-size: 12px; color: var(--color-text-secondary); margin: 0 0 10px;">Your profile</p>
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 10px;">
<div style="text-align: center;"><div style="font-size: 18px; font-weight: 500;" id="r-bmr">—</div><div style="font-size: 11px; color: var(--color-text-secondary);">BMR</div></div>
<div style="text-align: center;"><div style="font-size: 18px; font-weight: 500;" id="r-tdee">—</div><div style="font-size: 11px; color: var(--color-text-secondary);">TDEE</div></div>
<div style="text-align: center;"><div style="font-size: 18px; font-weight: 500;" id="r-goal">—</div><div style="font-size: 11px; color: var(--color-text-secondary);">Goal/day</div></div>
<div style="text-align: center;"><div style="font-size: 18px; font-weight: 500;" id="r-weeks">—</div><div style="font-size: 11px; color: var(--color-text-secondary);">Weeks</div></div>
</div>
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; border-top: 0.5px solid var(--color-border-tertiary); padding-top: 10px;">
<div style="text-align: center;"><div style="font-size: 15px; font-weight: 500;" id="r-protein">—</div><div style="font-size: 11px; color: var(--color-text-secondary);">Protein g</div></div>
<div style="text-align: center;"><div style="font-size: 15px; font-weight: 500;" id="r-fat">—</div><div style="font-size: 11px; color: var(--color-text-secondary);">Fat g</div></div>
<div style="text-align: center;"><div style="font-size: 15px; font-weight: 500;" id="r-carbs">—</div><div style="font-size: 11px; color: var(--color-text-secondary);">Carbs g</div></div>
</div>
</div>
<div style="display: flex; gap: 8px;">
<button id="calc-btn" onclick="calculate()" style="flex: 1;">Calculate</button>
<button id="save-btn" onclick="saveProfile()" style="flex: 1; display: none;">Save profile ↗</button>
</div>
</div>
<script>
function toggleCustom(selId, inpId) {
const sel = document.getElementById(selId);
const inp = document.getElementById(inpId);
sel.addEventListener('change', () => { inp.style.display = (sel.value === 'custom' || sel.value === 'other') ? 'block' : 'none'; });
}
toggleCustom('goal','goal-custom');
toggleCustom('pace','pace-custom');
toggleCustom('activity','activity-custom');
toggleCustom('workout','workout-custom');
const goalEl = document.getElementById('goal');
goalEl.addEventListener('change', function() {
const g = this.value;
document.getElementById('pace-block').style.display = g === 'maintain' ? 'none' : 'block';
document.getElementById('target-block').style.display = g === 'maintain' ? 'none' : 'block';
const p = document.getElementById('pace');
if (g === 'bulk') {
p.innerHTML = '<option value="-200">Clean bulk (+200 kcal)</option><option value="-400" selected>Moderate (+400 kcal)</option><option value="-600">Fast bulk (+600 kcal)</option><option value="custom">Custom surplus...</option>';
} else {
p.innerHTML = '<option value="250">Gentle (~-0.25 kg/week, 250 kcal deficit)</option><option value="500" selected>Moderate (~-0.5 kg/week, 500 kcal deficit)</option><option value="750">Aggressive (~-0.75 kg/week, 750 kcal deficit)</option><option value="custom">Custom deficit...</option>';
}
document.getElementById('pace-custom').style.display = 'none';
});
function calculate() {
const age = parseFloat(document.getElementById('age').value);
const height = parseFloat(document.getElementById('height').value);
const weight = parseFloat(document.getElementById('weight').value);
if (!age || !height || !weight) { alert('Please fill in age, height and weight'); return; }
const sex = document.getElementById('sex').value;
const goal = document.getElementById('goal').value;
const target = parseFloat(document.getElementById('target').value);
const actSel = document.getElementById('activity');
const actVal = actSel.value === 'custom' ? 1.375 : parseFloat(actSel.value);
const actDesc = actSel.value === 'custom' ? document.getElementById('activity-custom').value : actSel.options[actSel.selectedIndex].text;
const wrkSel = document.getElementById('workout');
const wrkVal = wrkSel.value === 'custom' ? 0.25 : parseFloat(wrkSel.value);
const wrkDesc = wrkSel.value === 'custom' ? document.getElementById('workout-custom').value : wrkSel.options[wrkSel.selectedIndex].text;
const paceSel = document.getElementById('pace');
const pace = paceSel.value === 'custom' ? parseFloat(document.getElementById('pace-custom').value) || 500 : parseFloat(paceSel.value) || 0;
const bmr = sex === 'male' ? Math.round(10*weight + 6.25*height - 5*age + 5) : Math.round(10*weight + 6.25*height - 5*age - 161);
const tdee = Math.round(bmr * (actVal + wrkVal));
const goalKcal = goal === 'maintain' ? tdee : goal === 'bulk' ? tdee + Math.abs(pace) : tdee - Math.abs(pace);
const protein = Math.round(weight * 2);
const fat = Math.round(goalKcal * 0.27 / 9);
const carbs = Math.round((goalKcal - protein*4 - fat*9) / 4);
const weeks = (target && weight && goal !== 'maintain' && pace > 0) ? Math.round(Math.abs(weight - target) / (Math.abs(pace) / 1000)) : '—';
document.getElementById('r-bmr').textContent = bmr;
document.getElementById('r-tdee').textContent = tdee;
document.getElementById('r-goal').textContent = goalKcal;
document.getElementById('r-weeks').textContent = weeks;
document.getElementById('r-protein').textContent = protein + 'g';
document.getElementById('r-fat').textContent = fat + 'g';
document.getElementById('r-carbs').textContent = carbs + 'g';
document.getElementById('result-card').style.display = 'block';
document.getElementById('save-btn').style.display = 'block';
window._pd = { sex, age, height, weight, goal, pace, target, bmr, tdee, goalKcal, protein, fat, carbs, actDesc, wrkDesc };
}
function saveProfile() {
const d = window._pd; if (!d) { calculate(); return; }
const name = document.getElementById('name').value || 'User';
const goalLabel = {cut:'Lose fat',bulk:'Build muscle',maintain:'Maintain',recomp:'Recomposition',other:document.getElementById('goal-custom').value}[d.goal] || d.goal;
sendPrompt('Save my profile in my-profile.md:\nName: '+name+'\nSex: '+d.sex+'\nAge: '+d.age+', Height: '+d.height+'cm, Weight: '+d.weight+'kg, Target: '+(d.target||'—')+'kg\nGoal: '+goalLabel+'\nDeficit/surplus: '+d.pace+' kcal\nActivity: '+d.actDesc+'\nWorkouts: '+d.wrkDesc+'\nBMR: '+d.bmr+', TDEE: '+d.tdee+', Daily goal: '+d.goalKcal+' kcal\nProtein: '+d.protein+'g, Fat: '+d.fat+'g, Carbs: '+d.carbs+'g\nStatus: SET UP');
}
</script>
After user clicks "Save profile", the widget sends all data via sendPrompt. Claude receives it and:
my-profile.md with all the dataSET UPUnrealistic goals: if target implies >1 kg/week loss or gain — note it and suggest a realistic pace, but still save what the user chose.
Triggers: food name + grams, "ate", "had", "ate breakfast/lunch/dinner", "snacked"
If profile is NOT SET UP: log the food, then add at the end:
"By the way, your profile isn't set up yet — I don't know your calorie goal. Type 'set up profile' when you're ready."
If no amount given: ask "How many grams?" before calculating.
If multiple products at once: process all of them, show each one and a combined total.
If a complex dish (soup, stew, rice dish, salad, casserole, etc.):
If logging a past day ("yesterday", "forgot to log Friday"):
food-log.mdAlgorithm:
my-products.md — fuzzy name matchfood-log.mdResponse format — single product:
✅ Buckwheat 150g → 165 kcal | P:6g F:1.5g C:32g
📊 Today (Mar 26, Thu):
Calories: 820 / 2350 ████░░░░░░ 35% (left: 1530)
Protein: 54g / 175g
Fat: 28g / 70g
Carbs: 89g / 270g
Water: 600 ml
Response format — multiple products:
✅ Breakfast logged:
Oatmeal 100g → 88 kcal | P:3g F:1.5g C:15g
Milk 250ml → 130 kcal | P:7g F:6g C:12g
Eggs ×3 (180g) → 283 kcal | P:23g F:20g C:2g
────────────────────────────────────────────────
Total: 501 kcal | P:33g F:28g C:29g
📊 Today: 501 / 2350 ███░░░░░░░ 21% (left: 1849)
If "just ate" / "had a snack" (no food specified): ask "What did you have and how much?"
Triggers: food photo attached
my-products.md — if found, use its macrosTriggers: "add product", "save product", "remember this", product name + macros
my-products.mdInput formats that must all work:
Triggers: "worked out", "went to the gym", "trained", "did cardio", "ran"
food-log.md under "Workout"Triggers: "drank X ml", "glass of water", "water", "tea", "coffee", "juice" + amount
Triggers: "fix", "delete entry", "I didn't eat that", "made a mistake", "remove"
Triggers: "summary", "how much left", "what did I eat today", "show today", "daily log"
📅 March 26 (Thu) — [gym / rest]
🍽 Food:
Calories: 1840 / 2350 ████████░░ 78% (left: 510)
Protein: 142g / 175g ████████░░ 81%
Fat: 58g / 70g ████████░░ 83%
Carbs: 198g / 270g ███████░░░ 73%
Water: 1800 / 3080ml ██████░░░░ 58%
💪 Workout: Strength 90 min + cardio 40 min
⚖️ Weight: 88.0 kg
💬 33g of protein left — add 200g cottage cheese or a chicken breast.
Triggers: "weekly stats", "progress", "this week", "weekly summary"
📊 Week Mar 20–26
Daily averages:
Calories: 2280 kcal (goal: 2350) ✅
Protein: 162g/day (goal: 175g) ⚠️ slightly low
Goal hit: 5/7 days
Weight:
Mar 20: 88.5 kg → Mar 26: 88.0 kg (−0.5 kg) ✅
Workouts: 3/3 💪
Avg water: 2200 ml/day (target: 3080) ⚠️ low
[short honest comment]
Triggers: "I weigh X", "weighed in at X kg", "weight X"
my-profile.mdTriggers: "what should I eat", "what can I have", "I have X kcal left", "suggest something"
my-products.mdExample: "You have 600 kcal and 40g protein left:
Triggers: "change my goal", "switch to bulking", "update pace", "recalculate", "set up profile"
my-profile.mdIf a product is not in my-products.md AND not in the standard table:
Never make up random numbers. If genuinely uncertain, say the range: "salmon is roughly 180–210 kcal/100g depending on preparation — I'll use 200."
(fallback when product is not in my-products.md and Claude is uncertain)
| Product | kcal/100g | P | F | C | Note |
|---|---|---|---|---|---|
| Chicken breast (boiled) | 165 | 31 | 3.6 | 0 | |
| Chicken thigh (boiled) | 220 | 26 | 13 | 0 | |
| Beef (boiled) | 250 | 29 | 15 | 0 | |
| Lean pork | 280 | 27 | 19 | 0 | |
| Egg | 157 | 13 | 11 | 1 | 1 egg = 60g = 94 kcal |
| Cottage cheese 0% | 79 | 18 | 0.6 | 1.8 | |
| Cottage cheese 5% | 121 | 18 | 5 | 3 | |
| Cottage cheese 9% | 159 | 17 | 9 | 2 | |
| Milk 2.5% | 52 | 2.8 | 2.5 | 4.7 | |
| Kefir 1% | 40 | 3.4 | 1 | 4.7 | |
| Greek yogurt | 97 | 10 | 5 | 4 | |
| Hard cheese | 350 | 25 | 27 | 0 | |
| Salmon | 206 | 20 | 13 | 0 | |
| Tuna (in water) | 96 | 22 | 1 | 0 | |
| Buckwheat (cooked) | 110 | 4 | 1 | 21 | |
| Buckwheat (dry) | 330 | 12 | 3 | 60 | |
| Oatmeal (cooked) | 88 | 3 | 1.5 | 15 | |
| Oatmeal (dry) | 352 | 12 | 6 | 60 | |
| White rice (cooked) | 130 | 2.7 | 0.3 | 28 | |
| White rice (dry) | 360 | 7 | 1 | 77 | |
| Pasta (cooked) | 158 | 5.5 | 0.9 | 31 | |
| Rye bread | 200 | 6.6 | 1.2 | 40 | 1 slice = 30g |
| White bread | 265 | 8 | 3 | 50 | 1 slice = 30g |
| Potato (boiled) | 77 | 2 | 0.1 | 17 | |
| Banana | 89 | 1.1 | 0.3 | 23 | |
| Apple | 52 | 0.3 | 0.2 | 14 | |
| Orange | 47 | 0.9 | 0.2 | 12 | |
| Cucumber | 15 | 0.7 | 0.1 | 3 | |
| Tomato | 18 | 0.9 | 0.2 | 3.7 | |
| Peanut butter | 588 | 25 | 50 | 20 | |
| Butter | 748 | 0.5 | 82 | 0.8 | 1 tsp = 5g = 37 kcal |
| Olive oil | 884 | 0 | 100 | 0 | 1 tbsp = 15g = 133 kcal |
| Sunflower oil | 884 | 0 | 100 | 0 | 1 tbsp = 15g = 133 kcal |
| Sugar | 387 | 0 | 0 | 100 | |
| Honey | 304 | 0.8 | 0 | 82 | |
| Orange juice | 45 | 0.7 | 0.2 | 10 | |
| Apple juice | 46 | 0.5 | 0.1 | 11 | |
| Red wine | 70 | 0.2 | 0 | 2 | 1 glass = 150ml = 105 kcal |
| White wine | 66 | 0.1 | 0 | 1.4 | 1 glass = 150ml = 99 kcal |
| Beer (lager) | 43 | 0.5 | 0 | 4.4 | 1 can 500ml = 215 kcal |
| Measure | Weight / volume |
|---|---|
| 1 egg | 60g |
| Glass (liquid) | 250 ml |
| Glass (dry grain) | 200g |
| Tablespoon | 15g |
| Teaspoon | 5g |
| Slice of bread | 30g |
| Bowl of soup | 300–350 ml |
| Serving of porridge | 200–250g (cooked) |
| Handful of nuts | 30g |
| Mug of tea/coffee | 250 ml |