跑步性能分析系统

Garmin Performance Analysis System 是一款面向个人跑者的跑步性能分析系统,非 Garmin 官方产品;它通过接入 Garmin Connect 数据,以 DuckDB 存储数据,并借助 MCP 工具链提供逐段跑步分析、教练式评论、环境数据整合和历史趋势追踪,适用于日常训练回顾、赛前准备与运动表现评估。

  • by yamakii
  • Python
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 yamakii/garmin-performance-analysis

使用说明

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 server
    • src/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/: ToolDef registry — 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/ and result/ 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

  1. Copy the example configuration:

    cp .env.example .env
    
  2. Edit .env with your preferred paths:

    # Use absolute paths for safety
    GARMIN_DATA_DIR=/home/user/garmin_data/data
    GARMIN_RESULT_DIR=/home/user/garmin_data/results
    
  3. Run the application: The system automatically uses the configured paths. No code changes needed!

  4. (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 allow
    

    With direnv configured, environment variables are automatically loaded when you cd into 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.toml with their respective licenses