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

205 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](https://github.com/astral-sh/uv)** — Python's package manager. Install:
```bash
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.
---
## Web app (recommended)
### 1. Get the code & install deps
```bash
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
```bash
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:
```bash
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:
```bash
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
```bash
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:
```bash
uv run openrun-web -- --server.port 8800
```
### "FIT file not at recorded path"
You moved your export folder after linking. Run:
```bash
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?
```bash
rm -rf data/ openrun.toml .secrets/
uv run openrun-web # the wizard reappears
```
Nothing on this list touches anything outside the project directory.