Bike-only Zwift .zwo generator with human-readable preview + confirmation loop. - scripts/zwo_builder.py: spec<->.zwo build/validate/parse/render/TSS estimate - scripts/zwo.py: CLI (build, from-template, validate, parse, render, templates) - references/zwo-format.md: condensed offline format reference - assets/example-vo2max.zwo + tests/test_zwo.py (9 tests) - Publishes via hosting skill; files result into Knowledge Wiki Format ground truth: h4l/zwift-workout-file-reference
4.9 KiB
name, description
| name | description |
|---|---|
| zwift-workout | Create, preview, edit, validate and publish Zwift .zwo workout files for cycling (bike-only). Use when the user asks to build a Zwift workout, generate a .zwo file, convert a training idea into a Zwift session, preview/adjust an existing workout, or publish a workout for import into Zwift. |
🚴 Zwift Workout (.zwo) Builder
Builds valid Zwift .zwo files from a small JSON spec, renders a human-readable
preview for confirmation, and publishes the finished file. Bike-only.
When to use
- "Bau mir ein Zwift-Workout …" / "Create a .zwo for 5×3min VO2max"
- "Zeig mir das Workout" / "änder die Intervalle auf 4×5min"
- "Lade das Workout in Zwift" (publish to hosting for import)
Core workflow (always follow this order)
- Draft the spec. Either pick a deterministic template
(
zwo.py templates→endurance | sweetspot | vo2max | sprint) or write a JSON spec from the user's request. Keep power as FTP fractions (0.88= 88 %,1.15= 115 %); durations in seconds. - Render the preview and ask for confirmation. Run
python3 {baseDir}/scripts/zwo.py render <spec.json>(orbuild … --preview) and show the table to the user. Do not publish before the user confirms. - Apply changes. Edit the JSON spec and re-render; repeat until confirmed.
- Build + publish on confirmation. Run
python3 {baseDir}/scripts/zwo.py build <spec.json> -o <name>.zwo --publish. This validates, writes the file, and uploads it via thehostingskill (https://hosting.haumdaucher.de/docs/…). - Deliver. Post the hosting link (and the
.zwoasMEDIA:<path>if the user wants the file directly). Optionally offer a QR code (hosting skill rule). - File the result into the wiki under
syntheses/orconcepts/per the Knowledge Wiki protocol (see below).
JSON spec format
{
"name": "VO2 Max 5x3",
"author": "IT Guy",
"description": "5 × 3 min @ 115 % FTP, 3 min Pause.",
"sportType": "bike",
"tags": ["vo2max", "structured"],
"steps": [
{"type": "Warmup", "duration": 600, "powerLow": 0.50, "powerHigh": 0.75},
{"type": "IntervalsT", "repeat": 5, "onDuration": 180, "offDuration": 180,
"onPower": 1.15, "offPower": 0.55},
{"type": "Cooldown", "duration": 300, "powerLow": 0.75, "powerHigh": 0.40}
]
}
Supported step types (bike)
type |
Required fields | Optional |
|---|---|---|
Warmup |
duration, powerLow, powerHigh |
cadence |
Cooldown |
duration, powerLow, powerHigh |
cadence |
SteadyState |
duration, power |
cadence |
Ramp |
duration, powerLow, powerHigh |
— |
IntervalsT |
repeat, onDuration, offDuration, onPower, offPower |
cadence, cadenceResting |
FreeRide |
duration |
flatRoad |
MaxEffort |
duration |
— |
SolidState |
duration, power |
— |
RestDay |
— | — |
Power values are fractions of FTP; duration is in seconds. See
references/zwo-format.md for the full tag/attribute reference.
CLI
python3 {baseDir}/scripts/zwo.py templates # list templates
python3 {baseDir}/scripts/zwo.py from-template vo2max --title "VO2 Max 5x3" --publish
python3 {baseDir}/scripts/zwo.py render my.json # preview only
python3 {baseDir}/scripts/zwo.py build my.json -o out.zwo --preview --publish
python3 {baseDir}/scripts/zwo.py validate existing.zwo # check a file
python3 {baseDir}/scripts/zwo.py parse existing.zwo --json # .zwo -> spec (editable)
Guardrails
- Power range:
0.20 – 1.50FTP. Outside → hard error (catches unit mistakes). - Durations: integer seconds,
> 0;< 5 sand> 4 hproduce warnings. - Structure: exactly one
<workout>, root<workout_file>,namerequired,sportTypemust bebike. - Round-trip check: output XML is re-parsed with
xml.etreebefore writing; text fields are escaped, so umlauts/quotes never corrupt the file. - Never publish without explicit user confirmation of the rendered preview.
Reference & fixtures
references/zwo-format.md— condensed tag/attribute reference (offline copy).assets/example-vo2max.zwo— known-good fixture; use for regression tests.
Knowledge Wiki filing
After a workout is confirmed and published, file it per the Karpathy LLM Wiki
protocol: create/update a concepts/ or syntheses/ page recording the workout
name, structure, power targets, hosting URL, and rationale, then append a
log.md entry (ingest/synthesis). Cross-link the Fitness agent page.
Inter-agent synergy
agents/fitness.md owns training intent (Tacx Flux 2, FTP 275 W). This skill is
the execution layer for structured cycling sessions. For evidence-based
protocols (e.g. SIT 30 s / 4 min), consult the Knowledge Wiki first via
wiki_search. A future refactor can share one spec module with garmin-workout
(one source spec → Garmin workout + .zwo).