⚠️ Experimental Project. This started as a personal experiment and remains a work in progress. The codebase is being refactored toward a configurable, modular architecture, but everything is in flux. Expect rough edges, breaking changes, and incomplete features. No guarantees that it will work out of the box for your setup.
Cycling Training is a modular analytics and planning toolkit for serious endurance cyclists. It syncs training and recovery data from multiple services into PostgreSQL, computes performance models, generates race planning outputs, and renders a daily HTML dashboard with an optional LLM coaching assessment. It is designed for athletes and coaches who want a repeatable, data driven workflow that can run locally or on a small server.
See dashboard preview at your-domain/cycling-dashboard/
git clone https://github.com/your-org/cycling-training.git
cd cycling-training
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# run the setup wizard
python -m cycling_training init
# create your database
createdb cycling_training
# sync the last 30 days from configured sources
python -m cycling_training sync-all --days 30
# generate the dashboard HTML
python -m cycling_training generate-dashboardCLI entry point is cycling_training/__main__.py. You can also run python -m cycling_training or create a symlink named cycling-training pointing to the module entry point.
python -m cycling_training <command> [options]
sync-whoop --days NSync Whoop recovery, sleep, and cycle data.sync-tp --days NSync TrainingPeaks workouts.sync-stravaSync Strava activities and power zones.sync-all --days NSync all configured sources.
statusShow current FTP, training load, last workout, and latest insight.pmcPrint the last 14 days of CTL, ATL, and TSB.correlateRun recovery and training correlation analysis.weekly-summary --target-date YYYY-MM-DDWeekly summary from legacy analysis module.trendsTraining trend analysis from legacy module.
generate-dashboard --uploadRender the HTML dashboard and optionally upload it.race-planGenerate the race planning summary.
initRun the configuration wizard and writeconfig.json.
┌───────────────────────────────────────────────────┐
│ CLI │
│ cycling_training/cli.py │
└───────────────┬───────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────┐
│ Data sources │
│ cycling_training/sources/* adapters │
└───────────────┬───────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────┐
│ PostgreSQL │
│ training_workouts, training_load, whoop_recovery │
└───────────────┬───────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────┐
│ Analysis and coaching │
│ cycling_training/analysis, coaching/assessment.py │
└───────────────┬───────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────┐
│ Dashboard rendering and upload │
│ cycling_training/dashboard │
└───────────────────────────────────────────────────┘
| Source | Data | Auth method |
|---|---|---|
| Whoop | Recovery, sleep, strain | OAuth2 with refresh tokens |
| TrainingPeaks | Planned and completed workouts | Cookie based token exchange |
| Strava | Activities and power zones | OAuth2 |
| Open-Meteo | Forecasts for training and race planning | Public API |
- Date navigation and daily archive links
- Header KPIs for FTP, CTL, ATL, and TSB
- Weekly training summary with completion and TSS targets
- Training load charts and PMC trends
- Strava power zone distribution charts
- Recovery and sleep trend charts
- Workout quality scoring and correlations
- FTP trajectory and testing roadmap
- Race plan summary and fueling guidance
- Coaching assessment narrative
The dashboard can include a coaching assessment generated by an OpenAI compatible API. The assessment is driven by recent training load, completion rate, recovery trends, and FTP changes. Providers are pluggable, so you can switch between LLM output, a Jinja2 template, or disable coaching entirely. The default configuration targets an OpenClaw gateway and Anthropic Claude Sonnet, but any OpenAI compatible endpoint works.
Race planning uses the analysis/race.py module to generate pacing and nutrition guidance from configuration. It supports:
- Course segmentation with terrain annotations
- Power targets and estimated segment time
- Rest stop planning and on bike fueling plans
- Physics parameters like CdA, Crr, and drafting benefit
Two upload paths are supported by the dashboard generator.
- Vercel deployment for static hosting with optional authentication middleware and cookie based access control
- WebDAV upload to a hosting provider that exposes a WebDAV endpoint
Use generate-dashboard --upload and set dashboard.upload_method to vercel or webdav in config.json.
Configuration lives in config.json at the repo root and is generated by the init wizard. See docs/CONFIGURATION.md for the full schema, examples, and per service credential requirements.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# run tests when a suite is available
python -m pytestContributions are welcome. Open a pull request with a clear summary and include any new configuration keys in the documentation.
MIT