본문으로 건너뛰기

{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}

Fitness Nutrition

체육관 운동 판자 및 영양 추적자. 검색 690+ 운동에 의해 근육, 장비, 또는 카테고리를 통해 wger. USDA FoodData Central을 통해 380,000+ 식품의 매크로와 칼로리를 찾습니다. Compute BMI, TDEE, one-rep max, Macro splits 및 body fat - 순수 파이썬, pip installs가 없습니다. 누구든지 쫓는 이익, 절단 무게를 위해 건축해, 또는 다만 더 나은 먹는 것을 시도하세요.

기술 메타데이터

소스선택 사항 - hermes skills install official/health/fitness-nutrition로 설치
경로optional-skills/health/fitness-nutrition
버전1.0.0
라이선스MIT
플랫폼linux, macos, windows
태그health, fitness, nutrition, gym, workout, diet, exercise

참고: 전체 SKILL.md

정보

아래는 Hermes가 이 스킬을 활성화할 때 로드하는 원문 SKILL.md 정의입니다. 명령어, 코드, 식별자를 정확히 보존하기 위해 이 참조 블록은 원문을 유지합니다.

# Fitness & Nutrition

Expert fitness coach and sports nutritionist skill. Two data sources
plus offline calculators — everything a gym-goer needs in one place.

**Data sources (all free, no pip dependencies):**

