Fitler
Fitler is a Python toolkit for aggregating, syncing, and analyzing your fitness activity data from multiple sources (Strava, RideWithGPS, spreadsheets, and local files). It is designed to be self-contained, non-destructive, and extensible.
🌐 Website: fitler.net 📦 PyPI: pypi.org/project/fitler 📚 Source: github.com/ckdake/fitler[CAUTION: This is under active development. Do not use it without reading every line of code!]
Features
- Parse and import activity files (
.fit
,.tcx
,.gpx
, and compressed variants) - Integrate with Strava and RideWithGPS APIs
- Store and manage activity metadata in a local SQLite database
- Command-line interface for authentication and data management
- Web dashboard for viewing configuration and database status (
./dev.sh
) - Modular provider and file format architecture for easy extension
- Static website with documentation at fitler.net
Quick Start
Option 1: Development Container (Recommended)
The easiest way to get started is using the provided development container:
- Prerequisites: Install VS Code and Docker
- Open Repository: Clone and open in VS Code
- Reopen in Container: When prompted, click "Reopen in Container" or use
Ctrl+Shift+P
→ "Dev Containers: Reopen in Container" - Wait for Setup: The container will automatically install all dependencies and run verification tests
- Start Developing: Everything is ready to go!
📋 See .devcontainer/README.md
for detailed container documentation.
Verify Setup:
.devcontainer/verify.sh # Quick environment check
python -m fitler --help # Test CLI access
Option 2: Local Installation
Clone the repository:
git clone https://github.com/ckdake/fitler.git cd fitler
Install dependencies:
pip install -e .[dev] # Development installation # OR pip install . # Regular installation
Set up development tools:
pre-commit install # Install git hooks
Set up environment variables: Create a
.env
file in the project root with the following variables:# Strava API credentials (required for Strava integration, generate with the auth-strava command) STRAVA_CLIENT_ID=your_client_id STRAVA_CLIENT_SECRET=your_client_secret STRAVA_ACCESS_TOKEN=your_access_token STRAVA_REFRESH_TOKEN=your_refresh_token STRAVA_TOKEN_EXPIRES=token_expiration_timestamp # RideWithGPS credentials (required for RWGPS integration) RIDEWITHGPS_EMAIL=your_email RIDEWITHGPS_PASSWORD=your_password RIDEWITHGPS_KEY=your_api_key # Garmin Connect credentials (required for Garmin integration) GARMIN_EMAIL=your_email GARMINTOKENS=~/.garminconnect
Note: You can get Strava API credentials by creating an application at https://www.strava.com/settings/api, RideWithGPS credentials at https://ridewithgps.com/api, and Garmin Connect credentials by using your existing Garmin Connect account.
Prepare your data:
- Place your exported Strava activity files in a folder such as
export_12345/
in the repo root. - If you're not using Strava export, place your files in
export_12345/activities/
in the repo root. - (Optional) Place your exercise spreadsheet at
~/Documents/exerciselog.xlsx
.
- Place your exported Strava activity files in a folder such as
Authenticating with Strava
To use Strava API features, you need to authenticate and get an access token.
Set your Strava API credentials as environment variables:
export STRAVA_CLIENT_ID=your_client_id export STRAVA_CLIENT_SECRET=your_client_secret
Run the Strava authentication command:
python -m fitler auth-strava
This will guide you through the OAuth process and print an access token. Set it in your environment:
export STRAVA_ACCESS_TOKEN=your_access_token
Authenticating with Garmin Connect
To use Garmin Connect API features, you need to authenticate and store OAuth tokens.
Set your Garmin Connect credentials as environment variables (optional):
export GARMIN_EMAIL=your_email export GARMINTOKENS=~/.garminconnect
Run the Garmin authentication command:
python -m fitler auth-garmin
This will prompt for your email and password, handle any required MFA, and automatically generate and store OAuth tokens that are valid for about a year. The tokens will be reused automatically for future API calls.
Running Fitler
You can use the CLI for various commands:
python -m fitler --help
python -m fitler configure
python -m fitler auth-strava
python -m fitler auth-garmin
python -m fitler pull --date 2025-08
python -m fitler sync-month 2025-08
python -m fitler reset --date 2025-08
configure
– Set up paths and API credentials.auth-strava
– Authenticate with Strava and get an access token.sync
– Sync and match activities from all sources.help
– Show usage and documentation.
You can also use the Python API in your own scripts to process files, sync with providers, or analyze your data.
Running Tests
Fitler uses pytest for testing. To run all tests:
python -m pytest --cov=fitler --cov-report=term-missing -v
Test files are in the tests/
directory and mirror the package structure.
Packaging & Publishing to PyPI
To prepare and publish the package:
- Update version and metadata in
setup.py
andsetup.cfg
. - Build the package:
python -m build
- Upload to PyPI (requires
twine
):twine upload dist/*
Contributing
PRs and issues are welcome! See the TODO section in this README for ideas and next steps.
Development
This is a monorepo containing both the Python package and the static website.
Repository Structure
fitler/
├── .devcontainer/ # Development container configuration
├── .github/workflows/ # CI/CD pipelines
├── app/ # Web dashboard (Flask)
├── fitler/ # Python package source
├── tests/ # Python tests
├── site/ # Static website source
│ ├── src/ # Website source files
│ ├── scripts/ # Build scripts
│ └── dist/ # Built website (generated)
├── pyproject.toml # Python package config
├── ruff.toml # Python linting configuration
├── dev.sh # Start web dashboard
└── README.md # This file (also used for website)
Web Dashboard
For local development, Fitler includes a simple web dashboard to view configuration and database status:
# Start the web dashboard
./dev.sh
Visit http://localhost:5000 to see:
- 📊 Configuration status from
fitler_config.json
- 🔌 Provider settings (enabled/disabled, priorities)
- 💾 Database information (size, tables, row counts)
- 🔗 API endpoints for programmatic access
The dashboard provides a quick way to verify your Fitler setup without running CLI commands.
Development Tools
Python Development:
- Ruff: Fast linting, formatting, and import sorting (replaces Black, Flake8, isort, Pylint)
- MyPy: Static type checking
- Pytest: Test runner with coverage
- Pre-commit: Git hooks for automated code quality
Web Development:
- Node.js 18: Runtime environment
- Vite: Build system and dev server
- ESLint: JavaScript linting
- Stylelint: CSS linting
- Prettier: Code formatting
Development Commands
Python:
# Run tests
python -m pytest -v
# Lint and format code
ruff check fitler/ tests/ # Check for issues
ruff check --fix fitler/ tests/ # Auto-fix issues
ruff format fitler/ tests/ # Format code
# Type checking
mypy fitler/
# Run CLI
python -m fitler --help
Website:
cd site/
# Install dependencies
npm install
# Development server (localhost:3000)
npm run dev
# Build for production
npm run build
# Lint and format
npm run lint
npm run format
Quality Assurance:
# Run all pre-commit hooks
pre-commit run --all-files
# Verify development environment
.devcontainer/verify.sh
VS Code Integration
The development container automatically configures VS Code with:
- Format on save for all file types
- Automatic import organization
- Error highlighting for Python, JavaScript, CSS
- Integrated terminal with proper environment
- All necessary extensions pre-installed
Available VS Code Tasks (Ctrl+Shift+P
→ "Tasks: Run Task"):
- Python: Run Tests - Run all Python tests
- Python: Lint All - Run Python linting
- DevContainer: Verify Setup - Verify environment health
Website Development
The website at fitler.net automatically includes content from this README.md file:
- Start development server:
cd site && npm run dev
- Edit files in
site/src/
or update README.md - Site rebuilds automatically with changes
- Build for production:
npm run build
The website is automatically deployed when changes are pushed to the main branch.
License
This project is licensed under the Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0). See the LICENSE file for details.
Getting things back out into spreadsheet
sqlite3 metadata.sqlite3
.headers on
.mode csv
.output metadata.csv
SELECT date,activity_type,location_name,city,state,temperature,equipment,duration_hms,max_speed,avg_heart_rate,max_heart_rate,calories,max_elevation,total_elevation_gain,with_names,avg_cadence,strava_id,garmin_id,ridewithgps_id,notes from ActivityMetadata where source="Main";
.quit
TODO
* Next month to fix: `python -m fitler sync-month 2024-03`
* File provider manually fixed, go through other providers and manually fix them to work the ~same way. make sure we're not making API calls if the month is synced.
* Fix strava gear matching to work for running shoes.
* Fix "create" in providers to create_from_activity, and get all that out of sync_month
* Write some tests...
* Get everything out of gpx files: https://pypi.org/project/gpxpy/ (basics are in, need to fill out metadata, add more fields to db!)
* Get everything out of tcx files: https://pypi.org/project/python-tcxparser/ (basics are in, need to fill out metadata, add more fields to db!)
* Get everything out of fit files: https://github.com/dtcooper/python-fitparse/ (basics are in, need to fill out metadata, add more fields to db!)
* Get everything out of KML files: https://pypi.org/project/pykml/
* Get everything out of a spreadsheet with headers: https://pypi.org/project/openpyxl/ (basics are in, work better with headers)
* Output as all fit (lib already included)
* Output as all tcx (lib already included)
* Output as all gpx (lib already included)
* Output as all kml (lib already included)
* Output as all geojson: https://pypi.org/project/geojson/
* Load files from S3 bucket or somewhere else instead of local: https://pypi.org/project/boto3/
* What is in TrainingPeaks?
* What is in Wandrer.earth?
* What about the weather?
* What about choochoo?
* What else?
* switch to fitdecode