OptionalHealthVersion 1.0.0

Fitness & Nutrition Skill for Hermes Agent: Workout Planner & Food Tracker

Gym workout planner and nutrition tracker. Search 690+ exercises by muscle, equipment, or category via wger. Look up macros and calories for 380,000+ foods via USDA FoodData Central. Compute BMI, TDEE, one-rep max, macro splits, and body fat — pure Python, no pip installs. Built for anyone chasing gains, cutting weight, or just trying to eat better.

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

Fitness and Nutrition Reference Guide

This document provides technical procedures for exercise lookup, food nutrition data retrieval, and offline body composition calculations using free APIs and Python scripts.

Prerequisites

Before using any of the procedures in this guide, ensure the following are in place:

  • Python 3 with standard library modules (urllib, json, sys, html, re).
  • curl command available in your terminal.
  • The scripts/ directory must contain python3 scripts/body_calc.py.
  • For USDA API calls, either set the USDA_API_KEY environment variable or accept the DEMO_KEY rate limit of 30 requests per hour.
  • Internet access is required for all API calls.

Exercise Lookup (wger API)

The wger API provides exercise data including descriptions, muscle groups, equipment, and images. All public endpoints require no authentication.

Required Parameters

Every wger API call must include these parameters:

  • format=json – response format must be JSON.
  • language=2 – filters results to English only. Without this, results may include all languages.
  • status=2 – returns only approved exercises. Without this, unverified user submissions may appear.

Search Exercises by Name

Use the exercise/search endpoint with the parameter term (not query) to search exercises by name. The endpoint is GET /api/v2/exercise/search/?term=&language=english. Use the full URL https://wger.de/api/v2/exercise/search/?term={query}&language=english&format=json as shown in the command below.

# 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')}\")
"

This returns up to 10 suggestions with exercise ID, name, and category. If no results appear, the query may be misspelled or no matching exercises exist.

Get Full Exercise Details

For complete details on a specific exercise, use GET /api/v2/exerciseinfo/{id}/ with the exercise ID. The full URL is https://wger.de/api/v2/exerciseinfo/{exercise_id}/?format=json.

# Get full details for a specific exercise
EXERCISE_ID="$1"
curl -s "https://wger.de/api/v2/exerciseinfo/${EXERCISE_ID}/?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',[{}])[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','')}\")
"

The description is stripped of HTML tags and limited to 500 characters. The first image URL is displayed if available.

Filter Exercises by Muscle, Category, or Equipment

To list exercises filtered by specific criteria, use the following endpoints with the appropriate IDs:

  • GET /api/v2/exercise/?muscles={id}&language=2&status=2&format=json – the full URL is https://wger.de/api/v2/exercise/?muscles={id}&language=2&status=2&format=json.
  • GET /api/v2/exercise/?category={id}&language=2&status=2&format=json – the full URL is https://wger.de/api/v2/exercise/?category={id}&language=2&status=2&format=json.
  • GET /api/v2/exercise/?equipment={id}&language=2&status=2&format=json – the full URL is https://wger.de/api/v2/exercise/?equipment={id}&language=2&status=2&format=json.
# 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" \
  | python3 -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',[])}\")
"

The response shows the total count and each exercise's ID, muscle IDs, and equipment IDs.

Reference ID Tables

Use GET /api/v2/exercisecategory/ and GET /api/v2/muscle/ to retrieve current ID mappings. Known category IDs include: 8=Arms, 9=Legs, 10=Abs, 11=Chest, 12=Back, 13=Shoulders, 14=Calves, 15=Cardio. Muscle IDs range from 1 to 15. Equipment IDs include: 1=Barbell, 3=Dumbbell, 4=Gym mat, 5=Swiss Ball, 6=Pull-up bar, 7=none/bodyweight, 8=Bench, 9=Incline bench, 10=Kettlebell.

Nutrition Lookup (USDA FoodData Central)

The USDA FoodData Central API provides food nutrient data. The API key is set via the USDA_API_KEY environment variable; if not set, DEMO_KEY is used (30 requests per hour). A free signup key provides 1000 requests per hour.

Search Foods by Name

Use GET /fdc/v1/foods/search?query=&dataType=Foundation,SR Legacy to search for foods.

# Search foods by name
FOOD="$1"
API_KEY="${USDA_API_KEY:-DEMO_KEY}"
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=${API_KEY}&query=${ENCODED}&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={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()
"

Each result shows the food description, per-100g values for Energy (kcal), Protein, Total lipid (fat), Carbohydrate by difference, and the FDC ID. Remind users that values are per 100g and must be scaled to actual portion size. If no foods are found, the query may be too specific or misspelled.

Get Detailed Nutrient Profile

For a full nutrient breakdown, use GET /fdc/v1/food/{fdcId} with the FDC ID.

# 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}" \
  | python3 -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','')}\")
"

This displays all nutrients with amount greater than 0, sorted by nutrient rank.

Rate Limiting

The DEMO_KEY has a limit of 30 requests per hour. If you exceed this, wait or use a free API key. Add sleep 2 between batch requests to avoid hitting the limit.

Offline Calculators

Use python3 scripts/body_calc.py with subcommands for various body composition calculations. Refer to references/FORMULAS.md for formula details.

BMI

python3 scripts/body_calc.py bmi <weight_kg> <height_cm>

Calculates Body Mass Index. Note: BMI does not distinguish muscle from fat. A high BMI in muscular people may not indicate unhealthy.

TDEE

python3 scripts/body_calc.py tdee <weight_kg> <height_cm> <age> <gender_M/F> <activity_level_1-5>

Calculates Total Daily Energy Expenditure using the Mifflin-St Jeor equation. Activity levels range from 1 (sedentary) to 5 (very active). If output is outside the 1500-3500 range for most adults, check input parameters.

One-Rep Max (1RM)

python3 scripts/body_calc.py 1rm <weight> <reps>

Estimates one-rep max using Epley, Brzycki, and Lombardi formulas. Accuracy decreases above 10 reps; use sets of 3-5 for best estimates.

Macros

python3 scripts/body_calc.py macros <tdee> <goal_cut/bulk/maintain>

Calculates macro splits for cutting, bulking, or maintenance based on TDEE.

Body Fat Percentage

python3 scripts/body_calc.py bodyfat <weight_kg> <height_cm> <age> <gender_M/F> <waist_cm> [hip_cm]

Estimates body fat percentage using the US Navy method. The [hip_cm] argument is required for females. These formulas are estimates with ±3-5% accuracy; DEXA scans are recommended for precision. Use the command python3 scripts/body_calc.py bodyfat [hip_cm] with the appropriate arguments.

Failure Modes

  • Exercise search returns no results: The query may be misspelled or no matching exercises exist.
  • USDA search returns no foods: The query may be too specific or misspelled.
  • USDA API rate limit exceeded: DEMO_KEY exhausted; wait or use a free key.
  • Offline calculator outputs unrealistic values: Check input parameters (e.g., TDEE outside 1500-3500).
  • wger API returns non-English results: Missing language=2 parameter.
  • wger API returns unapproved exercises: Missing status=2 parameter.

Key Notes

  • The wger exercise/search endpoint uses term not query as the parameter name.
  • The USDA database contains over 380000 foods.
  • A free USDA API key provides 1000 requests per hour, while DEMO_KEY allows only 30.
  • Body fat estimates have an accuracy of about 5%.

More Health skills