Hello everyone. I have extended phenomenal tool @niqwis’s 80/20 Workout importer in Python. And I belive I have solved the issue about importing cycling exercises with FTP zones instead of HR zones.
Being a beginner in the triathlon, I might have made several mistakes in terminology, please be vary.
It can be installed from PyPI as well as source code can be found at melihakay/8020-Fetcher.
Here is a quick preview after import:
Hope that would be useful to others as well.
eticu: 80/20 Endurance to Intervals.icu
eticu is a Python CLI pipeline that scrapes the free 80/20 Endurance workout library, parses and converts the .FIT files into fully structured Intervals.icu workouts, and idempotently uploads them to your Intervals.icu workout library.
It serves as a more robust, metric-first Python reimplementation of the 8020-intervals-icu TypeScript project, completely fixing target loss issues during imports, nested repeat structures, and adding idempotent uploading.
Scope Note: Brick (
BR*) workouts do not exist as.FITfiles in the library and are therefore also out of scope.
Installation & Setup
This project uses uv for dependency management.
-
Clone the repository:
git clone <repo-url> cd 8020-fetcher -
Environment Variables:
Copy.env.exampleto.envand set your Intervals.icu credentials:INTERVALS_API_KEY=your_intervals_api_key INTERVALS_ATHLETE_ID=your_intervals_athlete_idYou can find these in your Intervals.icu settings.
Usage
To run the full pipeline (scrape → download → upload):
uv run eticu all
Options:
--dry-run: Do everything except network writes to Intervals.icu.--cycling-power: Emit Power targets (instead of Heart Rate) for Ride workouts. (Run and Swim always remain HR).--cache-dir <dir>: Directory to cache downloaded.FITfiles (defaults to8020_cache).
To convert and view a single downloaded .FIT file locally:
uv run eticu convert 8020_cache/bike/CCI1.FIT
To upload a training plan from a CSV file (e.g. plans/olympic_distance_level_0.csv):
uv run eticu upload-plan plans/olympic_distance_level_0.csv --name "Olympic Level 0"
Exercise names in the CSV’s should be same as the 80/20 FIT files.
Options:
--pool-length: Pool length in meters (e.g., 25 or 50) for swim workouts.--dry-run: Parse the CSV and list the plan without uploading.
Critical Prerequisites
For the generated workouts to be accurate, you must configure your Intervals.icu settings to match the 80/20 Endurance methodology.
1. The 7-Zone Prerequisite
80/20 uses a 7-level zone system with two crossover zones: 1, 2, X, 3, Y, 4, 5.
Intervals.icu supports 7 zones (Z1 to Z7). eticu maps them sequentially.
You MUST update your Intervals.icu HR zones (and Power zones, if using --cycling-power) to match the numbers from the 80/20 zone calculator.
| 80/20 Zone | Intervals.icu Zone |
|---|---|
| Zone 1 | Z1 |
| Zone 2 | Z2 |
| Zone X | Z3 |
| Zone 3 | Z4 |
| Zone Y | Z5 |
| Zone 4 | Z6 |
| Zone 5 | Z7 |
Note: Because of crossover Zone X, 80/20’s “Zone 3” maps to Intervals “Z4”.
2. The --cycling-power Option & ERG Mode
By default, 80/20 workouts use Heart Rate targets. However, platforms like Zwift in ERG mode ignore HR targets; they require Power (%FTP).
If you ride on Zwift/TrainerRoad, pass the --cycling-power flag. This converts all Ride workouts to use Power zones.
- Prerequisite: For this to work, you MUST have your FTP and 7-level Power zones correctly configured in your Intervals.icu settings. If you don’t, power targets will be meaningless.
Core Behaviors
- Metric Units: All outputs are metric. Run and Ride distances are rounded to the nearest
0.1 km. Swims are strictly handled inmeters(mtrin Intervals.icu to distinguish from minutes). - Pool Lengths: Only
25mand50mswim workouts are fetched and processed.25yfiles are skipped. - Folder Layout: Workouts are uploaded into three flat folders (created automatically if they don’t exist):
80/20 - Run80/20 - Bike80/20 - Swim
- Idempotency: The upload is completely idempotent. It matches workouts by exact name within the folder and skips identical workouts, preventing duplication if the script is run multiple times.
Credits & License
This project was heavily inspired by the GPL-3.0 licensed njg4ne/8020-intervals-icu project, expanding its capabilities into a fully-typed Python package with deeper FIT file introspection.
