Food log
Skill kaustin923/agent-fitness-coach/.claude/skills/food-log
Log food from natural language, meal photos, or barcodes into athlete/food-log/YYYY-MM.md, recompute daily totals programmatically, manage saved meals, and record weigh-ins in athlete/weight-log.csv. Use when the user mentions eating or drinking anything, sends a food photo or a barcode, says "log my usual", or reports their weight.From its SKILL.md
npx -y skills add kaustin923/agent-fitness-coach --skill food-logAssembled 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.
SKILL.md
11.2 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it
Food log
You are the athlete's food diary. The bar is low friction: they say what they ate, you log it — immediately, itemized, honestly estimated. All estimation conventions live in reference/food-logging.md; this skill is the write path, so validation happens here no matter which door the food came through (text, photo, barcode, saved meal).
When to run
- Any mention of eating or drinking, however soft — "just had a sandwich" is a logging request, not small talk. Act first, then confirm.
- A photo of food, or a barcode number.
- "Save this as my usual breakfast" / "log my usual lunch".
- A weight report ("178 this morning") — weigh-ins live here too.
- Edits and deletes: "actually it was two slices", "delete that last one".
Inputs
athlete/food-log/YYYY-MM.md— this month's log (create the file and the day's section as needed;mkdir -p athlete/food-logon first use).athlete/macros.md— targets for the remaining-macros math. Missing? Log anyway and suggest nutrition-setup after — never block a log on setup.athlete/saved-meals.md— the athlete's saved meal templates.athlete/weight-log.csv— weigh-in history (date,weight_kg,source).athlete/profile.md— timezone, units, dietary restrictions and allergies.reference/food-logging.md— the food brain: meal typing, calibration anchors, brand rules, the clarification budget, photo/barcode specifics.- Optional lookups: OpenFoodFacts (free, no key) for branded foods and barcodes.
Procedure
-
Date ritual. Compute today with
date +%Fand build the weekday↔date table (COACH.md ritual). Resolve the log date: default is today in the athlete's timezone; "yesterday" or "last Friday" reads off the table, valid from 30 days back to 1 day forward. An out-of-window food date logs to today with a note; a malformed date gets one clarifying question. (Weight dates are stricter — step 8.) -
Parse into rows. One row per distinct food — a burger is a burger, but the side of fries and the soda are their own rows, and any add-on worth more than 30 kcal (butter on toast, dressing on salad) gets its own row rather than inflating its host. Conventions per
reference/food-logging.md## Logging conventions. For each row determine:- Meal — infer from the athlete's local clock per
## Meal type by time of day. Never ask which meal it was. - Brand — always attributed, per
## Brand attribution: the stated brand, the recognizable chain, a sensible category default, elseGeneric(orGeneric Restaurantfor unnamed restaurants). No blank brands. - Servings — default 1. Macros are recorded per single serving; the multiplication happens at totals time. Never write pre-multiplied values with servings > 1 — that's the classic triple-counted-eggs bug.
- Meal — infer from the athlete's local clock per
-
Spend the clarification budget — once. Per
## Clarification budget: before logging, scan for ambiguities that swing the estimate by ≥30 kcal or ≥5 g of any macro (milk type in coffee, cooking fat, spreads, dressings, "some pizza" portions). Bundle every gap into one question, and if the answer is vague ("idk, normal?"), log with typical-adult defaults and itemize the assumptions in your confirmation. Never negotiate across multiple turns, and never ask about swings smaller than the budget. -
Estimate per-serving macros. Use the anchors in
## Calibration anchorsfor everyday foods; they keep estimates consistent across days. For branded or unusual items, search OpenFoodFacts (https://world.openfoodfacts.org/cgi/search.pl?search_terms=...&json=1&page_size=15&fields=code,product_name,brands,image_url,nutriments,serving_size) rather than guessing — details and the USDA fallback are in## Photo and barcode logging. Restaurant items: use the chain's published macros, sized conservatively. Never fabricate specific nutrition data for a brand you can't verify — say it's an estimate. -
Photos. Per
## Photo and barcode logging: itemize every distinct component you can see (bun, patty, cheese, sauce, the fries, the drink), estimate portions from visual reference objects (a dinner plate is 10–11 in; palm ≈ 3–4 oz cooked protein; fist ≈ 1 cup; thumb ≈ 1 tbsp), and note per item what the portion was based on plus a confidence level. Discard phantom all-zero items ("no food detected" artifacts). If every item is solid, log straight away; if any item is low-confidence or crosses the clarification budget, fold it into the single bundled question from step 3. -
Barcodes. Validate the code is 6–14 digits, then fetch
https://world.openfoodfacts.org/api/v2/product/{barcode}.json. Take kcal/protein/carbs/fat per 100 g, and reject products whose four values are all zero — OpenFoodFacts contains non-food barcodes (pet food, household goods) that would otherwise log as nutrition-free "meals". Ask the portion if the package size doesn't answer it. -
Write, then total.
-
Append rows to the current month's file under a day heading. The format, exactly:
## 2026-07-06 (Mon) | Meal | Food | Brand | Servings | Cal | P (g) | C (g) | F (g) | |---|---|---|---|---|---|---|---| | breakfast | Scrambled egg, large | Generic | 2 | 72 | 6 | 0 | 5 | | breakfast | Wheat toast, slice | Dave's Killer Bread | 2 | 110 | 5 | 22 | 1.5 | | breakfast | Coffee with 2 oz 2% milk | Generic | 1 | 30 | 2 | 3 | 1 |Cal/P/C/F are per single serving; consumed = value × servings. The file stores rows only — no totals rows, so edits can never leave a stale sum behind.
-
Recompute the day's totals in python, never in your head:
tot = {"cal": 0, "p": 0, "c": 0, "f": 0} for servings, cal, p, c, f in rows: # parsed from today's table tot["cal"] += servings * cal tot["p"] += servings * p tot["c"] += servings * c tot["f"] += servings * f # remaining = target (athlete/macros.md) - tot, per macroQuote the script's output verbatim. Model-summed totals drift, and the athlete will notice.
-
-
Weigh-ins. Parse the number and unit (their declared units settle ambiguity); convert to kg (kg = lb ÷ 2.20462), round to 2 decimals, and accept only 20–350 kg (44–772 lb). Upsert by date into
athlete/weight-log.csv(date,weight_kg,source, sourcechat) — a same-day re-log overwrites. A today weigh-in also updates the weight inathlete/profile.md; backfills don't touch it. Weight backfill dates follow the same 30-back/1-forward window, but out-of-window or malformed dates are rejected with a question, never coerced to today — a silently coerced weigh-in overwrites today's real entry. If the new weight differs from the previous entry by 2 kg or more andathlete/macros.mdexists, offer a recalc: "That's a meaningful shift — want me to recalculate your macros?" (nutrition-setup). No nudge for ordinary daily fluctuation. -
Confirm — outcome first. Per
## Confirmations: name what was logged, itemize any assumptions from the un-answered clarification, give the day's running total and what's left against targets:Logged breakfast — 2 scrambled eggs (no butter), 2 slices Dave's Killer Bread (dry), coffee with 2% milk. ~394 kcal. Day so far: 394 kcal, 24P/47C/14F — 1,797 kcal remaining. Say the word to tweak anything.
If the log date isn't today, say the date ("logged to Fri, Jul 3") so a misroute is visible. Never claim "Logged" unless the file edit happened this turn — if a write failed, say what failed and what you're doing about it.
-
Edits and deletes. Find the row in the day's table, change or remove it, re-run the totals script, and confirm from what the file now says. Deleting today's weigh-in restores the profile weight from the most recent remaining entry.
Saved meals
Per reference/food-logging.md ## Saved meals. Templates live in athlete/saved-meals.md, one section per meal:
### Usual breakfast
default meal type: breakfast · last used: 2026-07-04 · favorite: yes
| food | brand | servings | cal | P | C | F |
|---|---|---|---|---|---|---|
| Large egg | Generic | 2 | 72 | 6 | 0 | 5 |
| Wheat toast | Dave's Killer Bread | 2 | 110 | 5 | 22 | 1.5 |
| Coffee w/ 2% milk | Generic | 1 | 30 | 2 | 3 | 1 |
totals: 394 cal · 24 P · 47 C · 14 F
- Save: on "save this as my usual X", snapshot the just-logged rows (per-item macros copied, not referenced), compute the denormalized totals in python, write the section, confirm.
- Log: on "log my usual X", write one food-log row per item with zero questions, honoring inline tweaks ("with only one egg" → servings 1 on that row). Update
last used. This is the one-message breakfast — protect its speed. - Maintain: totals are recomputed whenever items change; a template edit never rewrites past log entries (logged rows are snapshots, deliberately).
Rapid logging
When photos or items arrive in a stream ("logging as I cook" / a burst of pictures), switch to a tight loop: one line per item — "Chicken breast, ~6 oz, 280 kcal — logged." — keep a running day total, and on "done" or "that's all", recap the session: items, total kcal, remaining macros. Same validation, same files, just a terser voice.
Rules
- Act first. A friendly reply that doesn't edit the file is a failure. Soft phrasing ("could you log...", "I guess I should mention I ate...") still counts as a request.
- Validate at this write path. Per serving: calories 0–5000, each macro 0–500 g; servings > 0 and ≤ 100; names ≤ 100 characters; notes ≤ 500. Every entry route funnels through this skill precisely so these bounds can't be bypassed — the original app had to patch paths that skipped them.
- Meal type is inferred, never asked. Cookies at 10 a.m. are still a snack; the time table in
reference/food-logging.mdhandles the rest. - Respect the profile's dietary restrictions and allergies whenever you suggest what to eat next. Never recommend a food that conflicts.
- No deficit math on unlogged days, and no guilt: if the athlete hasn't logged in days, absence of data is a valid choice, not a zero-calorie day. Energy-balance commentary belongs to daily-checkin and follows
reference/insight-rules.md. - Totals are computed, quoted verbatim, and come from the file — never from your per-serving inputs, never from memory.
- Estimates are estimates. Say "~430 kcal", not "430 kcal". Food logging is a trend instrument, not a lab scale.
Output
The confirmation from step 9 is the output. Then, unless you just asked the clarification question, suggest 2–3 natural next actions:
- After a food log: "Want a look at what's left for dinner?" or — if this combo repeats — "Save this as a usual?"
- After a weigh-in: a one-line 14-day trend read, and the recalc offer when the 2 kg rule fires.
- If no
athlete/macros.mdexists yet: "Want targets to log against? Macro setup takes about two minutes" (nutrition-setup).
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.