A history longer than the phone’s
HealthKit keeps everything, but only as long as you keep the device and the backup chain intact. A server gives you a second, queryable copy that you control, with compression and no retention policy.
Local-first · MIT licensed
The Helsa app reads HealthKit on your iPhone, does its analysis on the device, and by default your health data never leaves the phone. Sending it anywhere is a switch you turn on — and when you do, you type in your own endpoint. This is the server that endpoint can point at.
Go API · ingestion worker · TimescaleDB · web dashboard · deployment recipe. Fork it, or replace it with your own that speaks the same API contract.
Helsa is not on the App Store yet. The iPhone app is in a TestFlight round — invitation only, and the invitations go to people the author already knows. There is no public link, and this site is not one.
What you can use today is the server: it is MIT licensed, it is documented here, and its API contract is the thing to implement if you would rather write your own client. The contract can still move while the app is in testing; a breaking change is described in the commit that makes it, because nobody outside depends on a deprecation window yet.
Helsa is a hobby project for looking at your own fitness data. It is not a medical device, it is not for diagnosis, treatment, or monitoring of any medical condition, and its output must not be used to make health decisions. It comes with no warranty of any kind. See the full disclaimer.
On the phone
Everything below runs on the device: 120 metrics, sleep stages, workouts, hydration, and a journal of what you felt at the time. The screenshots are taken from the running app, and the person in them does not exist.



What it is
Always
HealthKitanalysiswhat you see
HealthKit is the store and the analysis runs on the device. This works fully offline, with no server at all.
Optional, opt-in, and you type the URL. Mutual TLS plus a device token.
Only if you want it
CaddyAPIRabbitMQworkerTimescaleDB
Long-term history, a web dashboard on your LAN or VPN, exports, and daily summaries for Home Assistant.
The phone is the only writer. Every other surface — the web dashboard, an iPad, Home Assistant — reads from the server. That asymmetry is not a preference: HealthKit has no cloud API, so the device holding the data is the only thing that can upload it.
Why you might want it
HealthKit keeps everything, but only as long as you keep the device and the backup chain intact. A server gives you a second, queryable copy that you control, with compression and no retention policy.
Apple Health is an iPhone app. There is no official web view of your own data. The dashboard here is one.
Daily summaries into Home Assistant over MQTT, with discovery — including the sync-freshness sensor that tells you when the pipeline has quietly stopped.
It is a Postgres database with your data in it. Ask it whatever you want.
Why you might not
If you just want to look at your numbers on your phone, you do not need any of it. Run the app without a server. That is the intended default, and the project is built so that the default is the complete experience for a single device.
Running a server means running a server: TLS certificates that expire, backups that must be tested, a port on your router, and a database that is now your responsibility. The rest of these pages are honest about that cost.
Boundaries
Where to go next
Bring the stack up locally with Docker Compose, issue a device token, verify a first sync. Nothing is exposed to the internet.
TLS, mutual TLS with a private CA, the reverse proxy, backups and restore, and a hardening checklist. Read before you open a port.
The contract: what /v1/ingest accepts, what the read endpoints return, and the conventions — UTC, SI units, cursors — that apply everywhere.
Home Assistant over MQTT with discovery, plus a REST fallback. Daily summaries only, and the page explains why that limit matters.
The OpenAPI document in backend/api/openapi.yaml is the source of truth; the server, the app and the web client all generate from it. It is now a public interface, so breaking changes have a cost — but the version is 0.x and the project is one person’s hobby. Pin what you depend on.