Files
openrun/QUICKSTART.md
2026-06-12 05:48:30 -04:00

7.5 KiB
Raw Blame History

QUICKSTART

You're ~5 minutes from a running dashboard. Two ways in: web (recommended, almost zero terminal) or CLI (for scripting).


What you'll need

  • A Mac or Linux machine with a terminal. Windows works under WSL but isn't tested.
  • uv — Python's package manager. Install:
    curl -LsSf https://astral.sh/uv/install.sh | sh
    
  • A Garmin export — see Getting your Garmin data below. You can skip this for now and use the manual logger.

That's it. No accounts, no cloud, no Python knowledge required.


1. Get the code & install deps

git clone <repo-url> openrun
cd openrun
uv sync

uv sync creates a .venv/ and installs everything. ~30 seconds on first run.

2. Launch the app

uv run openrun-web

Your browser opens at http://localhost:8501. (If it doesn't, copy that URL manually.)

3. Run the setup wizard

The first time you load the app, a yellow banner says "Looks like a fresh install" with a Start setup → button. Click it.

The wizard has five steps, each ~15 seconds:

  1. Intro — read it, click Start.
  2. Your profile — name, max HR, lactate-threshold HR, resting HR. If you don't know your max HR, leave the default at 200 and we'll auto-derive zones. You can always come back.
  3. HR zones — auto-filled from your max HR. If you've already configured custom zones in Garmin Connect, paste those bpm boundaries here instead.
  4. Race calendar — optional. Add one row per upcoming race (label + ISO date). Skip-able.
  5. Get your data — upload a Garmin export zip, or skip and start logging by hand.

When the wizard finishes, you land on the Dashboard.

4. Look around

  • 📊 Dashboard — CTL/ATL/TSB tiles, PMC chart, weekly volume, polarized split, recent activities.
  • 📋 Activities — filter by type/date/distance/name. Click any row to drill into splits, time-in-zone, decoupling.
  • 📈 Race plan — edit your weekly plan in the table; the projected PMC redraws automatically. Race-day TSB is shown for each race in your calendar.
  • 📝 Manual log — quick form to log strength/hike/unrecorded-run sessions. These feed the PMC.
  • 🛌 Recovery — sleep stages, HRV + RHR trends, training→next-morning HRV correlation.
  • 🫀 Efficiency — m/beat with rolling median, distance-bucket × year heatmap.
  • 🔄 Sync — DB status + a place to upload more exports later.

That's the whole app.

5. Stop / restart

Ctrl-C in the terminal that's running it.
uv run openrun-web   # restart any time

Your data is in data/garmin.db. Back that file up periodically.


Getting your Garmin data

The web app's Sync page accepts a Garmin Connect data export zip. You request one from Garmin:

  1. Sign in at https://www.garmin.com/account/datamanagement/exportdata.
  2. Click Request Data Export. Pick the categories you want — Activities, Wellness, and Connect Settings are the useful ones.
  3. Garmin emails a download link within 2472 hours.
  4. Download the zip (several hundred MB to a few GB depending on your history).
  5. Drag-and-drop it into the Sync page, click Ingest.

You'll see a progress log; takes 15 minutes depending on how many years of data.

Two zip flavours

Garmin confusingly has two export formats:

  • Garmin Connect data export (connect.zip) — what you get from the link above. Filenames are clean <activity_id>_<name>.fit. The wizard / Sync page handles this directly.
  • Garmin Takeout dump — a separate, UUID-named folder you can request via Google's data tools (less common). FITs use upload-IDs in filenames so they need an extra by-content linking step. If you have one of these, see the CLI section below for the 4-step sequence.

Live sync (skip on first install)

You can also pull incrementally from Garmin Connect's live API instead of waiting on the email export. Currently this is CLI-only because Garmin's MFA flow needs interactive prompts:

uv run openrun-auth     # email + password + MFA prompt; saves OAuth to .secrets/
uv run openrun-sync     # incremental top-up (last 14 days by default)
uv run openrun-sync --full   # 365-day backfill

Browser-driven live sync is on the roadmap.


CLI quickstart (power-user path)

If you'd rather skip the web app entirely:

uv sync
uv run openrun-init                   # creates data/garmin.db, prints status
uv run openrun-ingest path/to/export/zip
uv run openrun-link-fit path/to/export/   # only if it's a Takeout dump
uv run openrun-time-in-zone           # precompute the TIZ cache

Then open one of the notebooks under examples/notebooks/, pick the project's .venv as the kernel, and run-all.

Manual activity import via CSV

echo 'activity_date,activity_type,distance_km,duration_min,training_load,notes,external_id
2026-05-19,strength,,45,30,upper body,
2026-05-18,hike,8.0,120,40,morning hike,' > workouts.csv

uv run openrun-import-manual workouts.csv

external_id makes re-imports idempotent (upsert on conflict). Leave blank if you don't care about dedupe.


Troubleshooting

"Port 8501 already in use"

Another Streamlit is running. Stop it (Ctrl-C in the terminal that started it) or pick another port:

uv run openrun-web -- --server.port 8800

"FIT file not at recorded path"

You moved your export folder after linking. Run:

uv run openrun-link-fit /new/path/to/export --relink

This rewrites every stored FIT path to the new location by basename match.

Dashboard is empty

Either you haven't ingested any data yet (use the Sync page or openrun-ingest), or the activities are filtered out by the default running / trail_running types — check the Activities page with the type filter cleared.

Garmin live sync fails with 429

The endpoint rate-limits aggressively. Wait 3060 minutes, switch networks, or use the Path A export instead.

TSB looks way off

Most likely your training_load column is missing on a chunk of activities (Garmin only reports it for activities recorded by a compatible device). Check on the Activities page; the dashboard's PMC only counts rows where training_load IS NOT NULL.


What next?

Once you have data in:

  • Race-plan page — set up your goal race in openrun.toml (or via the wizard), then iterate on the weekly km / long-run km until projected race-day TSB lands in +10 to +25.
  • Activity-detail page — pick a recent race or hard workout, scroll to the Pa:Hr decoupling section, and look for where the bar chart crosses Friel's 10 % "unsustainable" line. That's where the wheels came off.
  • Recovery page — after a few weeks of data, check whether the Pearson r between yesterday's training load and tonight's HRV is meaningful for you. Often it's not, which is itself useful information.
  • Manual log — every strength session you log lifts CTL the next day. The Dashboard updates automatically.

Where things live

What Where
Your config ./openrun.toml (edit by hand any time)
Your data ./data/garmin.db (single SQLite file — back this up)
Garmin auth tokens ./.secrets/ (gitignored)
Logs / errors Wherever you ran openrun-web — stderr in that terminal
Notebooks (reference) ./examples/notebooks/

Resetting

Want to start over?

rm -rf data/ openrun.toml .secrets/
uv run openrun-web    # the wizard reappears

Nothing on this list touches anything outside the project directory.