SKILL.md
SKILL.mdBrowse 4 files
2,910 tokens
9,822 bytes
Token encoding: o200k_base
Snapshot 24fd22b
1---2name: fitness-nutrition3description: "Workout planning, macros, and body metrics via wger/USDA."4platforms: [linux, macos, windows]5version: 1.0.06author: Hailey Marshall (haileymarshall), Hermes Agent7authors:8 - haileymarshall9license: MIT10metadata:11 hermes:12 tags: [health, fitness, nutrition, gym, workout, diet, exercise]13 category: health14 prerequisites:15 commands: [curl, python]16required_environment_variables:17 - name: USDA_API_KEY18 prompt: "USDA FoodData Central API key (free)"19 help: "Get one free at https://fdc.nal.usda.gov/api-key-signup/ — or skip to use DEMO_KEY with lower rate limits"20 required_for: "higher rate limits on food/nutrition lookups (DEMO_KEY works without signup)"21 optional: true22---23 24# Fitness & Nutrition25 26Expert fitness coach and sports nutritionist skill. Two data sources27plus offline calculators — everything a gym-goer needs in one place.28 29**Data sources (all free, no pip dependencies):**30 31- **wger** (https://wger.de/api/v2/) — open exercise database, 690+ exercises with muscles, equipment, images. Public endpoints need zero authentication.32- **USDA FoodData Central** (https://api.nal.usda.gov/fdc/v1/) — US government nutrition database, 380,000+ foods. `DEMO_KEY` works instantly; free signup for higher limits.33 34**Offline calculators (pure stdlib Python):**35 36- BMI, TDEE (Mifflin-St Jeor), one-rep max (Epley/Brzycki/Lombardi), macro splits, body fat % (US Navy method)37 38---39 40## When to Use41 42Trigger this skill when the user asks about:43- Exercises, workouts, gym routines, muscle groups, workout splits44- Food macros, calories, protein content, meal planning, calorie counting45- Body composition: BMI, body fat, TDEE, caloric surplus/deficit46- One-rep max estimates, training percentages, progressive overload47- Macro ratios for cutting, bulking, or maintenance48 49---50 51## Procedure52 53### Exercise Lookup (wger API)54 55All wger public endpoints return JSON and require no auth. Always add56`format=json` and `language=2` (English) to exercise queries.57 58**Step 1 — Identify what the user wants:**59 60- By muscle → use `/api/v2/exercise/?muscles={id}&language=2&status=2&format=json`61- By category → use `/api/v2/exercise/?category={id}&language=2&status=2&format=json`62- By equipment → use `/api/v2/exercise/?equipment={id}&language=2&status=2&format=json`63- By name → use `/api/v2/exercise/search/?term={query}&language=english&format=json`64- Full details → use `/api/v2/exerciseinfo/{exercise_id}/?format=json`65 66**Step 2 — Reference IDs (so you don't need extra API calls):**67 68Exercise categories:69 70| ID | Category |71|----|-------------|72| 8 | Arms |73| 9 | Legs |74| 10 | Abs |75| 11 | Chest |76| 12 | Back |77| 13 | Shoulders |78| 14 | Calves |79| 15 | Cardio |80 81Muscles:82 83| ID | Muscle | ID | Muscle |84|----|---------------------------|----|-------------------------|85| 1 | Biceps brachii | 2 | Anterior deltoid |86| 3 | Serratus anterior | 4 | Pectoralis major |87| 5 | Obliquus externus | 6 | Gastrocnemius |88| 7 | Rectus abdominis | 8 | Gluteus maximus |89| 9 | Trapezius | 10 | Quadriceps femoris |90| 11 | Biceps femoris | 12 | Latissimus dorsi |91| 13 | Brachialis | 14 | Triceps brachii |92| 15 | Soleus | | |93 94Equipment:95 96| ID | Equipment |97|----|----------------|98| 1 | Barbell |99| 3 | Dumbbell |100| 4 | Gym mat |101| 5 | Swiss Ball |102| 6 | Pull-up bar |103| 7 | none (bodyweight) |104| 8 | Bench |105| 9 | Incline bench |106| 10 | Kettlebell |107 108**Step 3 — Fetch and present results:**109 110```bash111# Search exercises by name112QUERY="$1"113ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$QUERY")114curl -s "https://wger.de/api/v2/exercise/search/?term=${ENCODED}&language=english&format=json" \115 | python -c "116import json,sys117data=json.load(sys.stdin)118for s in data.get('suggestions',[])[:10]:119 d=s.get('data',{})120 print(f\" ID {d.get('id','?'):>4} | {d.get('name','N/A'):<35} | Category: {d.get('category','N/A')}\")121"122```123 124```bash125# Get full details for a specific exercise126EXERCISE_ID="$1"127curl -s "https://wger.de/api/v2/exerciseinfo/${EXERCISE_ID}/?format=json" \128 | python -c "129import json,sys,html,re130data=json.load(sys.stdin)131trans=[t for t in data.get('translations',[]) if t.get('language')==2]132t=trans[0] if trans else data.get('translations',[{}])[0]133desc=re.sub('<[^>]+>','',html.unescape(t.get('description','N/A')))134print(f\"Exercise : {t.get('name','N/A')}\")135print(f\"Category : {data.get('category',{}).get('name','N/A')}\")136print(f\"Primary : {', '.join(m.get('name_en','') for m in data.get('muscles',[])) or 'N/A'}\")137print(f\"Secondary : {', '.join(m.get('name_en','') for m in data.get('muscles_secondary',[])) or 'none'}\")138print(f\"Equipment : {', '.join(e.get('name','') for e in data.get('equipment',[])) or 'bodyweight'}\")139print(f\"How to : {desc[:500]}\")140imgs=data.get('images',[])141if imgs: print(f\"Image : {imgs[0].get('image','')}\")142"143```144 145```bash146# List exercises filtering by muscle, category, or equipment147# Combine filters as needed: ?muscles=4&equipment=1&language=2&status=2148FILTER="$1" # e.g. "muscles=4" or "category=11" or "equipment=3"149curl -s "https://wger.de/api/v2/exercise/?${FILTER}&language=2&status=2&limit=20&format=json" \150 | python -c "151import json,sys152data=json.load(sys.stdin)153print(f'Found {data.get(\"count\",0)} exercises.')154for ex in data.get('results',[]):155 print(f\" ID {ex['id']:>4} | muscles: {ex.get('muscles',[])} | equipment: {ex.get('equipment',[])}\")156"157```158 159### Nutrition Lookup (USDA FoodData Central)160 161Uses `USDA_API_KEY` env var if set, otherwise falls back to `DEMO_KEY`.162DEMO_KEY = 30 requests/hour. Free signup key = 1,000 requests/hour.163 164```bash165# Search foods by name166FOOD="$1"167API_KEY="${USDA_API_KEY:-DEMO_KEY}"168ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$FOOD")169curl -s "https://api.nal.usda.gov/fdc/v1/foods/search?api_key=${API_KEY}&query=${ENCODED}&pageSize=5&dataType=Foundation,SR%20Legacy" \170 | python -c "171import json,sys172data=json.load(sys.stdin)173foods=data.get('foods',[])174if not foods: print('No foods found.'); sys.exit()175for f in foods:176 n={x['nutrientName']:x.get('value','?') for x in f.get('foodNutrients',[])}177 cal=n.get('Energy','?'); prot=n.get('Protein','?')178 fat=n.get('Total lipid (fat)','?'); carb=n.get('Carbohydrate, by difference','?')179 print(f\"{f.get('description','N/A')}\")180 print(f\" Per 100g: {cal} kcal | {prot}g protein | {fat}g fat | {carb}g carbs\")181 print(f\" FDC ID: {f.get('fdcId','N/A')}\")182 print()183"184```185 186```bash187# Detailed nutrient profile by FDC ID188FDC_ID="$1"189API_KEY="${USDA_API_KEY:-DEMO_KEY}"190curl -s "https://api.nal.usda.gov/fdc/v1/food/${FDC_ID}?api_key=${API_KEY}" \191 | python -c "192import json,sys193d=json.load(sys.stdin)194print(f\"Food: {d.get('description','N/A')}\")195print(f\"{'Nutrient':<40} {'Amount':>8} {'Unit'}\")196print('-'*56)197for x in sorted(d.get('foodNutrients',[]),key=lambda x:x.get('nutrient',{}).get('rank',9999)):198 nut=x.get('nutrient',{}); amt=x.get('amount',0)199 if amt and float(amt)>0:200 print(f\" {nut.get('name',''):<38} {amt:>8} {nut.get('unitName','')}\")201"202```203 204### Offline Calculators205 206Use the helper scripts in `scripts/` for batch operations,207or run inline for single calculations:208 209- `python scripts/body_calc.py bmi <weight_kg> <height_cm>`210- `python scripts/body_calc.py tdee <weight_kg> <height_cm> <age> <M|F> <activity 1-5>`211- `python scripts/body_calc.py 1rm <weight> <reps>`212- `python scripts/body_calc.py macros <tdee_kcal> <cut|maintain|bulk>`213- `python scripts/body_calc.py bodyfat <M|F> <neck_cm> <waist_cm> [hip_cm] <height_cm>`214 215See `references/FORMULAS.md` for the science behind each formula.216 217---218 219## Pitfalls220 221- wger exercise endpoint returns **all languages by default** — always add `language=2` for English222- wger includes **unverified user submissions** — add `status=2` to only get approved exercises223- USDA `DEMO_KEY` has **30 req/hour** — add `sleep 2` between batch requests or get a free key224- USDA data is **per 100g** — remind users to scale to their actual portion size225- BMI does not distinguish muscle from fat — high BMI in muscular people is not necessarily unhealthy226- Body fat formulas are **estimates** (±3-5%) — recommend DEXA scans for precision227- 1RM formulas lose accuracy above 10 reps — use sets of 3-5 for best estimates228- wger's `exercise/search` endpoint uses `term` not `query` as the parameter name229 230---231 232## Verification233 234After running exercise search: confirm results include exercise names, muscle groups, and equipment.235After nutrition lookup: confirm per-100g macros are returned with kcal, protein, fat, carbs.236After calculators: sanity-check outputs (e.g. TDEE should be 1500-3500 for most adults).237 238---239 240## Quick Reference241 242| Task | Source | Endpoint |243|------|--------|----------|244| Search exercises by name | wger | `GET /api/v2/exercise/search/?term=&language=english` |245| Exercise details | wger | `GET /api/v2/exerciseinfo/{id}/` |246| Filter by muscle | wger | `GET /api/v2/exercise/?muscles={id}&language=2&status=2` |247| Filter by equipment | wger | `GET /api/v2/exercise/?equipment={id}&language=2&status=2` |248| List categories | wger | `GET /api/v2/exercisecategory/` |249| List muscles | wger | `GET /api/v2/muscle/` |250| Search foods | USDA | `GET /fdc/v1/foods/search?query=&dataType=Foundation,SR Legacy` |251| Food details | USDA | `GET /fdc/v1/food/{fdcId}` |252| BMI / TDEE / 1RM / macros | offline | `python scripts/body_calc.py` |Discovery context
Discovered by repository scan. No exact path reference found in the snapshot’s root AGENTS.md.