CLI tool to backup fitness activities with incremental sync, map visualization, and export (Strava supported)
Project description
MyKrok
Note: This project was formerly known as "mykrok". The name "MyKrok" comes from Ukrainian "мій крок" meaning "my step" - fitting for a tool that preserves every step of your fitness journey.
CLI tool to backup fitness activities with incremental sync, map visualization, and export capabilities. Currently supports Strava as the data source.
Live Demo - Try the web frontend with synthetic data. It is served directly from gh-pages branch where you could also explore the backup filetree we show below.
Features
- Backup Activities: Download all your activities including metadata, GPS tracks, photos, comments, and kudos
- Incremental Sync: Only fetch new activities after initial backup
- Interactive Maps: Generate HTML maps with route visualization and heatmap mode
- Statistics: View activity statistics by time period with breakdowns by type
- Offline Browsing: Browse your backed-up activities locally without internet
- FitTrackee Export: Export activities to self-hosted FitTrackee instances
Screenshots
The unified web frontend provides a complete activity browsing experience.
Screenshots are auto-generated from the demo dataset (tox -e screenshots).
Map View
Map view with activity markers
Activities zoomed to fit
Activity popup with details
Sessions View
Sessions list with filters
Sessions filtered by type
Session detail panel
Session Detail
Full-screen session view
Activity data streams (elevation, heart rate, cadence)
Statistics
Statistics dashboard
Statistics by athlete
No Backend Required
The web UI loads data directly from the file tree — no database, no server-side processing, no custom data structures. Just standard formats (TSV, JSON, Parquet) served as static files:
data/
├── athletes.tsv # List of athletes
├── athl=alice/
│ ├── sessions.tsv # Activity index (dates, distances, stats)
│ └── ses=20241218T063000/
│ ├── info.json # Activity metadata
│ ├── tracking.parquet # GPS + sensor streams (lat, lng, hr, cadence...)
│ └── photos/
│ └── photo_1.jpg
└── athl=bob/
├── sessions.tsv
└── ses=20241218T063000/ # Shared run (same datetime)
├── info.json
└── tracking.parquet
The browser fetches athletes.tsv → discovers athletes → loads each sessions.tsv → renders the map/table. Clicking an activity fetches its tracking.parquet directly. This means you can:
- Host anywhere: Any static file server (nginx, GitHub Pages, S3, local
python -m http.server) - Query with standard tools: DuckDB, pandas, or any Parquet-compatible tool
- Version with git/DataLad: Text files diff cleanly, binary files handled by git-annex
- Browse offline: Open
mykrok.htmldirectly from disk
Installation
# Clone repository
git clone https://github.com/mykrok/mykrok
cd mykrok
# Install with uv (recommended)
uv venv
source .venv/bin/activate
uv pip install -e ".[devel]"
# Or with pip
pip install -e ".[devel]"
Strava API Setup
Before using MyKrok, you need to create a Strava API application:
- Go to https://www.strava.com/settings/api
- Click "Create an Application" (or use existing one)
- Fill in the form:
- Application Name: e.g., "My Backup Tool"
- Category: "Personal"
- Website: "http://localhost" (or your own)
- Authorization Callback Domain: "localhost"
- After creation, note your Client ID and Client Secret
Quick Start
-
Authenticate with your Strava API credentials:
mykrok auth --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET
This opens a browser for OAuth authorization. After approval, tokens are saved automatically.
-
Sync your activities:
mykrok sync -
View your data:
mykrok view stats mykrok create-browser --serve
Configuration
MyKrok looks for configuration in the following order:
MYKROK_CONFIGenvironment variable (explicit path).mykrok/config.tomlin the current directory (recommended for DataLad datasets).mykrok/config.tomlin the current directory (legacy, still supported).mykrok.tomlin the current directory (legacy, still supported)~/.config/mykrok/config.toml
OAuth tokens are stored separately in .mykrok/oauth-tokens.toml (gitignored).
Configuration File Format
Create .mykrok/config.toml in your project directory or ~/.config/mykrok/config.toml:
[strava]
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
# These are auto-populated after `mykrok auth`:
# access_token = "..."
# refresh_token = "..."
# token_expires_at = 1234567890
[data]
directory = "./data" # Where to store backed-up activities
[sync]
photos = true # Download activity photos
streams = true # Download GPS/sensor data
comments = true # Download comments and kudos
[fittrackee]
url = "https://fittrackee.example.com"
email = "your@email.com"
# password can be set via FITTRACKEE_PASSWORD env var
Environment Variables
All settings can be overridden with environment variables:
| Variable | Description |
|---|---|
MYKROK_CONFIG |
Path to config file |
STRAVA_CLIENT_ID |
Strava API client ID |
STRAVA_CLIENT_SECRET |
Strava API client secret |
MYKROK_DATA_DIR |
Data storage directory |
FITTRACKEE_URL |
FitTrackee instance URL |
FITTRACKEE_EMAIL |
FitTrackee login email |
FITTRACKEE_PASSWORD |
FitTrackee login password |
Commands
Authentication
# First-time authentication
mykrok auth --client-id YOUR_ID --client-secret YOUR_SECRET
# Re-authenticate (e.g., after token expiry)
mykrok auth --force
Sync Activities
# Incremental sync (default) - only new activities since last sync
mykrok sync
# Full sync - re-download all activities
mykrok sync --what=full
# Refresh social data (kudos/comments) for existing activities
mykrok sync --what=social
# Refresh athlete profile info and avatar
mykrok sync --what=athlete-profiles
# Sync with limits
mykrok sync --limit 100
# Preview without downloading
mykrok sync --dry-run
# Skip photos/comments
mykrok sync --no-photos --no-comments
# Sync specific activities by ID
mykrok sync --activity-ids 12345678901,12345678902
View Statistics
# Overall stats
mykrok view stats
# Stats for specific year
mykrok view stats --year 2025
# Stats for specific month
mykrok view stats --month 2025-06
# Breakdown by month
mykrok view stats --by-month
# Breakdown by activity type
mykrok view stats --by-type
# JSON output
mykrok view stats --json
Generate Interactive Browser
# Generate and serve locally
mykrok create-browser --serve
# Custom port
mykrok create-browser --serve --port 9000
# Generate without serving
mykrok create-browser
# Custom output filename
mykrok create-browser --output my-activities.html
The browser includes:
- Interactive map with activity markers and GPS tracks
- Sessions list with filtering by date, type, and search
- Statistics dashboard with charts
- Heatmap layer toggle
- Photo viewing
- Offline support (works without internet)
Export GPX
# Export specific activity
mykrok gpx 12345678901 --output activity.gpx
# Export all activities
mykrok gpx --all --output-dir ./gpx/
Export to FitTrackee
# Export to FitTrackee
mykrok export fittrackee --url https://fittrackee.example.com --email user@example.com
# Preview what would be exported
mykrok export fittrackee --dry-run
# Force re-export all
mykrok export fittrackee --full
Create DataLad Dataset
Create a version-controlled dataset for reproducible backups using DataLad:
# Create a new DataLad dataset
mykrok create-datalad-dataset ./my-backup
# Navigate to the dataset
cd my-backup
# Edit config with your Strava API credentials
nano .mykrok/config.toml
# Authenticate
mykrok auth
# Sync using datalad run (creates versioned commit)
make sync
# Generate interactive browser for web viewing
mykrok create-browser
This creates a dataset with:
- text2git configuration: Text files (JSON, TSV) tracked by git, binary files (photos, Parquet) by git-annex
- Sample config:
.mykrok/config.tomlwith comments explaining each setting - README: Documentation for the dataset
- Makefile: Targets for
make sync,make stats,make map, etc. usingdatalad run
Benefits of DataLad integration:
- Full version history of all backups
- Reproducible sync operations with
datalad run - Efficient storage of binary files with git-annex
- Easy to clone and share datasets
- Simple publishing to web servers (see below)
Publishing to a Web Server
With DataLad, publishing your backup to a web server for browser-based viewing is trivial:
# Create a sibling that excludes sensitive files (API credentials)
datalad create-sibling -s public-website \
--annex-wanted "not metadata=distribution-restrictions=*" \
user@server.example.com:/var/www/mykrok
# Push your data (sensitive config files are automatically excluded)
datalad push --to=public-website
Then access the map visualization at https://your-server.example.com/mykrok/mykrok.html.
Note: Access restrictions and user management are outside the scope of this project. Implement access control using your web server's authentication mechanisms (HTTP Basic Auth, OAuth proxy, IP allowlisting, etc.).
Data Storage
Activities are stored in a Hive-partitioned directory structure:
data/
├── athletes.tsv # Summary of all athletes
├── mykrok.html # Generated interactive browser
└── athl={username}/
├── athlete.json # Athlete profile data
├── avatar.jpg # Profile photo
├── sessions.tsv # Activity summary (TSV format)
├── gear.json # Equipment catalog
└── ses={datetime}/ # Individual activity folder
├── info.json # Activity metadata, comments, kudos
├── tracking.parquet # GPS + sensor data (Parquet)
├── tracking.json # Data manifest
└── photos/ # Activity photos
└── 20251218T063500.jpg
Query with DuckDB
duckdb
-- Activity summary
SELECT sport, SUM(distance_m)/1000 as km, COUNT(*) as activities
FROM read_csv_auto('data/athl=*/sessions.tsv')
GROUP BY sport;
-- GPS track analysis
SELECT ses, AVG(heartrate) as avg_hr, MAX(heartrate) as max_hr
FROM read_parquet('data/**/tracking.parquet', hive_partitioning=true)
WHERE heartrate > 0
GROUP BY ses;
Cron Setup
For automated daily backups:
# Edit crontab
crontab -e
# Add daily sync at 2 AM
0 2 * * * cd /path/to/mykrok && .venv/bin/mykrok sync --quiet
Troubleshooting
Token Expired
mykrok auth --force
Rate Limit Hit
The tool automatically pauses when hitting Strava's rate limits (200 requests/15 minutes, 1000/day) and resumes. For large initial syncs, the process may span multiple days.
Missing GPS Data
Some activities (treadmill, manual entries) have no GPS. They appear in sessions.tsv but not on maps.
Photo Download Failed
Photo URLs expire. Re-run sync to retry:
mykrok sync --full
License
Apache 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mykrok-1.4.1.tar.gz.
File metadata
- Download URL: mykrok-1.4.1.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0280c8e205cfdc0bd29a320a9653278308f5185080adfab53f8e1e06f7d41150
|
|
| MD5 |
29ca1cba3351f9db3401c0d5c31a3703
|
|
| BLAKE2b-256 |
c7eb6ff52f3c3193e11c48ac6bcc008df19d2ec1ce4ffe9f36839883c8d464d9
|
File details
Details for the file mykrok-1.4.1-py3-none-any.whl.
File metadata
- Download URL: mykrok-1.4.1-py3-none-any.whl
- Upload date:
- Size: 488.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
768f4540d1ca77ba32aa2f52a5e4a5ed8834caf21a28eee060f0e79db3d57479
|
|
| MD5 |
92f8c4b9eefd95c76d0b3ef09e57ca49
|
|
| BLAKE2b-256 |
9faad9b5347e93e4ab4b96472e790e14dc140bdf364716ca5df73f8355616b24
|