healthsync

Parse Apple Health exports into a local SQLite database.
Query from the CLI, serve over HTTP, or sync from iPhone via Tailscale.

$ go install github.com/BRO3886/healthsync@latest

$ healthsync parse export.zip
Parsed 540,110 records and 1,011 workouts in 30.6s

$ healthsync query heart-rate --limit 3
┌────────┬───────┬─────────────────────────┐
│ Source │ BPM   │ Date                    │
├────────┼───────┼─────────────────────────┤
│ Watch  │ 72    │ 2026-02-12 19:11:31     │
│ Watch  │ 68    │ 2026-02-12 19:06:22     │
│ Watch  │ 75    │ 2026-02-12 18:58:14     │
└────────┴───────┴─────────────────────────┘

$ healthsync query steps --from 2024-01-01 --format json
$ healthsync query workouts --format csv
$ healthsync server --port 8080

What it does

  • Parses .zip or .xml Apple Health exports via streaming XML (constant ~10MB memory)
  • Stores records in ~/.healthsync/healthsync.db (SQLite, WAL mode, deduplication via INSERT OR IGNORE)
  • Queries 6 metrics: heart rate, steps, SpO2, VO2 Max, sleep, workouts
  • Output as table, JSON, or CSV with date range filters
  • HTTP server with async upload (202 Accepted + progress polling) for Tailscale workflows
  • Single binary, zero CGO dependencies (modernc.org/sqlite)

Quick start

  1. Install
    go install github.com/BRO3886/healthsync@latest
  2. Export from iPhone

    Health app → Profile → Export All Health Data → save the .zip

  3. Parse
    healthsync parse export.zip -v
  4. Query
    healthsync query heart-rate --limit 10
    healthsync query steps --from 2024-01-01 --format json

How it works

ParserStreaming XML with DTD stripping via io.Pipe. Handles 500k+ records in ~30s.
StoragePure Go SQLite. WAL mode, batch inserts (1000/tx), UNIQUE constraints for dedup.
ServerChi router. POST /api/upload returns 202, parses async, poll GET /api/upload/status.
CLICobra. parse, query, server subcommands. --db, --format, --from/--to flags.