OptionalHealthVersion 1.0.0

Fitness & Nutrition Skill for Hermes Agent: Workouts, Macros, and Body Metrics

Workout planning, macros, and body metrics via wger/USDA.

Written by Neura Market from the official Hermes Agent documentation for Fitness Nutrition. Commands, paths, and version numbers are reproduced from the source unchanged.

Read the official documentation

The Fitness & Nutrition skill turns Hermes Agent into a practical gym companion. It pulls exercise data from the open wger database and food nutrition facts from the USDA, then runs offline calculators for the numbers lifters and dieters actually need: BMI, TDEE, one-rep max, macro splits, and body fat percentage. If you train, track food, or plan meals, this skill puts the reference data and the math in one place, with no pip dependencies and no paid API keys required.

What it does

This skill answers three kinds of questions. First, exercise lookup: what muscles does a movement work, what equipment does it need, and how do you perform it? It queries the wger API, which hosts over 690 exercises with images and muscle/equipment tags. Second, nutrition lookup: how many calories and grams of protein, fat, and carbs are in a given food? It uses the USDA FoodData Central database, covering more than 380,000 foods. Third, offline calculations: given your weight, height, age, and activity, it estimates your daily energy needs, your one-rep max, your body fat percentage, and the macro ratios for cutting, bulking, or maintenance. All calculators run on pure Python standard library, so they work even without network access.

Before you start

This is an optional skill, installed on demand. It is authored by Hailey Marshall (haileymarshall) for Hermes Agent, version 1.0.0, licensed under MIT, and supports Linux, macOS, and Windows. You need Python and curl available on your system, since the skill's commands rely on both. No API keys are strictly required: wger's public endpoints need zero authentication, and the USDA accepts the built-in DEMO_KEY for quick testing. For heavier USDA use, you can sign up for a free key and set it as the USDA_API_KEY environment variable. The skill's helper scripts live in scripts/, and the formulas behind the calculators are documented in references/FORMULAS.md.

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

Exercise categories:

IDCategory
8Arms
9Legs
10Abs
11Chest
12Back
13Shoulders
14Calves
15Cardio

Muscles:

IDMuscleIDMuscle
1Biceps brachii2Anterior deltoid
3Serratus anterior4Pectoralis major
5Obliquus externus6Gastrocnemius
7Rectus abdominis8Gluteus maximus
9Trapezius10Quadriceps femoris
11Biceps femoris12Latissimus dorsi
13Brachialis14Triceps brachii
15Soleus

Equipment:

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

Step 3, Fetch and present results