- **wger** (https://wger.de/api/v2/) — open exercise database, 690+ exercises with muscles, equipment, images. Public endpoints need zero authentication.
- **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.

**Offline calculators (pure stdlib Python):**

- BMI, TDEE (Mifflin-St Jeor), one-rep max (Epley/Brzycki/Lombardi), macro splits, body fat % (US Navy method)

---

## When to Use

Trigger this skill when the user asks about:
- Exercises, workouts, gym routines, muscle groups, workout splits
- Food macros, calories, protein content, meal planning, calorie counting
- Body composition: BMI, body fat, TDEE, caloric surplus/deficit
- One-rep max estimates, training percentages, progressive overload
- Macro ratios for cutting, bulking, or maintenance

---

## Procedure

### Exercise Lookup (wger API)

All wger public endpoints return JSON and require no auth. Always add
`format=json` and `language=2` (English) to exercise queries.

**Step 1 — Identify what the user wants:**

- By muscle → use `/api/v2/exercise/?muscles={id}&language=2&status=2&format=json`
- By category → use `/api/v2/exercise/?category={id}&language=2&status=2&format=json`
- By equipment → use `/api/v2/exercise/?equipment={id}&language=2&status=2&format=json`
- By name → use `/api/v2/exercise/search/?term={query}&language=english&format=json`
- Full details → use `/api/v2/exerciseinfo/{exercise_id}/?format=json`

**Step 2 — Reference IDs (so you don't need extra API calls):**

Exercise categories:

| ID | Category |
|----|-------------|
| 8 | Arms |
| 9 | Legs |
| 10 | Abs |
| 11 | Chest |
| 12 | Back |
| 13 | Shoulders |
| 14 | Calves |
| 15 | Cardio |

Muscles:

| ID | Muscle | ID | Muscle |
|----|---------------------------|----|-------------------------|
| 1 | Biceps brachii | 2 | Anterior deltoid |
| 3 | Serratus anterior | 4 | Pectoralis major |
| 5 | Obliquus externus | 6 | Gastrocnemius |
| 7 | Rectus abdominis | 8 | Gluteus maximus |
| 9 | Trapezius | 10 | Quadriceps femoris |
| 11 | Biceps femoris | 12 | Latissimus dorsi |
| 13 | Brachialis | 14 | Triceps brachii |
| 15 | Soleus | | |

Equipment:

| ID | Equipment |
|----|----------------|
| 1 | Barbell |
| 3 | Dumbbell |
| 4 | Gym mat |
| 5 | Swiss Ball |
| 6 | Pull-up bar |
| 7 | none (bodyweight) |
| 8 | Bench |
| 9 | Incline bench |
| 10 | Kettlebell |

**Step 3 — Fetch and present results:**

```bash
# Search exercises by name
QUERY="$1"
ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$QUERY")
curl -s "https://wger.de/api/v2/exercise/search/?term=${ENCODED}&language=english&format=json" \
| python3 -c "
import json,sys
data=json.load(sys.stdin)
for s in data.get('suggestions',[])[:10]:
d=s.get('data',{})
print(f\" ID {d.get('id','?'):>4} | {d.get('name','N/A'):<35} | Category: {d.get('category','N/A')}\")
"
```

```bash
# Get full details for a specific exercise
EXERCISE_ID="$1"
curl -s "https://wger.de/api/v2/exerciseinfo/$&#123;EXERCISE_ID&#125;/?format=json" \
| python3 -c "
import json,sys,html,re
data=json.load(sys.stdin)
trans=[t for t in data.get('translations',[]) if t.get('language')==2]
t=trans[0] if trans else data.get('translations',[&#123;&#125;])[0]
desc=re.sub('<[^>]+>','',html.unescape(t.get('description','N/A')))
print(f\"Exercise : &#123;t.get('name','N/A')&#125;\")
print(f\"Category : &#123;data.get('category',&#123;&#125;).get('name','N/A')&#125;\")
print(f\"Primary : &#123;', '.join(m.get('name_en','') for m in data.get('muscles',[])) or 'N/A'&#125;\")
print(f\"Secondary : &#123;', '.join(m.get('name_en','') for m in data.get('muscles_secondary',[])) or 'none'&#125;\")
print(f\"Equipment : &#123;', '.join(e.get('name','') for e in data.get('equipment',[])) or 'bodyweight'&#125;\")
print(f\"How to : &#123;desc[:500]&#125;\")
imgs=data.get('images',[])
if imgs: print(f\"Image : &#123;imgs[0].get('image','')&#125;\")
"
```

```bash
# List exercises filtering by muscle, category, or equipment
# Combine filters as needed: ?muscles=4&equipment=1&language=2&status=2
FILTER="$1" # e.g. "muscles=4" or "category=11" or "equipment=3"
curl -s "https://wger.de/api/v2/exercise/?$&#123;FILTER&#125;&language=2&status=2&limit=20&format=json" \
| python3 -c "
import json,sys
data=json.load(sys.stdin)
print(f'Found &#123;data.get(\"count\",0)&#125; exercises.')
for ex in data.get('results',[]):
print(f\" ID &#123;ex['id']:>4&#125; | muscles: &#123;ex.get('muscles',[])&#125; | equipment: &#123;ex.get('equipment',[])&#125;\")
"
```

### Nutrition Lookup (USDA FoodData Central)

Uses `USDA_API_KEY` env var if set, otherwise falls back to `DEMO_KEY`.
DEMO_KEY = 30 requests/hour. Free signup key = 1,000 requests/hour.

```bash
# Search foods by name
FOOD="$1"
API_KEY="$&#123;USDA_API_KEY:-DEMO_KEY&#125;"
ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$FOOD")
curl -s "https://api.nal.usda.gov/fdc/v1/foods/search?api_key=$&#123;API_KEY&#125;&query=$&#123;ENCODED&#125;&pageSize=5&dataType=Foundation,SR%20Legacy" \
| python3 -c "
import json,sys
data=json.load(sys.stdin)
foods=data.get('foods',[])
if not foods: print('No foods found.'); sys.exit()
for f in foods:
n=&#123;x['nutrientName']:x.get('value','?') for x in f.get('foodNutrients',[])&#125;
cal=n.get('Energy','?'); prot=n.get('Protein','?')
fat=n.get('Total lipid (fat)','?'); carb=n.get('Carbohydrate, by difference','?')
print(f\"&#123;f.get('description','N/A')&#125;\")
print(f\" Per 100g: &#123;cal&#125; kcal | &#123;prot&#125;g protein | &#123;fat&#125;g fat | &#123;carb&#125;g carbs\")
print(f\" FDC ID: &#123;f.get('fdcId','N/A')&#125;\")
print()
"
```

```bash
# Detailed nutrient profile by FDC ID
FDC_ID="$1"
API_KEY="$&#123;USDA_API_KEY:-DEMO_KEY&#125;"
curl -s "https://api.nal.usda.gov/fdc/v1/food/$&#123;FDC_ID&#125;?api_key=$&#123;API_KEY&#125;" \
| python3 -c "
import json,sys
d=json.load(sys.stdin)
print(f\"Food: &#123;d.get('description','N/A')&#125;\")
print(f\"{'Nutrient':<40} {'Amount':>8} {'Unit'}\")
print('-'*56)
for x in sorted(d.get('foodNutrients',[]),key=lambda x:x.get('nutrient',&#123;&#125;).get('rank',9999)):
nut=x.get('nutrient',&#123;&#125;); amt=x.get('amount',0)
if amt and float(amt)>0:
print(f\" {nut.get('name',''):<38} {amt:>8} {nut.get('unitName','')}\")
"
```

### Offline Calculators

Use the helper scripts in `scripts/` for batch operations,
or run inline for single calculations:

- `python3 scripts/body_calc.py bmi <weight_kg> <height_cm>`
- `python3 scripts/body_calc.py tdee <weight_kg> <height_cm> <age> <M|F> <activity 1-5>`
- `python3 scripts/body_calc.py 1rm <weight> <reps>`
- `python3 scripts/body_calc.py macros <tdee_kcal> <cut|maintain|bulk>`
- `python3 scripts/body_calc.py bodyfat <M|F> <neck_cm> <waist_cm> [hip_cm] <height_cm>`

See `references/FORMULAS.md` for the science behind each formula.

---

## Pitfalls

- wger exercise endpoint returns **all languages by default** — always add `language=2` for English
- wger includes **unverified user submissions** — add `status=2` to only get approved exercises
- USDA `DEMO_KEY` has **30 req/hour** — add `sleep 2` between batch requests or get a free key
- USDA data is **per 100g** — remind users to scale to their actual portion size
- BMI does not distinguish muscle from fat — high BMI in muscular people is not necessarily unhealthy
- Body fat formulas are **estimates** (±3-5%) — recommend DEXA scans for precision
- 1RM formulas lose accuracy above 10 reps — use sets of 3-5 for best estimates
- wger's `exercise/search` endpoint uses `term` not `query` as the parameter name

---

## Verification

After running exercise search: confirm results include exercise names, muscle groups, and equipment.
After nutrition lookup: confirm per-100g macros are returned with kcal, protein, fat, carbs.
After calculators: sanity-check outputs (e.g. TDEE should be 1500-3500 for most adults).

---

## Quick Reference

| Task | Source | Endpoint |
|------|--------|----------|
| Search exercises by name | wger | `GET /api/v2/exercise/search/?term=&language=english` |
| Exercise details | wger | `GET /api/v2/exerciseinfo/{id}/` |
| Filter by muscle | wger | `GET /api/v2/exercise/?muscles={id}&language=2&status=2` |
| Filter by equipment | wger | `GET /api/v2/exercise/?equipment={id}&language=2&status=2` |
| List categories | wger | `GET /api/v2/exercisecategory/` |
| List muscles | wger | `GET /api/v2/muscle/` |
| Search foods | USDA | `GET /fdc/v1/foods/search?query=&dataType=Foundation,SR Legacy` |
| Food details | USDA | `GET /fdc/v1/food/{fdcId}` |
| BMI / TDEE / 1RM / macros | offline | `python3 scripts/body_calc.py` |