Jerem Flow

A data-driven personal coach, built from my own health data

· 3 mins read · #self-hosting #health #data #duckdb #dashboard #ai-agents #privacy

I wanted a coach that answers with my numbers, not generic advice. So I built one — a private pipeline that collects my training, nutrition and sleep data, and an agent that coaches from it. 🏋️

Why a data-driven coach

Generic fitness advice is everywhere. What's rare is advice grounded in your own data: your actual training volume, your real calorie balance, your sleep and resting heart rate over weeks. That's what I set out to build — a coach that looks at my numbers before it says anything.

Two constraints shaped everything:

  1. Private by design. 🛡️ Health data is the most sensitive data I own. It stays on my own machine — no third-party cloud, no analytics.
  2. Numbers, not vibes. Every answer must come from the data, never invented.

The sources: where the data comes from

I already track my training, food and health in apps I use daily, so the pipeline reads from them rather than asking me to log twice:

Source What it provides How it gets in
Hevy workouts, sets, exercises official API (pull)
MacroFactor calories, protein, targets weekly export
Apple Health weight, sleep, resting HR, steps weekly export
RingConn HRV, sleep detail via Apple Health

The exports land in a shared inbox folder and are picked up automatically — I don't have to do anything except keep using the apps I already use.

The pipeline: DuckDB as the single source of truth

All sources feed into one local DuckDB database. The key design decision was idempotent ingestion: each table has a unique key and uses INSERT OR REPLACE, so re-importing the same period overwrites rather than duplicates. Re-running a week's export is safe — no double counting.

Hevy API ─┐
MacroFactor ─┼─▶ inbox ─▶ DuckDB ─▶ KPIs ─▶ dashboard
Apple Health ─┘              │
                             └─▶ agent (coach)

A scheduled job runs each morning: pull the latest data, ingest what's new, and regenerate the dashboard. A file watcher catches exports that arrive during the day. Everything is incremental — adding a day takes seconds, not a full rebuild.

The dashboard

A lightweight, dark-themed web dashboard shows the KPIs that matter: weekly calorie balance, protein vs target, training volume, sleep, resting heart rate, and weight trend. It's a static page regenerated from the data — no database exposed to the browser, no analytics, served from my own machine.

The coach: an agent that reads the numbers

The most interesting piece: an agent that combines the data with sensible coaching rules. When I ask it a question — "why is my weight stuck?", "how's my protein this week?" — it queries the database first, then answers with the real figures.

The rules it applies are the ones a good coach would:

  • Judge weight on the weekly average, not a single day's reading (daily weight is noise — water and glycogen swing ±1-2 kg).
  • When progress stalls, look for the leak before cutting calories: unlogged days, sleep under 7 h, protein too low.
  • Never invent a number, and never give a medical diagnosis — red flags go to a doctor.

The model proposes, the data decides. The agent is a coach with a spreadsheet, not a fortune teller.

Why this approach works

  • It's mine. The data never leaves my machine.
  • It's automatic. I keep using the apps I already use; the pipeline does the rest.
  • It's honest. Answers are grounded in real numbers, and the coaching rules are explicit and adjustable.
  • It's cheap. DuckDB, a static dashboard and a local agent — no per-seat SaaS, no data subscription.

In short

A private, data-driven coach: my training, nutrition and sleep data flow into a local DuckDB, a dashboard makes it visible, and an agent coaches from the real numbers. The payoff: advice that's about me, not about everyone — private, automatic, and grounded in data.

See also: Giving Hermes a headless browser (and a VPN) for the web — the same self-hosted, privacy-first approach applied to browsing.

← Back