# Search exercises by name
QUERY="$1"
ENCODED=$(python -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" \
  | python -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')}\")
"
# Get full details for a specific exercise
EXERCISE_ID="$1"
curl -s "https://wger.de/api/v2/exerciseinfo/${EXERCISE_ID}/?format=json" \
  | python -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',[{}])[0]
desc=re.sub('<[^>]+>','',html.unescape(t.get('description','N/A')))
print(f\"Exercise  : {t.get('name','N/A')}\")
print(f\"Category  : {data.get('category',{}).get('name','N/A')}\")
print(f\"Primary   : {', '.join(m.get('name_en','') for m in data.get('muscles',[])) or 'N/A'}\")
print(f\"Secondary : {', '.join(m.get('name_en','') for m in data.get('muscles_secondary',[])) or 'none'}\")
print(f\"Equipment : {', '.join(e.get('name','') for e in data.get('equipment',[])) or 'bodyweight'}\")
print(f\"How to    : {desc[:500]}\")
imgs=data.get('images',[])
if imgs: print(f\"Image     : {imgs[0].get('image','')}\")
"
# 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/?${FILTER}&language=2&status=2&limit=20&format=json" \
  | python -c "
import json,sys
data=json.load(sys.stdin)
print(f'Found {data.get(\"count\",0)} exercises.')
for ex in data.get('results',[]):
    print(f\"  ID {ex['id']:>4} | muscles: {ex.get('muscles',[])} | equipment: {ex.get('equipment',[])}\")
"

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.

# Search foods by name
FOOD="$1"
API_KEY="${USDA_API_KEY:-DEMO_KEY}"
ENCODED=$(python -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=${API_KEY}&query=${ENCODED}&pageSize=5&dataType=Foundation,SR%20Legacy" \
  | python -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={x['nutrientName']:x.get('value','?') for x in f.get('foodNutrients',[])}
    cal=n.get('Energy','?'); prot=n.get('Protein','?')
    fat=n.get('Total lipid (fat)','?'); carb=n.get('Carbohydrate, by difference','?')
    print(f\"{f.get('description','N/A')}\")
    print(f\"  Per 100g: {cal} kcal | {prot}g protein | {fat}g fat | {carb}g carbs\")
    print(f\"  FDC ID: {f.get('fdcId','N/A')}\")
    print()
"
# Detailed nutrient profile by FDC ID
FDC_ID="$1"
API_KEY="${USDA_API_KEY:-DEMO_KEY}"
curl -s "https://api.nal.usda.gov/fdc/v1/food/${FDC_ID}?api_key=${API_KEY}" \
  | python -c "
import json,sys
d=json.load(sys.stdin)
print(f\"Food: {d.get('description','N/A')}\")
print(f\"{'Nutrient':<40} {'Amount':>8} {'Unit'}\")
print('-'*56)
for x in sorted(d.get('foodNutrients',[]),key=lambda x:x.get('nutrient',{}).get('rank',9999)):
    nut=x.get('nutrient',{}); 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:

  • python scripts/body_calc.py bmi
  • python scripts/body_calc.py tdee
  • python scripts/body_calc.py 1rm
  • python scripts/body_calc.py macros
  • python scripts/body_calc.py bodyfat [hip_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

TaskSourceEndpoint
Search exercises by namewgerGET /api/v2/exercise/search/?term=&language=english
Exercise detailswgerGET /api/v2/exerciseinfo/{id}/
Filter by musclewgerGET /api/v2/exercise/?muscles={id}&language=2&status=2
Filter by equipmentwgerGET /api/v2/exercise/?equipment={id}&language=2&status=2
List categorieswgerGET /api/v2/exercisecategory/
List muscleswgerGET /api/v2/muscle/
Search foodsUSDAGET /fdc/v1/foods/search?query=&dataType=Foundation,SR Legacy
Food detailsUSDAGET /fdc/v1/food/{fdcId}
BMI / TDEE / 1RM / macrosofflinepython scripts/body_calc.py

When not to use it

The source does not list explicit alternatives, but the skill's design points to its limits. If you need clinical-grade body composition analysis, the body fat formulas are only estimates, and the source recommends DEXA scans for precision. For highly accurate one-rep max testing, the formulas lose accuracy above 10 reps, so you would want to test with heavier, lower-rep sets instead. If you need a food database beyond the USDA's coverage, or if you need authenticated access to wger's full API, this skill's free endpoints may not suffice.

Limits and gotchas

The source is explicit about several constraints. The wger exercise endpoint returns all languages by default, so you must always add language=2 for English. It also includes unverified user submissions, so add status=2 to only get approved exercises. The USDA DEMO_KEY is limited to 30 requests per hour, so for batch work you should either add sleep 2 between requests or get a free key for 1,000 requests per hour. USDA data is per 100g, so you must remind users to scale to their actual portion size. BMI does not distinguish muscle from fat, so a high BMI in a muscular person is not necessarily unhealthy. Body fat formulas are estimates with a ±3-5% error margin. One-rep max formulas lose accuracy above 10 reps, so use sets of 3-5 for best estimates. Finally, note that wger's exercise/search endpoint uses term not query as the parameter name.

What pairs with this

This skill is part of the Hermes Agent optional skills collection. It pairs naturally with other health-related skills that might handle sleep tracking, stress management, or medical information, though the source does not list specific companions. Within the skill itself, the references/FORMULAS.md file documents the science behind each calculator, so you can explain the "why" behind the numbers. The scripts/ directory holds the batch-capable calculators, which you can chain with the API lookups to build a full workout-and-diet planning workflow.

More Health skills