惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
aimingoo的专栏
aimingoo的专栏
IT之家
IT之家
G
Google Developers Blog
爱范儿
爱范儿
博客园 - 司徒正美
Recent Announcements
Recent Announcements
The Register - Security
The Register - Security
J
Java Code Geeks
The Cloudflare Blog
M
MIT News - Artificial intelligence
Apple Machine Learning Research
Apple Machine Learning Research
Microsoft Security Blog
Microsoft Security Blog
博客园 - Franky
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
Vercel News
Vercel News
宝玉的分享
宝玉的分享
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
B
Blog
小众软件
小众软件
Microsoft Azure Blog
Microsoft Azure Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
WordPress大学
WordPress大学
T
Troy Hunt's Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Hacker News: Front Page
H
Help Net Security
S
Security @ Cisco Blogs
V
V2EX
Security Archives - TechRepublic
Security Archives - TechRepublic
Stack Overflow Blog
Stack Overflow Blog
O
OpenAI News
L
LINUX DO - 最新话题
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
S
Secure Thoughts
Help Net Security
Help Net Security
F
Full Disclosure
博客园 - 叶小钗
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Jina AI
Jina AI
K
Kaspersky official blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
Vulnerabilities – Threatpost
P
Privacy International News Feed
Scott Helme
Scott Helme

jonno.nz

Ukraine’s Drone Advantage Is an Engineering Loop — jonno.nz Prove the Machine Wrong — jonno.nz I Parsed Every Law New Zealand Has Ever Passed — jonno.nz Your Show HN dies in 7 hours — jonno.nz The Fastest Repealers in the West — jonno.nz Six Years, $228 Million, Zero Metres of Track The holes that kill you are the ones you never tested What Happens When a Worm Drives Claude? The Laws of Human Nature Conscious Minimalism The dent and the crater I Built a Read-Later Chrome Extension Because Pocket Died Product market fit isn't a stage, it's a gauntlet Change management Three Ways to Look at Time What an hour of your attention is worth Teaching a Neural Network to Watch Crime Like Video Open-Source Agent That Teaches Claude Code Your Architecture Claude Code Can Now Spawn Copies of Itself in Isolated VMs The Future of Security Is an Open-Source Model That Detects and Acts on Threats I Spent 29 Hours Debugging iptables to Boot VMs in 4 Seconds Can You Beat Last Month? Claude Code Running Claude Code in 4-Second Disposable VMs Stealing NanoClaw Patterns for Web Apps and SaaS What if your browser built the UI for you? — jonno.nz What the Data Actually Shows How I Built an SMS Gateway with a $20 Android Phone
OpenHealth – Chat with Apple Health Data, Anywhere
John Gregoriadis · 2026-04-13 · via jonno.nz

I built OpenHealth because Claude's and ChatGPT's Apple Health connectors are US-only. Drop your export.zip, get seven markdown files any LLM can read — browser, CLI, or phone-to-desktop over WebRTC.

For years I've worn an Apple Watch and let my iPhone quietly hoover up my resting heart rate, HRV, sleep stages, every workout, every nutrition log. Millions of data points. And for most of that time, when I wanted to actually ask something about my training — "am I cooked this week?", "has my recovery gotten worse since Christmas?" — I'd open ChatGPT and get an answer that was basically vibes, because it couldn't see any of the data.

So I built openhealth. It turns your Apple Health export into seven short markdown files any LLM can read. Drop the zip in your browser at openhealth-axd.pages.dev, run the CLI, or beam the zip straight from your iPhone over WebRTC. Paste the output into Claude or ChatGPT and start asking the questions you actually wanted to ask.

openhealth's web app — drop the zip, get seven markdown files, nothing uploaded

What's US-only and why that's annoying

In January, Anthropic shipped an Apple Health connector for Claude. OpenAI has one in ChatGPT. Both are US-only — if you're in New Zealand like me, or the UK, EU, or Switzerland, they're not available. That's a lot of people locked out of the most natural way to use this data.

And even if you are in the US, you're letting Anthropic or OpenAI decide what the model reads, how it's framed, and what tier unlocks it. I wanted control over the whole pipeline — including which LLM I feed it into.

What I built

openhealth ships three ways.

