Analyze Garmin health and performance data specifically for Ultimate Frisbee players. Generate interactive HTML dashboards for post-game review, tournament fatigue tracking, training load optimization, and season-long trend comparison.
bash
pip3 install -r requirements.txt
Pinned versions are in requirements.txt:
garminconnect>=0.2.19 — Garmin Connect API clientfitparse>=3.2.0 — FIT file parsing for activity datagpxpy>=1.3.5 — GPX file parsingWhy email + password? Garmin does not expose a public OAuth API. The
garminconnectlibrary authenticates via Garmin's SSO, the same flow as the Garmin Connect mobile app. The password is used once during login and is never written to disk or logged. The resulting session token is then stored locally at~/.clawdbot/garmin/(permissions 700); all subsequent API requests use that token, not the password.
Set GARMIN_EMAIL and GARMIN_PASSWORD in your shell profile ( ~/.zshrc or ~/.bashrc):
bash
export GARMIN_EMAIL="your-email@example.com"
export GARMIN_PASSWORD="your-password"
bash
python3 scripts/garmin_auth.py login
python3 scripts/garmin_auth.py status # verify
Analyze a single activity in depth: sprints, speed, heart rate zones.
bash
# Most recent activity
python3 scripts/frisbee_activity.py --latest
# Specific date
python3 scripts/frisbee_activity.py --date 2026-03-08
# Specific activity ID
python3 scripts/frisbee_activity.py --activity-id 12345678
# Save to file
python3 scripts/frisbee_activity.py --latest --output ~/Desktop/game.html
Dashboard includes:
Sprint detection: speed > 14.4 km/h sustained ≥ 2 seconds. Sprint Fatigue Index: last 3 sprint peaks ÷ first 3 sprint peaks. < 0.85 = significant fatigue.
Full overview of a multi-day tournament: fatigue curve, game intensity, heart rate recovery, overnight sleep/HRV.
bash
python3 scripts/frisbee_tournament.py \
--start 2026-03-08 \
--end 2026-03-10 \
--name "Spring Tournament 2026" \
--output ~/Desktop/tournament.html
Dashboard includes:
Compare training sessions, games, or the full season.
bash
# Training vs training (last 90 days)
python3 scripts/frisbee_compare.py --mode training --days 90
# Game vs game
python3 scripts/frisbee_compare.py --mode tournament --days 180
# Training intensity vs game intensity
python3 scripts/frisbee_compare.py --mode cross --days 60
# Full season overview
python3 scripts/frisbee_compare.py --mode season --days 180
# Save output
python3 scripts/frisbee_compare.py --mode season --days 180 --output ~/Desktop/season.html
Activity classification uses name keywords:
game, match, tournament, vs, finalspractice, training, train, drill, scrimmageDashboard includes:
bash
# Sleep
python3 scripts/garmin_data.py sleep --days 14
# Body Battery
python3 scripts/garmin_data.py body_battery --days 30
# HRV
python3 scripts/garmin_data.py hrv --days 30
# Heart rate
python3 scripts/garmin_data.py heart_rate --days 7
# Activities
python3 scripts/garmin_data.py activities --days 30
# Stress
python3 scripts/garmin_data.py stress --days 7
# Combined summary
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
bash
python3 scripts/garmin_chart.py sleep --days 30
python3 scripts/garmin_chart.py body_battery --days 30
python3 scripts/garmin_chart.py hrv --days 90
python3 scripts/garmin_chart.py activities --days 30
python3 scripts/garmin_chart.py dashboard --days 30
Player asksScriptWhat to report"How many sprints did I hit?"frisbee_activity.py --latestsprint_count, sprint fatigue index"What was my top speed?"frisbee_activity.py --latesttop_speed_kmh from summary"Was I fatigued at the end?"frisbee_activity.py --latestsprint_fatigue_index < 0.85 = yes"How long was my heart rate elevated?"frisbee_activity.py --latestZone 4-6 time percentage"Did I recover fast enough between points?"frisbee_tournament.pyHRR curves, slope comparison"Was I ready for the tournament?"frisbee_tournament.pyPre-game Body Battery values"Is my training intense enough?"frisbee_compare.py --mode crossAvg HR: training vs game"Am I improving this season?"frisbee_compare.py --mode seasonTop speed + HRV trends"How did I sleep during the tournament?"frisbee_tournament.pyRecovery nights chart
MetricAvailableSprint count & speed✅ FIT file analysisTop speed✅ FIT file speed fieldSprint fatigue index✅ Computed from speed time-seriesHeart rate zones✅ FIT file HR + max HRHeart Rate Recovery (HRR)✅ Intraday HR time-seriesBody Battery✅ Garmin APIHRV (overnight)✅ Garmin APISleep stages & score✅ Garmin APITotal distance✅ FIT file + Garmin APIHigh-intensity distance✅ Computed from speed thresholdGround Contact Time❌ Requires HRM-Run Pod (not wrist)
Ratio of last 3 sprint peak speeds to first 3: ≥ 0.95 stable, 0.85–0.95 mild decline, < 0.85 significant fatigue. Use this to judge if you're losing speed output as the game progresses.
How fast your HR drops after game ends. Steeper curve = better cardiovascular fitness and recovery. Flatter curves in later games of a tournament = cumulative fatigue.
Pre-game value is the key readiness indicator. ≥ 70 = ready to go, 50–69 = manageable, < 50 = compromised performance likely.
python3 scripts/garmin_auth.py loginCredentials
GARMIN_EMAIL and GARMIN_PASSWORD are read from environment variables at runtime onlySession tokens
~/.clawdbot/garmin/ with directory permissions 700 (owner read/write/execute only)garth library (part of garminconnect); format is an opaque token bundle, not plaintext passwordrm -rf ~/.clawdbot/garmin/ — next login will re-authenticateNetwork
connect.garmin.com onlycdn.jsdelivr.net (versions pinned: chart.js@4.4.0, chartjs-plugin-annotation@3.0.1) — requires internet access when viewing dashboardsreferences/api.md — Garmin Connect API detailsreferences/health_analysis.md — Science-backed metric interpretationreferences/mcp_setup.md — Claude Desktop MCP setup