A personalised migraine early-warning you train on your own Apple Health export.
It learns, from your data, a two-phase physiological pattern that tends to precede your logged headaches, and gives you a simple three-stage daily status.
⚕️ Not a medical device. This is a hobby / self-tracking tool. It does not diagnose, treat, or predict disease and is not a substitute for professional medical advice. Its accuracy is modest and has not been validated beyond the single dataset it was developed on. Treat it as a gentle self-awareness nudge — nothing more. If you have migraines, talk to a doctor.
- GUIDE.md — the full walkthrough: prerequisites, install, exporting your Health data, what the numbers mean, troubleshooting every error message, how the algorithm works, and the peer-reviewed literature behind its assumptions. Start here if you've not used a terminal much.
- AGENTS.md — context for AI assistants. Hand this to Claude, Copilot, Cursor or similar and it can explain the project, walk you through setup, interpret your output, or help you extend it.
From your daily Apple Health signals it computes two scores and maps them to a stage:
- LOAD (a "run-up", ~3–5 days out): respiratory rate up, more activity/daylight, HRV starting to dip.
- CRASH (the last ~48 h): an autonomic "come-down" — heart rate below your baseline, more light (core) sleep, HRV rebounding.
| Stage | Meaning |
|---|---|
Life is good |
no pattern |
⚠️ Stage 1 |
early load pattern — keep an eye on it |
🚨 Critical |
48-h pre-migraine pattern — reduce stress, protect sleep |
No one's physiology is baked in. On your data the tool:
- auto-detects which signals your export contains (HRV, resting HR, respiratory rate, sleep stages, activity, daylight …) and uses whichever it finds;
- auto-detects when your wearable era starts;
- standardises every signal against your own rolling baseline;
- calibrates its alert thresholds from your own no-headache days.
The only fixed part is the direction of each signal (a physiologically-motivated
prior you can read and edit at the top of migraine_forecast.py).
git clone https://github.com/<you>/migraine-forecast.git
cd migraine-forecast
./install.sh # makes a .venv and installs numpy + pandasOr manually: python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/python migraine_forecast.py demo
.venv/bin/python migraine_forecast.py train
.venv/bin/python migraine_forecast.py check- Export on iPhone: Health app → your profile photo → Export All Health Data
→ you get
export.zip. Move it to your computer. - Point the tool at it — copy
config.example.jsontoconfig.jsonand set theexportpath, or just pass--export:.venv/bin/python migraine_forecast.py preprocess --export /path/to/export.zip .venv/bin/python migraine_forecast.py train .venv/bin/python migraine_forecast.py check
- Keep it fresh — each time you re-export,
updateingests only the new days and retrains, so it improves over time:.venv/bin/python migraine_forecast.py update --export /path/to/new_export.zip
The 800 MB+ export.xml is streamed straight out of the zip and collapsed into a
tiny daily table in seconds — the raw file is never extracted or re-read.
- An Apple Watch (heart rate, HRV, sleep, respiratory rate) — the more signals, the better; it degrades gracefully if some are missing.
- Your headache labels. Log headaches in Health (Symptoms → Headache), or pass
your own log with
--headaches yourlog.csv(a CSV with adatecolumn). - Enough history — several months with a handful of logged attacks. With very few attacks the model is weak and will say so.
Run ./run.sh (it asks y/N, then preprocesses + retrains if an export is configured
and prints your stage). On macOS you can rename it to run.command and add it to
System Settings → Login Items to be asked each morning.
Everything runs locally. Your export, the cached daily table, the model, and the
alert log all live in data/, which is git-ignored — nothing personal is committed
or uploaded. Only code goes to GitHub.
- Modest, unvalidated accuracy. It was developed on a single individual's data; held-out performance there was a small lift, not a reliable predictor. It has not been tested in a cohort, and yours may differ.
- Correlational, not causal. Many attacks have no health-data signal at all (e.g. weather/hormonal/dietary triggers). The tool can't catch those.
- Cold start is weak — it needs your labelled attacks to personalise.
- Not medical advice. See the disclaimer above.
Per day, the raw signals become z-scores against your rolling baseline, combined
(with fixed signs) into a LOAD component and a CRASH component; LOAD is averaged over
days −5..−2 and CRASH over the last 48 h. Thresholds are percentiles of your
no-headache score distribution. Evaluation uses a time-based hold-out (train on the
earlier part, test on the most recent). python migraine_forecast.py explain prints
the full rationale.
Issues and PRs welcome — especially: learning per-user signal directions (not just magnitudes), Android/Google Fit and Garmin importers, and better handling of sparse data. Please don't commit any personal health data.
Thanks to Claudia, who helped design and write this algorithm.
MIT — see LICENSE.