Automated Strava-to-Garmin Sync for MyWhoosh Activities
Zero manual steps. Just ride, and your training effect appears on Garmin Connect automatically.
This project automatically syncs your MyWhoosh virtual cycling activities from Strava to Garmin Connect as .fit files, ensuring they're recognized as Garmin device uploads. This is crucial for having your training effect properly reflected in your Garmin Training Readiness and Preparation Score.
The original forked project required multiple manual steps:
- π Manually downloading
.fitfiles from MyWhoosh website - π§ Applying transformations to fix power/heart rate averages
- π‘οΈ Removing temperature data
- π€ Manually uploading to Garmin Connect
This was tedious and error-prone. Big training sessions weren't impacting training preparation scores because manual uploads were missed.
This fully automated workflow:
- β Zero manual steps β runs completely in the cloud via GitHub Actions
- β Automatic detection β finds new MyWhoosh activities on Strava
- β Smart filtering β only uploads activities not already on Garmin Connect
- β
Training effect preserved β
.fitfiles recognized as Garmin device uploads - β Webhook support β optional instant sync when you upload to Strava
graph LR
A[MyWhoosh App] -->|Auto-upload| B[Strava]
B -->|Webhook trigger| C{GitHub Actions}
C -->|If Created & Virtual Ride: Fetch activity via API| D[Strava Client]
D -->|Download .fit data| E[FIT Builder]
E -->|Convert to Garmin .fit| F[Garmin Client]
F -->|Upload as device| G[Garmin Connect]
- Garmin Client (garth) β handles authentication and upload
- FIT Builder (fit_tool) β converts Strava JSON to Garmin-compatible
.fit - Strava API β OAuth2 authentication and activity download
π For detailed step-by-step instructions, see SETUP.md
- GitHub account (for running GitHub Actions)
- Strava account with MyWhoosh activities auto-uploaded
- Garmin Connect account
- Strava API application (create one here)
- Fork this repository or clone it to your GitHub account
- Enable GitHub Actions in your repository settings
Run the Garmin setup script locally to authenticate and generate tokens:
# Clone the repo
git clone https://github.com/YourUsername/MyWhoosh2Garmin.git
cd MyWhoosh2Garmin
# Install dependencies
pip install uv
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv pip install -r pyproject.toml
# Run Garmin authentication
python garmin/utils.pyYou'll be prompted for:
- Garmin username (email)
- Garmin password
- 2FA code (if enabled)
The script will output a GARMIN_TOKENS string β save this securely!
Run the Strava setup script to initialize OAuth tokens:
python strava/client.pyFollow the prompts:
- Click the authorization URL that appears
- Authorize the application
- Copy the callback URL from your browser
- Paste it back into the terminal
This creates strava_tokens.json with your access/refresh tokens.
Go to your repository β Settings β Secrets and variables β Actions β New repository secret
Add the following secrets:
| Secret Name | Description | Where to Find |
|---|---|---|
STRAVA_CLIENT_ID |
Your Strava API application ID | Strava API Settings |
STRAVA_CLIENT_SECRET |
Your Strava API secret | Strava API Settings |
STRAVA_ACCESS_TOKEN |
OAuth access token | From strava_tokens.json after setup |
STRAVA_EXPIRES_AT |
Token expiration timestamp | From strava_tokens.json |
STRAVA_EXPIRES_IN |
Token expiration duration | From strava_tokens.json |
STRAVA_REFRESH_TOKEN |
OAuth refresh token | From strava_tokens.json |
GARMIN_TOKENS |
Garmin authentication tokens | From garmin/utils.py output |
Go to Actions β Self-hosted runner β Run MyWhoosh2Garmin β Run workflow
That's it! The workflow will:
- Fetch your last 7 days of Garmin virtual cycling activities
- Check Strava for MyWhoosh activities
- Download new activities not on Garmin
- Convert to
.fitformat - Upload to Garmin Connect
For instant sync after every Strava upload, set up a webhook using my WebhookProcessor:
- Deploy the WebhookProcessor to handle Strava webhook events
- Configure it to trigger your GitHub Actions workflow
- Register the webhook URL with Strava
Now every MyWhoosh activity uploaded to Strava will automatically sync to Garmin within minutes! β‘
The following environment variables are required for the complete workflow:
# Strava OAuth credentials
STRAVA_CLIENT_ID="12345"
STRAVA_CLIENT_SECRET="your_strava_client_secret"
STRAVA_ACCESS_TOKEN="your_strava_access_token"
STRAVA_EXPIRES_AT="1234567890"
STRAVA_EXPIRES_IN="21600"
STRAVA_REFRESH_TOKEN="your_strava_refresh_token"
# Garmin authentication (from garth client)
GARMIN_TOKENS="your_garmin_tokens_string"Note: For local development, copy
.env-templateto.envand fill in your values.
-
Authentication
- Garmin: Uses pre-authenticated tokens from
GARMIN_TOKENS - Strava: Uses OAuth2 with automatic token refresh
- Garmin: Uses pre-authenticated tokens from
-
Activity Discovery
- Fetches last 7 days of virtual cycling activities from Garmin Connect
- Fetches recent MyWhoosh activities from Strava (filtered by name containing "MyWhoosh")
-
Smart Filtering
- Compares Strava and Garmin activities by start time
- Only processes activities not already on Garmin
-
Data Conversion
- Downloads Strava activity data (metadata + streams: power, heart rate, cadence, etc.)
- Builds Garmin-compatible
.fitfile usingfit_tool
-
Upload
- Uploads
.fitfile to Garmin Connect usinggarthclient - File is recognized as a Garmin device upload (triggers training effect)
- Uploads
The workflow uses SQLite (strava.db) to track downloaded activities and prevent duplicate processing.
β οΈ Never commit.envor token files to version control- π Store all credentials as GitHub Secrets
- π Tokens are automatically refreshed when expired
- ποΈ Processed
.fitfiles are deleted after upload
- Python 3.13+
- uv (package manager)
- Key libraries:
garthβ Garmin Connect API clientpydantic/pydantic-settingsβ configuration managementrequestsβ HTTP clientfit_toolβ FIT file manipulation
Feel free to open issues or pull requests! This project is a personal automation tool, but improvements are welcome.
- Original inspiration from MyWhoosh2Garmin
- matin/garth for excellent Garmin API client
- fit_tool for FIT file utilities
- Strava API for activity data access
Made with β€οΈ for cyclists who want their training data to just work.