A static web app. Drop export.zip, wait five seconds, download seven files. The browser does the parse. There's no upload endpoint because there's no server — the Cloudflare Pages site is static HTML plus a tiny Web Worker. Open DevTools, watch the Network panel, nothing goes out.

A Bun-compiled CLI. openhealth ~/export.zip -o ./output gets you seven markdown files. --bundle concatenates them into one. --clipboard pushes that bundle straight to your system clipboard so you can paste it into any chat window. Zero deps beyond saxes for XML and fflate for unzip — even the argument parsing is node:util parseArgs, not Commander. One binary, put it wherever.

A phone-to-desktop handoff over WebRTC. The desktop site renders a QR code. Point your iPhone camera at it, Safari opens a tiny receiver page, pick the zip, and it streams directly to your desktop browser over a DataChannel. The only backend in the whole stack is a ~100-line Cloudflare Worker that relays the WebRTC handshake — it never sees a byte of your health data.

Getting the export off your iPhone — six taps, or scan the desktop QR

How the parse actually works

Apple's export.xml is properly huge. A long-term Watch user can easily have a 500MB–4GB file with millions of rows. Most XML parsers build a tree in memory, which OOMs before they finish.

openhealth uses saxes — a streaming SAX parser in pure TypeScript. It's isomorphic, so the same parser runs in Bun, Node, and the browser. I tested it against a synthetic 169MB / 1 million-record export and it finished in about 5 seconds in Chrome, with the main-thread heap staying around 5MB because the parse runs in a Web Worker.

The rest of the core is a small pipeline: stream XML, accumulate per-record-type, roll up into weekly and monthly summaries, run each through a writer that produces one markdown file. Every writer is snapshot-tested against byte-for-byte expected output. 85 tests, TDD throughout.

What the seven files are

Each one is deliberately small and shaped to be LLM-readable:

  • health_profile.md — baselines, data sources, long-term averages
  • weekly_summary.md — current week plus a 4-week rolling comparison with week-over-week deltas
  • workouts.md — detailed log for the last 4 weeks: HR, duration, distance, energy
  • body_composition.md — weight trend, recent readings, nutrition averages
  • sleep_recovery.md — nightly stages, 8-week averages, HRV, resting HR, SpO2 trends
  • cardio_fitness.md — running log, HR-zone distribution, walking-speed trends
  • prompt.md — a ready-to-paste system prompt that frames the other six as coaching input

Drop one file or all seven, depending on which chat model you're using.

What it's actually good at

Feeding real data to an LLM is a different experience from answering its questions. When Claude can see that my resting HR has crept up 4bpm over the last fortnight while my HRV has dropped and my training load stayed the same, it gives a real answer — "you're likely undercooked on recovery this week, here's what I'd change" — rather than a generic reminder to drink water.

It's especially good if you've got multiple devices in the mix. I've got data from Apple Watch, the iPhone step counter, a Withings scale, and MyFitnessPal. The parser picks the highest-trust source per metric — Apple Watch wins over iPhone for steps, Watch sleep beats AutoSleep which beats Withings, duplicate-weight entries on the same day get deduped. You feed in one zip and get one coherent picture.

Ask it about your recovery, your training load, what you might be doing wrong, how your sleep correlates with your long runs. It'll tell you — and it'll be right more often than not.

If privacy matters, go all the way

openhealth itself never uploads your data. The web app parses in your browser tab. The CLI runs locally. The WebRTC handoff stays peer-to-peer — the Cloudflare Worker that relays the handshake never sees a byte of the file. Clone the repo, diff the build output, and confirm it yourself.

When you paste the seven files into ChatGPT or Claude, they see the data. That's the trade most people will take for convenience, and it's fine. But if you don't want to make that trade, you don't have to — run the CLI and pipe the bundle into a local model:

openhealth ~/export.zip --bundle -o ./out
ollama run llama3 < ./out/openhealth.md

Ollama, llama.cpp, LM Studio, whatever you run. Your health data never leaves your laptop. The output is just markdown — it doesn't care what reads it.

That's why the shape is seven files and not an API. You pick what sees them.

I'm not a doctor. Neither is the model. Use this for thinking out loud about your own training, not diagnosing anything.

MIT, source at github.com/jonnonz1/openhealth. Web app at openhealth-axd.pages.dev. If you've been sitting on a 200MB export.zip with nothing that'll open it, have a go.