使用说明
Garmin Performance Analysis System
⚠️ Unofficial Tool: This is a community-developed project for personal use, not affiliated with Garmin Ltd.
A comprehensive running performance analysis system that integrates with Garmin Connect to provide detailed split-by-split analysis with environmental integration. Built on a DuckDB-first storage layer and a MCP-first tooling layer.
Features
- Garmin MCP Integration: token-optimized MCP tools for data retrieval and analysis, declared from a single-source
tools/registry (tool reference lists the full set) - DuckDB Backend: Normalized storage (30 tables, 100+ activities) for efficient querying
- Coach Review: one analysis agent (
run-note-analyst) writing the prose on top of the deterministic run report - Japanese Analysis: All analysis stored in DuckDB and viewed via the web app (
packages/garmin-web) - Environmental Integration: Weather, terrain, and body condition analysis
- Performance Tracking: Historical trend analysis, race readiness, ACWR load, and workout comparison
Architecture
Data Flow
Garmin API → Raw JSON → DuckDB → MCP Tools → Analysis → Web App (packages/garmin-web)
Core Components
The project is a uv workspace with two packages:
packages/garmin-mcp-server: Python MCP serversrc/garmin_mcp/ingest/: API → raw data collection (ApiClient,RawDataFetcher,DuckDBSaver)src/garmin_mcp/database/: DuckDB read/write layer (inserters/,readers/,migrations/)src/garmin_mcp/tools/:ToolDefregistry — single source for all MCP tools (reference)src/garmin_mcp/scripts/: ingestion, regeneration, and backfill utilities
packages/garmin-web: FastAPI backend + Vite/React SPA that renders analysis stored in DuckDB- Analysis Agent & Skills (
.claude/): the coach-review agent and user-invocable skills (/analyze-activity,/weekly-review, etc.)
See docs/architecture.md for the design rationale
(the "why"), and CLAUDE.md for the full module map and DuckDB schema reference.
Installation
# Install dependencies (including development tools)
uv sync --extra dev
# Configure data/result directories and credentials, then auto-load env
cp .env.example .env # edit GARMIN_DATA_DIR, GARMIN_RESULT_DIR, GARMIN_EMAIL, GARMIN_PASSWORD
direnv allow
New here? Follow the Getting Started guide for the full cold-start path (authenticate → fetch → build DuckDB → analyze → view).
Garmin Connect Authentication
Fetching data requires your Garmin Connect credentials in the environment
(see .env.example):
| Variable | Required | Purpose |
|---|---|---|
GARMIN_EMAIL |
yes | Garmin Connect account email |
GARMIN_PASSWORD |
yes | Garmin Connect account password |
GARMINTOKENS |
no | OAuth token cache directory (default ~/.garth) |
On first fetch the system logs in and caches OAuth tokens under GARMINTOKENS;
subsequent runs reuse the cache and do not resend your password. If Garmin
returns 429 Too Many Requests, wait before retrying — repeated auth failures
can trigger a temporary block.
Usage
Individual Activity Analysis
Run inside Claude Code — ingests the data, writes the coach review, and stores it in DuckDB:
/analyze-activity <date> # e.g. /analyze-activity 2025-10-15 (defaults to today)
/analyze-activity missing 14 # catch up every run of the last 14 days still missing analyses
Coaching Skills
Conversational coaching runs through dedicated skills so the same data set is read every time:
/daily-checkin [date] # pre-run: today's recovery + load + this week's prescription
/run-debrief [date] # post-run: why a run felt hard / form slipped / a split degraded
/schedule-workout [date] # push the weekly-review prescription to the Garmin calendar ([MCP] workout)
/weekly-review [week] # coach review of the target week, saved to DuckDB
Fetch Raw Data
# Fetch raw data from a start date
uv run python -m garmin_mcp.scripts.bulk_fetch_raw_data --start-date 2025-10-01
# Fetch detailed activity data for specific activities
uv run python -m garmin_mcp.scripts.bulk_fetch_activity_details --activity-ids 12345 67890
Surgical DuckDB Update
# Regenerate selected tables for selected activities
uv run python -m garmin_mcp.scripts.regenerate_duckdb --tables splits --activity-ids 12345 --force
Development
Code Quality
# Format code
uv run black .
# Lint
uv run ruff check .
# Type check
uv run mypy .
# Run tests
uv run pytest
Pre-commit Hooks
# Install hooks
pre-commit install
# Run manually
pre-commit run --all-files
Data Structure
data/raw/: Immutable Garmin API responses (one set of files per activity)data/database/: DuckDB database file (garmin_performance.duckdb)
data/andresult/are git-ignored and configurable via.env(GARMIN_DATA_DIR,GARMIN_RESULT_DIR).
Configurable Data Paths
Privacy Protection: Keep your personal health data separate from the codebase by configuring custom data directories.
Setup
-
Copy the example configuration:
cp .env.example .env -
Edit
.envwith your preferred paths:# Use absolute paths for safety GARMIN_DATA_DIR=/home/user/garmin_data/data GARMIN_RESULT_DIR=/home/user/garmin_data/results -
Run the application: The system automatically uses the configured paths. No code changes needed!
-
(Optional) Setup direnv for automatic environment loading:
# Install direnv if not already installed # Ubuntu/Debian: sudo apt install direnv # Or: curl -sfL https://direnv.net/install.sh | bash # Add direnv hook to your shell (~/.bashrc or ~/.zshrc) eval "$(direnv hook bash)" # For bash # eval "$(direnv hook zsh)" # For zsh # Allow direnv to load .envrc direnv allowWith direnv configured, environment variables are automatically loaded when you
cdinto the project directory.
Default Behavior
If .env is not configured, the system uses default directories:
- Data:
./data - Results:
./result
Benefits
- Privacy: Personal health data stored outside the Git repository
- Flexible Storage: Use external drives or NAS for large datasets
- Environment Separation: Different paths for development/production
MCP Servers
MCP servers are configured per-user in a local, git-ignored .mcp.json:
- garmin-db: DuckDB-based performance data queries and section analysis storage (see tool reference)
- serena: Symbol-aware code navigation and editing operations
- github: Issues, pull requests and CI inspection via the hosted GitHub MCP server
The GitHub server needs "X-MCP-Toolsets": "default,actions" alongside its Authorization
header, otherwise CI job logs are unreadable from a sandbox (the REST log endpoint redirects
to a blob host that sandboxes cannot reach). See .claude/rules/dev/github-mcp-only.md.
Configuration
See CLAUDE.md for detailed configuration and usage guidelines.
Disclaimer
This is an unofficial, community-developed tool and is not affiliated with, endorsed by, or supported by Garmin Ltd. or its affiliates.
- This project uses the third-party Python library
garminconnect(MIT License) to access personal Garmin Connect data - This tool is intended for personal use only to analyze your own fitness data
- Users are responsible for complying with Garmin's Terms of Service
- Use at your own risk - the authors assume no liability for any issues arising from the use of this software
Privacy Note: This tool processes your personal health data locally. Ensure you keep your data directories (configured via .env) secure and never commit personal data to version control.
License
This project is licensed under the MIT License - see the LICENSE file for details.
The project uses the following third-party libraries:
garminconnect- MIT License- Other dependencies are listed in
pyproject.tomlwith their respective licenses