Garmin Connect CLI built with Rust.
brew install vicentereig/tap/garminOr tap first, then install:
brew tap vicentereig/tap
brew install garmincargo install garmin-cliPre-built binaries for macOS and Linux (amd64/arm64) are available on the releases page.
# Login (opens browser for SSO)
garmin auth login
# Check status
garmin auth status
# Logout
garmin auth logout# Daily summary
garmin health summary
garmin health summary --date 2025-12-13
# Sleep
garmin health sleep
garmin health sleep --date 2025-12-13
garmin health sleep --days 7
# Stress
garmin health stress
garmin health stress --date 2025-12-13
garmin health stress --days 7
# Heart rate
garmin health heart-rate
garmin health heart-rate --date 2025-12-13
# Body battery
garmin health body-battery
garmin health body-battery --date 2025-12-13
# Steps (with date range)
garmin health steps
garmin health steps --days 28
# Calories
garmin health calories
garmin health calories --days 7
# Weight
garmin health weight
garmin health weight --from 2025-01-01 --to 2025-12-31
garmin health weight-add 80.2 --unit kg
# VO2 Max
garmin health vo2max
garmin health vo2max --date 2025-12-10
# Training readiness (score, level, acute load, HRV)
garmin health training-readiness
garmin health training-readiness --date 2025-12-13
garmin health training-readiness --days 14
# Training status (load, ratio, focus)
garmin health training-status
garmin health training-status --date 2025-12-13
garmin health training-status --days 14
# HRV
garmin health hrv
garmin health hrv --date 2025-12-13
# Fitness age
garmin health fitness-age
# Performance metrics
garmin health lactate-threshold --days 90
garmin health race-predictions
garmin health endurance-score --days 30
garmin health hill-score --days 30
garmin health personal-records
garmin health performance-summary
# Additional health metrics
garmin health spo2
garmin health respiration
garmin health intensity-minutes
garmin health blood-pressure --from 2025-01-01 --to 2025-12-31
garmin health hydration
# Health insights (sleep/stress correlations)
garmin health insights
garmin health insights --days 28# List activities
garmin activities list
garmin activities list --limit 20
# Get activity details
garmin activities get 21247810009
# Download activity (FIT, GPX, TCX)
garmin activities download 21247810009 --type fit --output activity.fit
garmin activities download 21247810009 --type gpx --output activity.gpx
# Upload activity
garmin activities upload activity.fit# List devices
garmin devices list
# Get device details
garmin devices get 3442975663
# Show device history from synced data
garmin devices history# Show profile
garmin profile show
# Show settings
garmin profile settingsSync your Garmin data to local Parquet files for offline analysis. Sync runs use line-oriented terminal progress and a final summary.
# Sync recent data (latest mode)
garmin sync run
# Sync specific date range
garmin sync run --from 2025-01-01 --to 2025-12-31
# Backfill historical data
garmin sync run --backfill
# Sync only activities
garmin sync run --activities
# Sync only health data
garmin sync run --health
# Sync only performance metrics
garmin sync run --performance
# Dry run (preview what will be synced)
garmin sync run --dry-run
# Check sync status
garmin sync status
# Reset failed sync tasks
garmin sync reset
# Clear pending sync tasks
garmin sync clearData is stored in time-partitioned Parquet files for efficient querying:
~/.local/share/garmin/ # Linux
~/Library/Application Support/garmin/ # macOS
├── sync.db # SQLite: sync state + task queue
├── profiles.parquet # User profiles
├── activities/
│ ├── 2024-W48.parquet # Weekly partitions
│ └── ...
├── track_points/
│ ├── 2024-12-01.parquet # Daily partitions (GPS data)
│ └── ...
├── daily_health/
│ ├── 2024-12.parquet # Monthly partitions
│ └── ...
└── performance_metrics/
├── 2024-12.parquet # Monthly partitions
└── ...
The sync uses a producer/consumer architecture with 4 concurrent workers:
- 4 Producers: Fetch data from Garmin API (rate-limited)
- Bounded channel: Backpressure with 100-item buffer
- 4 Consumers: Write to Parquet with partition-level locks
- Crash recovery: SQLite task queue persists progress
Different partitions can be written in parallel; writes to the same partition are serialized to prevent data loss.
Query your synced Parquet files directly using DuckDB:
# Install DuckDB CLI
brew install duckdb # macOS
# or download from https://duckdb.org
# Set your data path
# macOS: ~/Library/Application Support/garmin
# Linux: ~/.local/share/garmin
export GARMIN_DATA=~/Library/Application\ Support/garmin
# Query activities from all partitions
duckdb -c "SELECT * FROM '$GARMIN_DATA/activities/*.parquet' ORDER BY start_time_local DESC LIMIT 10"
# Query health data for a specific month
duckdb -c "SELECT * FROM '$GARMIN_DATA/daily_health/2025-01.parquet' ORDER BY date"
# Aggregate across all health data
duckdb -c "SELECT date, steps, resting_hr, sleep_seconds/3600.0 as sleep_hours FROM '$GARMIN_DATA/daily_health/*.parquet' WHERE date >= '2025-01-01' ORDER BY date"The sync creates several Parquet datasets:
activities/*.parquet- Activity summaries (runs, rides, etc.) - weekly partitionstrack_points/*.parquet- GPS track points - daily partitionsdaily_health/*.parquet- Daily health metrics (sleep, stress, HRV, etc.) - monthly partitionsperformance_metrics/*.parquet- Training data (readiness, VO2 max, race predictions) - monthly partitionsprofiles.parquet- User profile data
Example query for training load trends:
-- macOS path shown; use ~/.local/share/garmin on Linux
SELECT date, training_status, training_readiness, vo2max
FROM '~/Library/Application Support/garmin/performance_metrics/*.parquet'
WHERE date >= '2025-12-01'
ORDER BY date DESC;# Use a specific profile
garmin --profile work auth login
garmin --profile work health summary
# Or via environment variable
GARMIN_PROFILE=work garmin health summary$ garmin health performance-summary
Performance Summary for 2025-12-19
==================================================
VO2 Max: 53.1 ml/kg/min
Fitness Age: 37 years (actual: 43)
Training Status: strained 1
Training Load: 306 acute / 249 chronic (ratio: 1.20 OPTIMAL)
Load Focus: anaerobic shortage
Training Readiness: 32 (LOW)
Lactate Threshold
------------------------------
Heart Rate: 162 bpm
Pace: 4:24/km
Last Updated: 2025-11-01
Race Predictions
------------------------------
5K 21:13 (4:14/km)
10K 45:21 (4:32/km)
Half Marathon 1:42:47 (4:52/km)
Marathon 3:46:27 (5:22/km)
$ garmin health training-status --days 7
Date Status Acute Chronic Ratio
------------------------------------------------------
2025-12-19 strained 306 249 1.20
2025-12-18 strained 212 232 0.90
2025-12-17 strained 146 223 0.60
2025-12-16 strained 171 231 0.70
2025-12-15 strained 221 235 0.90
2025-12-14 unproductive 268 240 1.10
2025-12-13 unproductive 314 244 1.20
$ garmin health insights --days 28
╔══════════════════════════════════════════════════════════════════╗
║ HEALTH INSIGHTS (28 days) ║
╚══════════════════════════════════════════════════════════════════╝
RESTORATIVE SLEEP RATIO
Your avg: 38% | Target: >45% | Last night: 22%
STRESS CORRELATION
Low restorative (<30%) -> avg next-day stress: 38
High restorative (>45%) -> avg next-day stress: 24
TODAY'S PREDICTION
Based on last night (50m restorative, 22%):
Expected stress: HIGH (35-45 avg expected)
MIT