Personal health intelligence layer — ingesting WHOOP biometric data into a conversational knowledge graph.
Author: Jordan Rose (Rosevari)
Repo: jros-hermes-backup (private — this design doc is the public reference)
Status: Active development — nightly sync operational
JROS is a single-user, private health data pipeline that consumes WHOOP recovery, sleep, workout, and cycle data to populate a personal knowledge graph. The primary interface is conversational AI via Hermes Agent, not a traditional web dashboard.
- Automated daily health journaling — structured markdown pages with YAML frontmatter
- Longitudinal pattern detection — correlate recovery with subjective tags, travel, workload
- Conversational access — query years of health data via natural language
- Data ownership — portable, queryable archive outside the WHOOP app
┌─────────────────┐ OAuth 2.0 (read-only) ┌──────────────────┐
│ WHOOP API v2 │ ─────────────────────────────→ │ whoop_sync.py │
│ (developer.whoop.com) │ (Python 3.13) │
└─────────────────┘ └────────┬─────────┘
│ HTTPS
↓
┌─────────────────┐
│ gbrain CLI │
│ (Bun/TS) │
└────────┬────────┘
│ pg+vector
↓
┌─────────────────┐
│ Supabase │
│ (Postgres) │
│ 1,119+ pages │
└────────┬────────┘
│
↓
┌─────────────────┐
│ Hermes Agent │
│ (Telegram/CLI) │
└─────────────────┘
| Component | Tech | Role |
|---|---|---|
| WHOOP API | REST v2 | Source of truth for recovery, sleep, workout, cycle, body measurement |
| whoop_sync.py | Python 3.13, urllib | Pulls data, formats markdown, pipes to gbrain |
| gbrain | Bun/TypeScript CLI | Knowledge graph CLI — writes pages, manages chunks, embeddings, links |
| Supabase | Postgres + pgvector | Persistent brain store (private instance) |
| Hermes Agent | Python AI agent | Conversational interface — queries brain, synthesizes answers |
| Host | Private Linux VPS | Cron-scheduled, TLS-only, token-encrypted at rest |
A headless cron job runs whoop_sync.py:
- Authenticates with WHOOP via OAuth 2.0 bearer token
- Requests 6 read-only endpoints:
GET /v2/user/profile/basicGET /v2/user/measurement/bodyGET /v2/recovery?limit=1GET /v2/activity/sleep?limit=1GET /v2/activity/workout?limit=1GET /v2/cycle?limit=1
- Formats response as structured markdown with YAML frontmatter
- Pipes to
gbrain put concepts/whoop-daily-{YYYY-MM-DD}
gbrain processes the markdown:
- Chunks the page into searchable segments
- Embeds via
zeroentropyai:zembed-1(1280-dim vectors) - Auto-links to existing pages (e.g.,
concepts/value-equation,concepts/training-blocks) - Tags with
whoop,health,recovery,sleep,workout - Timelines the entry for date-based queries
When Jordan asks a health question, Hermes Agent:
- Issues
gbrain query "..."orgbrain get concepts/whoop-daily-YYYY-MM-DD - Receives ranked excerpts with relevance scores
- Synthesizes a natural language answer with context and trends
The UX is AI-native, not GUI-native. Jordan interacts entirely through Telegram DM and terminal CLI.
Querying a specific day:
User: "What was my recovery yesterday?"
Hermes: "Recovery score 47 — below your 30-day average of 62.
HRV was 65.8ms (low), resting HR 62bpm.
Sleep was 8h 42m but deep sleep was only 12%.
You had a 14-min walk as your only strain."
Longitudinal pattern detection:
User: "How does my HRV trend after long-haul flights?"
Hermes: "Across 8 travel days logged:
- Average HRV drops 18% day-of-flight
- Recovery score averages 51 vs. baseline 67
- Full recovery typically takes 2-3 days
- Best recovery hack so far: early sleep (+1.5hrs night before)"
Cross-domain correlation:
User: "Do heavy deadlift days tank my recovery?"
Hermes: "Last 6 heavy lower-body sessions:
- Next-day recovery avg: 58 (vs. 64 baseline)
- HRV suppressed for ~36 hours
- Sleep quality drops 8-12%
- But day-2 recovery often rebounds above baseline
Pattern: acute suppression, 48hr supercompensation."
Each sync creates a page like:
---
type: concept
title: WHOOP Daily Sync 2026-05-21
tags: [whoop, health, recovery, sleep, workout]
---
# WHOOP Daily Sync — 2026-05-21
**User:** Jordan Rose (jordan@rosevari.com)
**Body:** 178cm | 77kg | Max HR 189
## Latest Recovery
- **Score:** 47.0
- **Resting HR:** 62 bpm
- **HRV (RMSSD):** 65.8 ms
- **SpO2:** 96.4%
- **Skin Temp:** 36.85°C
## Latest Sleep
- **Start:** 2026-05-20T21:30:00+00:00
- **End:** 2026-05-21T06:12:00+00:00
- **In Bed:** 8h 42m
- **Awake:** 22m
- **Light Sleep:** 4h 18m
- **REM:** 2h 06m
- **Deep:** 1h 02m
## Latest Workout
- **Activity:** walking
- **Start:** 2026-05-21T07:15:00+00:00
- **Duration:** 14m
- **Strain:** 2.84
- **Avg HR:** 98 bpm
- **Max HR:** 115 bpm
- **Energy:** 142.3 kJ
## Daily Cycle
- **Strain:** 9.36
- **Energy:** 18714.6 kJ
- **Avg HR:** 68 bpm
- **Max HR:** 179 bpm
---
*Synced: 2026-05-21T08:00:00+00:00*
*Source: WHOOP API v2*| Control | Implementation |
|---|---|
| User scope | Single user only — no external sharing, no social features |
| API access | Read-only (6 scopes); zero write operations |
| Auth | OAuth 2.0 bearer token, encrypted at rest on private VPS |
| Transport | TLS 1.3 for all API and database traffic |
| Data residency | Private Supabase instance (not shared tenant) |
| Backup | Nightly git backup to private GitHub repo with .gitignore excluding tokens |
| Retention | Indefinite — user-owned archive |
| Layer | Tool | Version |
|---|---|---|
| Ingestion | Python + urllib | 3.13 |
| Scheduling | cron (Hermes cronjob) | — |
| Knowledge graph | gbrain CLI | 0.37.5 |
| Database | Supabase Postgres + pgvector | 15+ |
| Embeddings | zeroentropyai:zembed-1 | 1280-dim |
| AI interface | Hermes Agent | latest |
| Messaging | Telegram Bot API | — |
| Hosting | Private Linux VPS | Ubuntu 22.04 |
- OAuth 2.0 connection (all 6 read scopes)
- Nightly automated sync via cron
- Structured markdown ingest into knowledge graph
- Conversational retrieval via Hermes Agent
- Request refresh token support (production app approval)
- Weekly trend summaries (auto-generated via LLM)
- Anomaly alerting ("recovery dropped 2 std devs — check for illness/travel")
- Cross-reference with calendar/travel tags for causal inference
- Heart Rate Variability (HRV) rolling average dashboard (text-based)
Jordan Rose — jordan@rosevari.com
GitHub: @Rosevari