The reason nobody switches
There is no interchange format for a personal food diary. Not a neglected one, not a partial one. None at all.
Nobody experiences it as a missing specification. What they say is that they have years of data in a calorie tracker they stopped enjoying, and that leaving would mean starting over.
The export button is why. Every consumer tracker has one, and every one of them spits out a proprietary CSV that no other tracker will read. Different column names. Different units. Different ideas about what counts as a serving, and no shared way of saying which food was actually eaten. Migrating turns into a scripting job, so almost nobody migrates. The button exists to tick a compliance box.
Ours was no better. Burnin has always had an export, and for most of its life it produced a file only Burnin could read again. Writing the format was the part we had skipped.
We went looking for a format to adopt
Writing a specification is a bad idea when one already exists. We checked. None did.
Open mHealth and IEEE 1752 cover body weight, activity and sleep between them, across roughly 113 schemas. Neither has a schema for food.
HL7 FHIR has NutritionIntake. It was modelled on inpatient tray monitoring: a hospital recording what it served a patient. No consumer app implements it, and it does not describe a person logging their lunch.
Apple Health exports your nutrition data with no field for the name of the food. Calories survive. Macros survive. What you ate does not.
So the gap is real. Your own eating history, years of it, is about the least portable data you own.
What Onyx is
A specification for a personal diary of food and weight, plus a reference engine that reads, validates and migrates Onyx documents. The specification is at 1.0.0.
The rest of this is aimed at anyone who might implement it.
Three decisions.
The specification is public domain. Specification, conformance corpus, migration manifests, documentation: all CC0. The engine, the CLI and the language bindings are MIT or Apache-2.0. A format one company owns is a format its competitors will not build on. CC0 means nobody has to take that on trust.
Unknown fields must be ignored. Versioning is semver, and the obligations sit with the consumer. Refuse a major version you do not know. Accept any minor of a major you do know, ignoring fields you have never seen. That one rule is what lets the format grow without breaking anybody. Adding a field usually needs no change in the reader at all.
There is a conformance corpus. Documents that should pass, documents that should fail, in a form that does not care which language you implement in. A second implementation can demonstrate it is correct instead of claiming to be. Skip this and you get a specification everybody interprets slightly differently.
You can check a file without installing anything
npx @dsemakin/onyx validate diary.json
There are prebuilt binaries on GitHub for the usual platforms, if you would rather keep a runtime out of it altogether. A document that links to the schema also gets validation, autocomplete and hover docs in VS Code and the JetBrains IDEs, with nothing installed there either.
Governance
Onyx has one maintainer today. If you are weighing up whether to build on it, that is a risk, and you should price it in.
When a second implementer ships, Onyx moves to a neutral organisation and changes need agreement from more than one party.
Where it stands
The first implementation is Burnin, and it lands in the next release. The crates are not on crates.io yet.
What the format needs now is a second implementer. If you build a tracker and your users ask how to get their history out, the specification is public domain, the corpus will tell you whether you have read it correctly, and the issue tracker is open.