Project 3: Your HRV trend
**Goal:** your resting heart rate and heart rate variability (HRV) week by week, how this week compares, and, with an Apple Watch, the HRV of each recording computed from your own heartbeats.
Goal: your resting heart rate and heart rate variability (HRV) week by week, how this week compares, and, with an Apple Watch, the HRV of each recording computed from your own heartbeats.
Time: 15 minutes. Level: terminal. Needs: project 1, with a ring, a band or an Apple Watch.
1. The weekly trend
Day to day, resting heart rate and HRV jump around. Week by week, a trend shows.
python3 recipes/heart-trend.py --weeks 87 days to Resting HR HRV
Tue 22 Sep 54.0 bpm 53.0 ms
Tue 29 Sep 55.1 bpm 52.6 ms
Tue 06 Oct 53.6 bpm 57.7 ms
Tue 13 Oct 52.3 bpm 55.0 ms
Sources: resting HR from apple_health, HRV from apple_health (SDNN)
Last 7 days against the 3 weeks before: resting HR -2.0 bpm, HRV +1%A resting heart rate going up while HRV goes down often comes with short nights, stress, a hard training block or a cold on its way. It is a trend to notice, not a diagnosis.
One thing to know. Rings and bands usually report HRV as RMSSD, the Apple Watch as SDNN. They are two different measures on two different scales, so the recipe never mixes them and says which one it used. Compare yourself with yourself, on the same device.
2. HRV from your own heartbeats (Apple Watch)
When an Apple Watch takes an HRV reading, it also records the time between each of your heartbeats, and the Health export carries them. Open Health Sync keeps every one of those intervals and computes the standard measures from them, the same way every time:
set -a; . ~/.ohs.env; set +a
START=$(python3 -c 'import datetime as d; print(d.date.today() - d.timedelta(days=30))')
curl -s "$OHS_URL/v1/users/$OHS_USER/hrv?start=$START" -H "Authorization: Bearer $OHS_KEY" \
| jq -r '.data[] | "\(.start_date[:16]) RMSSD \(.rmssd_ms // "-") ms SDNN \(.sdnn_ms // "-") ms (\(.accepted_intervals) beats)"'2026-10-01T07:00 RMSSD 38.9 ms SDNN 41.207 ms (70 beats)
2026-10-02T07:01 RMSSD 44.2 ms SDNN 47.031 ms (68 beats)Now you have RMSSD from your watch too, so it can sit next to the figure a ring gives. A dash means the recording had too few clean beats to give a measure. How the beats are cleaned and counted is in RR intervals and HRV.
Make it yours
- Flag a week. Open
recipes/heart-trend.pyand print a!next to any week whose resting heart rate is 3 bpm or more above the average of the others. - A longer view.
--weeks 26shows half a year: you may see a training block, a holiday or a season. - Morning only. Keep the
/hrvrecordings that start before 9:00, when you are most comparable from one day to the next.
Share it
A screenshot of your trend, with or without the numbers, in Show and tell.
Project 2: Read your sleep
**Goal:** a report of your last two weeks of sleep in the terminal, then a script of your own, about twenty lines, that adds deep and REM sleep to it.
Project 4: Ask an AI about your training
**Goal:** an AI assistant such as Claude answering questions about your sleep, heart and training from your real numbers, through a token that can only read.