Health data CLI — ETL Apple Health & SleepCycle into DuckDB, generate AI narratives, and build interactive dashboards.
Project description
A CLI tool for managing personal health data from Apple Health and SleepCycle. Load data into a local DuckDB database, generate AI-powered health narratives with Claude, and build interactive static HTML dashboards — no database server required.
Features
vitalog load— Extract Apple Health XML exports and SleepCycle CSV data into a local DuckDB databasevitalog narrative— Generate AI-written health journal entries using Claude, with trend analysis and period-over-period comparisonsvitalog dashboard— Build self-contained static HTML dashboards with D3.js charts, Leaflet workout route maps, dark mode, and interactive tooltips
Installation
pip install vitalog
Or install from source with uv:
git clone https://github.com/geocoug/vitalog.git
cd vitalog
uv sync --all-extras
Usage
Load data
# Load an Apple Health export (ZIP from iPhone → Health → Export)
vitalog load apple --file data/export.zip
# Load SleepCycle app data (CSV export)
vitalog load sleep --file data/sleepdata.csv
# Load both at once
vitalog load all --apple data/export.zip --sleep data/sleepdata.csv
# Apple Health only (SleepCycle is optional)
vitalog load all --apple data/export.zip
Both commands write to vitalog.duckdb in the current directory by default. Override with --db path/to/file.duckdb.
Generate a health narrative
# Last week summary
vitalog narrative --period last-week
# Custom date range, saved to file
vitalog narrative --start 2025-01-01 --end 2025-03-31 --output q1-narrative.md
# Ask a specific question about your health data
vitalog narrative --question "How has my sleep quality changed?"
# Question with a specific time period
vitalog narrative --period last-month -q "Am I exercising enough?"
Set your profile (optional)
# Provide demographics for personalized health context in narratives
vitalog profile --age 35 --weight 175 --height 70 --sex male
# View current profile
vitalog profile --show
Demographics are stored in the DuckDB database and used to contextualize metrics in narratives (e.g., age-appropriate resting HR norms, BMI, VO2Max percentiles).
Generate a health narrative
Requires ANTHROPIC_API_KEY set in your environment or .env file.
Optionally set ANTHROPIC_MODEL to choose a specific Claude model (defaults to claude-sonnet-4-20250514).
Build a dashboard
# Last year dashboard (opens in browser)
vitalog dashboard --period last-year
# Custom range, no auto-open
vitalog dashboard --start 2024-01-01 --end 2024-12-31 --output 2024.html --no-open
Generates a self-contained HTML file with 20+ interactive charts across 6 tabs: Overview, Vitals, Sleep, Training, Activity, and Routes.
Data Sources
Apple Health Export
How to export: iPhone → Health app → profile icon → Export All Health Data → save ZIP file.
Expected format: A ZIP archive containing:
apple_health_export/export.xml— All health records, workouts, and activity summariesapple_health_export/workout-routes/*.gpx— GPS tracks for outdoor workouts
What gets extracted:
| Category | Metrics |
|---|---|
| Activity | Steps, flights climbed, walking speed, distance |
| Heart | Heart rate, resting HR, HRV, VO2Max |
| Body | SpO2, respiratory rate |
| Workouts | Type, duration, distance, running pace, power, cycling stats |
| Sleep | Apple Health sleep analysis (duration) |
| Activity Rings | Move, Exercise, Stand — values and goals |
| Routes | GPS trackpoints with elevation, speed, accuracy |
SleepCycle CSV
How to export: SleepCycle app → Profile → More → Database → Export Database → save CSV file.
Expected format: Semicolon-delimited CSV (;) with headers including:
Start;End;Sleep Quality;Regularity;Deep (seconds);Light (seconds);Dream (seconds);
Awake (seconds);Heart rate (bpm);Steps;...
What gets extracted: Sleep duration, quality percentage, stage breakdown (deep/light/REM/awake), heart rate, environmental data (air pressure, temperature, weather), and snore time.
What Gets Produced
DuckDB Database
A local vitalog.duckdb file with staging tables and analytical views:
| Table | Contents |
|---|---|
stg_records |
All Apple Health records (steps, HR, VO2Max, etc.) with a record_type discriminator |
stg_workouts |
Workout sessions (type, duration, distance) |
stg_activity_summary |
Daily activity ring data (move, exercise, stand) |
stg_workout_routes |
GPS trackpoints from workout GPX files |
stg_sleep_cycle |
SleepCycle app data |
Plus analytical views: daily_steps, daily_heart_rate, daily_resting_hr, daily_summary, workout_summary, sleep_combined.
Dashboard
A single self-contained HTML file (~700KB) with:
- 6 tabbed sections with 20+ interactive charts built with D3.js
- Summary cards with sparkline trends
- Personal records section
- Monthly summary table with conditional formatting
- Workout route maps with GPS tracks built with Leaflet
- Dark/light mode toggle
- Print-friendly CSS
Narrative
A markdown document with a 3-5 paragraph AI-generated health journal entry covering steps, heart rate, sleep, workouts, and activity rings — with trend analysis vs. the prior equivalent period.
Development
# Clone and install
git clone https://github.com/geocoug/vitalog.git
cd vitalog
uv sync --all-extras
# Run tests
just test
# Lint + format
just lint
# Run pre-commit hooks
just pre-commit
# See all available recipes
just
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vitalog-0.2.3.tar.gz.
File metadata
- Download URL: vitalog-0.2.3.tar.gz
- Upload date:
- Size: 192.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78cc3f5ab40ba17b42f871b92cd6fa90171d8f9bd96c3d829ffcd269e6a98023
|
|
| MD5 |
d93250795f35946108cbf03cd8c0e62f
|
|
| BLAKE2b-256 |
97a90f6b1cc0ca6bce59b7d605e41b7a5ee012c74e927a46a8d5ca65f7400f04
|
Provenance
The following attestation bundles were made for vitalog-0.2.3.tar.gz:
Publisher:
ci-cd.yml on geocoug/vitalog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vitalog-0.2.3.tar.gz -
Subject digest:
78cc3f5ab40ba17b42f871b92cd6fa90171d8f9bd96c3d829ffcd269e6a98023 - Sigstore transparency entry: 1189448370
- Sigstore integration time:
-
Permalink:
geocoug/vitalog@b209e3b5e685aee8a542e0e7b59c0f2f3dfc176b -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/geocoug
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@b209e3b5e685aee8a542e0e7b59c0f2f3dfc176b -
Trigger Event:
push
-
Statement type:
File details
Details for the file vitalog-0.2.3-py3-none-any.whl.
File metadata
- Download URL: vitalog-0.2.3-py3-none-any.whl
- Upload date:
- Size: 88.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3af16141baf9919f3637f8eb7cfa27b5bcd72910a440b00f510b63303fb3da77
|
|
| MD5 |
07a59d2fac3a84dcea924eeb134e3656
|
|
| BLAKE2b-256 |
6f2e789d29582ae6e9bf4f551d1bf6a89921a0f3840aaea7d60483912bf5123a
|
Provenance
The following attestation bundles were made for vitalog-0.2.3-py3-none-any.whl:
Publisher:
ci-cd.yml on geocoug/vitalog
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vitalog-0.2.3-py3-none-any.whl -
Subject digest:
3af16141baf9919f3637f8eb7cfa27b5bcd72910a440b00f510b63303fb3da77 - Sigstore transparency entry: 1189448375
- Sigstore integration time:
-
Permalink:
geocoug/vitalog@b209e3b5e685aee8a542e0e7b59c0f2f3dfc176b -
Branch / Tag:
refs/tags/v0.2.3 - Owner: https://github.com/geocoug
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@b209e3b5e685aee8a542e0e7b59c0f2f3dfc176b -
Trigger Event:
push
-
Statement type: