Install
openclaw skills install @bolinches/garmin-health-analysis-2Talk to your Garmin data naturally - "what was my fastest speed snowboarding?", "how did I sleep last night?", "what was my heart rate at 3pm?". Access 20+ metrics (sleep stages, Body Battery, HRV, VO2 max, training readiness, body composition, SPO2), download FIT/GPX files for route analysis, query elevation/pace at any point, and generate interactive health dashboards. From casual "show me this week's workouts" to deep "analyze my recovery vs training load".
openclaw skills install @bolinches/garmin-health-analysis-2Query health metrics from Garmin Connect and generate interactive HTML charts.
This skill supports two different setups:
Choose the path that matches your use case. You can also use both simultaneously!
pip3 install garminconnect
You have three options to provide your Garmin Connect credentials:
Add credentials to ~/.clawdbot/clawdbot.json:
{
"skills": {
"entries": {
"garmin-health-analysis": {
"enabled": true,
"env": {
"GARMIN_EMAIL": "your-email@example.com",
"GARMIN_PASSWORD": "your-password"
}
}
}
}
}
Tip: You can also set these through the Clawdbot UI in the Skills settings panel.
Create a config file in the skill directory:
cd ~/.clawdbot/skills/garmin-health-analysis
# or: cd <workspace>/skills/garmin-health-analysis
cp config.example.json config.json
# Edit config.json and add your email and password
config.json:
{
"email": "your-email@example.com",
"password": "your-password"
}
Note: config.json is gitignored to keep your credentials secure.
Pass credentials directly when authenticating:
python3 scripts/garmin_auth.py login \
--email YOUR_EMAIL@example.com \
--password YOUR_PASSWORD
Login to Garmin Connect and save session tokens:
python3 scripts/garmin_auth.py login
This uses credentials from (in priority order):
--email, --password)config.json)GARMIN_EMAIL, GARMIN_PASSWORD)skills.entries.garmin-health-analysis.env)Session tokens are stored in ~/.clawdbot/garmin/ (garth tokenstore) and auto-refresh on subsequent calls.
If you have existing tokens from a previous version (~/.garminconnect/), they are automatically migrated on first use.
Check authentication status:
python3 scripts/garmin_auth.py status
Use scripts/garmin_data.py to get JSON data:
# Sleep (last 7 days default)
python3 scripts/garmin_data.py sleep --days 14
# Body Battery (Garmin's recovery metric)
python3 scripts/garmin_data.py body_battery --days 30
# HRV data
python3 scripts/garmin_data.py hrv --days 30
# Heart rate (resting, max, min)
python3 scripts/garmin_data.py heart_rate --days 7
# Activities/workouts (now includes activity_id)
python3 scripts/garmin_data.py activities --days 30
# Stress levels
python3 scripts/garmin_data.py stress --days 7
# Combined summary with averages
python3 scripts/garmin_data.py summary --days 7
# Custom date range
python3 scripts/garmin_data.py sleep --start 2026-01-01 --end 2026-01-15
# User profile
python3 scripts/garmin_data.py profile
Get lap-by-lap data for a specific activity — average/max HR, speed, distance, power, cadence per lap:
# Get lap splits for an activity (use activities to find activity_id)
python3 scripts/garmin_data.py activity_splits --activity-id 600107330
Returns per-lap: lap_index, distance_meters, duration_seconds, average_speed, max_speed, avg_hr, max_hr, calories, elevation_gain, average_power, normalized_power, average_run_cadence, intensity_type, etc.
Get second-by-second data for a specific activity — heart rate, speed, distance, elevation, power, cadence, and more:
# All metrics, every second (full resolution)
python3 scripts/garmin_data.py activity_detail --activity-id 600107330
# Specific metrics only (faster, smaller output)
python3 scripts/garmin_data.py activity_detail --activity-id 600107330 \
--metrics directHeartRate,directSpeed,sumDistance
# Sample every 30 seconds (good for quick overview of a long activity)
python3 scripts/garmin_data.py activity_detail --activity-id 600107330 \
--sample-interval 30
# Common metrics:
# directHeartRate - Heart rate (bpm)
# directSpeed - Speed (m/s)
# sumDistance - Cumulative distance (m)
# directElevation - Elevation (m)
# directPower - Power (watts, running/cycling)
# directRunCadence - Cadence (spm for running)
# directTimestamp - Timestamp (ms epoch)
# directLatitude - Latitude
# directLongitude - Longitude
# directGradeAdjustedSpeed - Grade-adjusted speed (m/s)
# directVerticalOscillation - Vertical oscillation (cm)
# directGroundContactTime - Ground contact time (ms)
# directStrideLength - Stride length (cm)
# directVerticalRatio - Vertical ratio (%)
# directPerformanceCondition - Performance condition
Output is JSON to stdout. Parse it to answer user questions.
Use scripts/garmin_chart.py for interactive HTML visualizations:
# Sleep analysis (hours + scores)
python3 scripts/garmin_chart.py sleep --days 30
# Body Battery recovery chart (color-coded)
python3 scripts/garmin_chart.py body_battery --days 30
# HRV & resting heart rate trends
python3 scripts/garmin_chart.py hrv --days 90
# Activities summary (by type, calories)
python3 scripts/garmin_chart.py activities --days 30
# Full dashboard (all 4 charts)
python3 scripts/garmin_chart.py dashboard --days 30
# Save to specific file
python3 scripts/garmin_chart.py dashboard --days 90 --output ~/Desktop/garmin-health.html
Charts open automatically in the default browser. They use Chart.js with a modern gradient design, stat cards, and interactive tooltips.
| User asks | Action |
|---|---|
| "How did I sleep last night?" | garmin_data.py summary --days 1, report sleep hours + score |
| "How's my recovery this week?" | garmin_data.py body_battery --days 7, report average + trend |
| "Show me my health for the last month" | garmin_chart.py dashboard --days 30 |
| "Is my HRV improving?" | garmin_data.py hrv --days 30, analyze trend |
| "What workouts did I do this week?" | garmin_data.py activities --days 7, list activities with details |
| "How's my resting heart rate?" | garmin_data.py heart_rate --days 7, report average + trend |
| "Show me my heart rate during my run" | garmin_data.py activity_detail --activity-id ID --metrics directHeartRate,directSpeed --sample-interval 30 |
| "What were my lap splits?" | garmin_data.py activity_splits --activity-id ID, report per-lap HR + pace |
| "How did my pace change over the run?" | garmin_data.py activity_detail --activity-id ID --metrics directSpeed,sumDistance --sample-interval 60 |
Garmin's proprietary recovery metric based on HRV, stress, sleep, and activity:
Overall sleep quality based on duration, stages, and disturbances:
Measured in milliseconds, higher is generally better:
Lower generally indicates better cardiovascular fitness:
Based on HRV analysis throughout the day:
When users ask for insights or want to understand their trends, use references/health_analysis.md for:
python3 scripts/garmin_data.py summary --days Nreferences/health_analysis.md for interpretation frameworkpython3 scripts/garmin_auth.py login ...garminconnect import fails: pip3 install --upgrade garminconnect~/.clawdbot/garmin/ (garth tokenstore directory)~/.garminconnect/ are automatically migrated on first use~/.clawdbot/garmin/ directory| Feature | Garmin | Whoop |
|---|---|---|
| Recovery metric | Body Battery (0-100) | Recovery Score (0-100%) |
| HRV tracking | Yes (nightly average) | Yes (detailed) |
| Sleep stages | Light, Deep, REM, Awake | Light, SWS, REM, Awake |
| Activity tracking | Built-in GPS, many sport modes | Strain score (0-21) |
| Stress | All-day stress levels | Not directly tracked |
| API | Unofficial (garminconnect) | Official OAuth |
| Device types | Watches, fitness trackers | Wearable band only |
references/api.md — Garmin Connect API details (unofficial)references/health_analysis.md — Science-backed health data interpretation