# Copy to .env and fill in. Everything here is optional except the athlete # zones — each missing key just disables its feature (see README "Degrading # gracefully"). The pipeline runs with an empty .env; it just runs dumber. # --- Model provider: one provider powers the whole run (vision + narrative) --- # --- gemini (default) | openai | local. Do not mix providers in a single run. --- MODEL_PROVIDER=gemini # --- Gemini (used when MODEL_PROVIDER=gemini) --- # Without a key, candidates come from telemetry and Strava only. GEMINI_API_KEY= GEMINI_MODEL=gemini-3.5-flash # --- OpenAI (used when MODEL_PROVIDER=openai) --- # Default is gpt-4.1-mini — current, vision-capable, cost-oriented for # high-volume frame scoring. Override OPENAI_MODEL to compare models; # cache keys fingerprint the model so ratings never silently reuse. OPENAI_API_KEY= OPENAI_MODEL=gpt-4.1-mini # --- Local OpenAI-compatible VLM (used when MODEL_PROVIDER=local) --- # Default URL is MLX-VLM. Ollama is often http://localhost:11434/v1; # LM Studio often http://localhost:1234/v1. Prefers json_schema structured # outputs; falls back to free-form JSON when the server rejects that format. # LOCAL_MAX_CONCURRENCY is process-wide (scanner builds one adapter per clip). LOCAL_BASE_URL=http://localhost:8080/v1 LOCAL_API_KEY=local LOCAL_MODEL= LOCAL_MAX_CONCURRENCY=1 LOCAL_TIMEOUT_SECONDS=600 # --- Strava: segment popularity. Optional. --- # Register an app at https://www.strava.com/settings/api STRAVA_CLIENT_ID= STRAVA_CLIENT_SECRET= # --- Garmin Connect: only for `garmin-download`. Skip both if you copy --- # --- the .fit off the device yourself. --- GARMIN_EMAIL= GARMIN_PASSWORD= # --- OpenStreetMap: your email. Nominatim's usage policy requires a real --- # --- contact address. Unset = no GPS-derived origin/destination/road. --- # https://operations.osmfoundation.org/policies/nominatim/ OSM_CONTACT_EMAIL= # --- SET THESE. The defaults are one rider's numbers and are probably not --- # --- yours. They drive three things: the spike thresholds below, the HUD's --- # --- power/HR zone colors, and the power zones handed to the vision model --- # --- so it knows whether 216W means "cruising" or "peak effort" for you. --- FTP=240 MAX_HEART_RATE=196 # --- Spike thresholds. Leave commented to scale off FTP / MAX_HEART_RATE --- # --- (~1.45x FTP, ~87% max HR). Uncomment only to hand-tune. --- # POWER_SPIKE_THRESHOLD=350 # HR_SPIKE_THRESHOLD=170 SPEED_SPIKE_THRESHOLD=12.0 # Paths DATA_DIR=data