Skip to content

Apple Health Extraction ​

  owner: jimmy-neutron + zoro
  first_touched: 2026-05-26
  last_touched: 2026-05-26

Phase 1 Shipped — Export.xml Python ETL to Per-Category CSVs ​

source: documentation/activities/apple-health-phase1.md

Task #840054. Phase 1 (export.xml to Python ETL to per-category CSVs) is live. Phase 2 (Shortcut daily delta sync) and Phase 3 (Parquet + jimmy-vps webhook) deferred.

Files landed (Sandpit commit 877cc21) ​

  • ~/Sandpit/hinata/scripts/parse-apple-health.py — stdlib-only ElementTree.iterparse over export.xml. Streaming = memory-bounded; safe on 1-10GB exports. Per-HKType cursor in state.json = idempotent.

  • ~/Library/LaunchAgents/com.hinata.health-normaliser.plist — 03:15 daily. Not loaded yet.

Storage shape ​

~/Sandpit/hinata/data/health/
├── inbox/         drop export.zip or export.xml here
├── processed/     timestamped archive of consumed inputs
├── csv/
│   ├── activity/  steps, distance, active_energy, exercise_min, stand_hr, flights
│   ├── vitals/    heart_rate, resting_hr, hrv, spo2, respiratory_rate, vo2max, bp_*, body_temp
│   ├── sleep/     sleep_stages
│   ├── body/      weight, bmi, body_fat, lean_mass, height, waist
│   ├── mobility/  walking_asymmetry, double_support, step_length, walking_speed, stair_*
│   ├── nutrition/ calories, protein, carbs, fat, water, caffeine, sugar, fiber, sodium
│   ├── mindfulness/ meditation
│   ├── cardiac/   afib_events, high_hr_events, low_hr_events
│   ├── environmental/ headphone_exposure, noise_exposure
│   ├── workouts/  workouts (with totalEnergyBurned + totalDistance)
│   └── other/     any unmapped HKType (safety net)
├── state.json     cursor: {HKType: lastSeenStartDate}
└── parse-apple-health.log

Why stdlib-only ​

pandas + lxml would be cleaner code but add dependency installs to every Mac that runs the LaunchAgent. stdlib xml.etree.ElementTree.iterparse is sufficient and runs everywhere.

Verification path (Michael) ​

  1. iPhone Health profile picture → Export All Health Data → AirDrop export.zip to Mac

  2. Save to ~/Sandpit/hinata/data/health/inbox/

  3. python3 ~/Sandpit/hinata/scripts/parse-apple-health.py

  4. ls ~/Sandpit/hinata/data/health/csv/ → confirm categories

  5. launchctl load ~/Library/LaunchAgents/com.hinata.health-normaliser.plist

What this closes ​

* #840054 closure trigger met when verification step 5 runs without error

* #200009 (Zoro body-weight query) auto-resolves once csv/body/weight.csv exists

◆ hinata · apple-health-extraction · folded from documentation/activities/ phase-19